diff --git a/tests/smoke/axe/axe-exit-codes.test.ts b/tests/smoke/axe/axe-exit-codes.test.ts
index ebadd870c0e..89e6e69b771 100644
--- a/tests/smoke/axe/axe-exit-codes.test.ts
+++ b/tests/smoke/axe/axe-exit-codes.test.ts
@@ -21,19 +21,20 @@ import { existsSync } from "../../../src/deno_ral/fs.ts";
import { join } from "../../../src/deno_ral/path.ts";
import { execProcess } from "../../../src/core/process.ts";
import { unitTest } from "../../test.ts";
+import { writeFixture } from "../../utils.ts";
import { quartoDevBinCmd, quartoSpawnEnvOptions } from "../../quarto-cmd.ts";
import { AxeFindings } from "../../../src/command/call/axe/schemas.ts";
const workingDir = Deno.makeTempDirSync({ prefix: "quarto-axe-exit" });
-Deno.mkdirSync(join(workingDir, "site"));
-Deno.writeTextFileSync(
- join(workingDir, "site", "index.html"),
+writeFixture(
+ workingDir,
+ "site/index.html",
`
exit codes
Exit codes
`,
);
-Deno.writeTextFileSync(join(workingDir, "site", "dot.png"), "not-really-a-png");
+writeFixture(workingDir, "site/dot.png", "not-really-a-png");
function findings(): AxeFindings {
return JSON.parse(
@@ -158,10 +159,8 @@ unitTest(
const notABrowser = join(workingDir, "not-a-browser");
Deno.writeTextFileSync(notABrowser, "");
// a previous scan's summary must not survive to be read as current
- const artifacts = join(workingDir, "_axe-checks");
- Deno.mkdirSync(artifacts, { recursive: true });
- const staleFindings = join(artifacts, "findings.json");
- Deno.writeTextFileSync(staleFindings, `{"stale": true}`);
+ writeFixture(workingDir, "_axe-checks/findings.json", `{"stale": true}`);
+ const staleFindings = join(workingDir, "_axe-checks", "findings.json");
const result = await execProcess({
cmd: quartoDevBinCmd(),
diff --git a/tests/smoke/check/check-info-project.test.ts b/tests/smoke/check/check-info-project.test.ts
index 2ddfe37b67a..58d4afcc431 100644
--- a/tests/smoke/check/check-info-project.test.ts
+++ b/tests/smoke/check/check-info-project.test.ts
@@ -9,6 +9,7 @@
*/
import { dirname, join, resolve } from "../../../src/deno_ral/path.ts";
+import { writeDefaultProject } from "../../utils.ts";
import { execProcess } from "../../../src/core/process.ts";
import { originalRealPathSync } from "../../../src/deno_ral/original-real-path.ts";
import { isWindows } from "../../../src/deno_ral/platform.ts";
@@ -30,7 +31,7 @@ function tempDir(prefix: string): string {
// The tree must exist at registration: the harness enters `cwd` before setup.
function tempProject(): string {
const dir = tempDir("quarto-check-info-project");
- Deno.writeTextFileSync(join(dir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(dir);
Deno.mkdirSync(join(dir, "sub"));
return dir;
}
diff --git a/tests/smoke/check/check-project-config-only.test.ts b/tests/smoke/check/check-project-config-only.test.ts
index bcefe567d36..78a84be3f1a 100644
--- a/tests/smoke/check/check-project-config-only.test.ts
+++ b/tests/smoke/check/check-project-config-only.test.ts
@@ -15,6 +15,7 @@ import {
makeUnreadableDir,
removeProject,
tempProject,
+ writeFixture,
} from "../../utils.ts";
import { assert, assertEquals } from "testing/asserts";
@@ -23,8 +24,7 @@ import { assert, assertEquals } from "testing/asserts";
if (canMakeUnreadableDir) {
const projectDir = tempProject("quarto-check-project");
const locked = join(projectDir, "locked");
- Deno.mkdirSync(locked);
- Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
+ writeFixture(projectDir, "locked/doc.qmd", "# Locked\n");
const output = join(projectDir, "check-info.json");
let restore: (() => void) | undefined;
testQuartoCmdJson(
diff --git a/tests/smoke/check/check-render-temp-in-project.test.ts b/tests/smoke/check/check-render-temp-in-project.test.ts
index bc6985b3c51..d7dc17ead91 100644
--- a/tests/smoke/check/check-render-temp-in-project.test.ts
+++ b/tests/smoke/check/check-render-temp-in-project.test.ts
@@ -21,6 +21,7 @@ import {
canMakeUnreadableDir,
makeUnreadableDir,
tempProject,
+ writeFixture,
} from "../../utils.ts";
import { checkRender } from "../../../src/command/check/check-render.ts";
import { renderServices } from "../../../src/command/render/render-services.ts";
@@ -36,8 +37,7 @@ unitTest(
async () => {
const projectDir = tempProject("quarto-check-render-temp");
const locked = join(projectDir, "locked");
- Deno.mkdirSync(locked);
- Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
+ writeFixture(projectDir, "locked/doc.qmd", "# Locked\n");
const tmp = join(projectDir, "tmp");
Deno.mkdirSync(tmp);
const restore = makeUnreadableDir(locked);
@@ -72,8 +72,7 @@ unitTest(
await initYamlIntelligenceResourcesFromFilesystem();
const projectDir = tempProject("quarto-check-render-temp");
const locked = join(projectDir, "locked");
- Deno.mkdirSync(locked);
- Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
+ writeFixture(projectDir, "locked/doc.qmd", "# Locked\n");
const restore = makeUnreadableDir(locked);
const services = {
...renderServices(notebookContext()),
diff --git a/tests/smoke/project/project-unreadable-dir.test.ts b/tests/smoke/project/project-unreadable-dir.test.ts
index 7dcd9c6eacc..49eb48501db 100644
--- a/tests/smoke/project/project-unreadable-dir.test.ts
+++ b/tests/smoke/project/project-unreadable-dir.test.ts
@@ -16,6 +16,7 @@ import {
makeUnreadableDir,
removeProject,
tempProject,
+ writeFixture,
} from "../../utils.ts";
import { assert, assertEquals } from "testing/asserts";
@@ -42,11 +43,10 @@ function registerUnreadableDirTest(
) {
const root = normalizePath(tempProject("quarto-unreadable-project"));
if (quartoYml) {
- Deno.writeTextFileSync(join(root, "_quarto.yml"), quartoYml);
+ writeFixture(root, "_quarto.yml", quartoYml);
}
const locked = join(root, "locked");
- Deno.mkdirSync(locked);
- Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
+ writeFixture(root, "locked/doc.qmd", "# Locked\n");
let restore: (() => void) | undefined;
testQuartoCmd(cmd, ["index.qmd"], [verify(root, locked)], {
cwd: () => join(root, "sub"),
diff --git a/tests/smoke/use/brand.test.ts b/tests/smoke/use/brand.test.ts
index 1e21348674d..dea5240f1e7 100644
--- a/tests/smoke/use/brand.test.ts
+++ b/tests/smoke/use/brand.test.ts
@@ -1,6 +1,7 @@
import { testQuartoCmd, ExecuteOutput, Verify } from "../../test.ts";
import { fileExists, folderExists, noErrorsOrWarnings, printsMessage } from "../../verify.ts";
import { join, fromFileUrl, dirname } from "../../../src/deno_ral/path.ts";
+import { writeDefaultProject, writeFixture } from "../../utils.ts";
import { ensureDirSync, existsSync } from "../../../src/deno_ral/fs.ts";
import { pathWithForwardSlashes } from "../../../src/core/path.ts";
@@ -90,7 +91,7 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(basicDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(basicDir);
return Promise.resolve();
},
cwd: () => basicDir,
@@ -137,7 +138,7 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(dryRunDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(dryRunDir);
return Promise.resolve();
},
cwd: () => dryRunDir,
@@ -188,14 +189,12 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(forceOverwriteDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(forceOverwriteDir);
// Create existing _brand directory with files
- const brandDir = join(forceOverwriteDir, "_brand");
- ensureDirSync(brandDir);
// This file exists in source - should be overwritten
- Deno.writeTextFileSync(join(brandDir, "_brand.yml"), "meta:\n name: Old Brand\n");
+ writeFixture(forceOverwriteDir, "_brand/_brand.yml", "meta:\n name: Old Brand\n");
// This file does NOT exist in source - should be preserved
- Deno.writeTextFileSync(join(brandDir, "unrelated.txt"), "keep me");
+ writeFixture(forceOverwriteDir, "_brand/unrelated.txt", "keep me");
return Promise.resolve();
},
cwd: () => forceOverwriteDir,
@@ -257,12 +256,10 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(dryRunOverwriteDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(dryRunOverwriteDir);
// Create existing _brand directory with _brand.yml and extra.txt (not logo.png)
- const brandDir = join(dryRunOverwriteDir, "_brand");
- ensureDirSync(brandDir);
- Deno.writeTextFileSync(join(brandDir, "_brand.yml"), "meta:\n name: Old Brand\n");
- Deno.writeTextFileSync(join(brandDir, "extra.txt"), "extra file not in source");
+ writeFixture(dryRunOverwriteDir, "_brand/_brand.yml", "meta:\n name: Old Brand\n");
+ writeFixture(dryRunOverwriteDir, "_brand/extra.txt", "extra file not in source");
return Promise.resolve();
},
cwd: () => dryRunOverwriteDir,
@@ -285,7 +282,7 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(errorFlagDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(errorFlagDir);
return Promise.resolve();
},
cwd: () => errorFlagDir,
@@ -336,7 +333,7 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(multiFileDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(multiFileDir);
return Promise.resolve();
},
cwd: () => multiFileDir,
@@ -384,7 +381,7 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(nestedDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(nestedDir);
return Promise.resolve();
},
cwd: () => nestedDir,
@@ -464,14 +461,12 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(nestedOverwriteDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(nestedOverwriteDir);
// Create existing _brand/images directory with files
- const imagesDir = join(nestedOverwriteDir, "_brand", "images");
- ensureDirSync(imagesDir);
// This file exists in source - should be overwritten
- Deno.writeTextFileSync(join(imagesDir, "logo.png"), "old logo\n");
+ writeFixture(nestedOverwriteDir, "_brand/images/logo.png", "old logo\n");
// This file does NOT exist in source - should be preserved
- Deno.writeTextFileSync(join(imagesDir, "unrelated.png"), "keep me nested");
+ writeFixture(nestedOverwriteDir, "_brand/images/unrelated.png", "keep me nested");
return Promise.resolve();
},
cwd: () => nestedOverwriteDir,
@@ -521,13 +516,11 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(dryRunNestedDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(dryRunNestedDir);
// Create existing _brand/images directory with only logo.png (not header.png)
- const imagesDir = join(dryRunNestedDir, "_brand", "images");
- ensureDirSync(imagesDir);
- Deno.writeTextFileSync(join(imagesDir, "logo.png"), "old logo\n");
+ writeFixture(dryRunNestedDir, "_brand/images/logo.png", "old logo\n");
// Also create _brand.yml so we're only testing nested behavior
- Deno.writeTextFileSync(join(dryRunNestedDir, "_brand", "_brand.yml"), "meta:\n name: Old\n");
+ writeFixture(dryRunNestedDir, "_brand/_brand.yml", "meta:\n name: Old\n");
return Promise.resolve();
},
cwd: () => dryRunNestedDir,
@@ -565,11 +558,9 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(nestedNewSubdirDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(nestedNewSubdirDir);
// Create _brand/ but NOT images/ subdirectory
- const brandDir = join(nestedNewSubdirDir, "_brand");
- ensureDirSync(brandDir);
- Deno.writeTextFileSync(join(brandDir, "_brand.yml"), "meta:\n name: Old Brand\n");
+ writeFixture(nestedNewSubdirDir, "_brand/_brand.yml", "meta:\n name: Old Brand\n");
return Promise.resolve();
},
cwd: () => nestedNewSubdirDir,
@@ -610,11 +601,9 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(dryRunNewSubdirDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(dryRunNewSubdirDir);
// Create _brand/ but NOT images/ subdirectory
- const brandDir = join(dryRunNewSubdirDir, "_brand");
- ensureDirSync(brandDir);
- Deno.writeTextFileSync(join(brandDir, "_brand.yml"), "meta:\n name: Old\n");
+ writeFixture(dryRunNewSubdirDir, "_brand/_brand.yml", "meta:\n name: Old\n");
return Promise.resolve();
},
cwd: () => dryRunNewSubdirDir,
@@ -659,11 +648,9 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(emptyDirCleanupDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(emptyDirCleanupDir);
// Create _brand/extras/ with a file not in source
- const extrasDir = join(emptyDirCleanupDir, "_brand", "extras");
- ensureDirSync(extrasDir);
- Deno.writeTextFileSync(join(extrasDir, "orphan.txt"), "this file will be removed");
+ writeFixture(emptyDirCleanupDir, "_brand/extras/orphan.txt", "this file will be removed");
return Promise.resolve();
},
cwd: () => emptyDirCleanupDir,
@@ -708,11 +695,9 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(deepNestedCleanupDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(deepNestedCleanupDir);
// Create _brand/deep/nested/path/ with a file not in source
- const deepDir = join(deepNestedCleanupDir, "_brand", "deep", "nested", "path");
- ensureDirSync(deepDir);
- Deno.writeTextFileSync(join(deepDir, "orphan.txt"), "deeply nested orphan");
+ writeFixture(deepNestedCleanupDir, "_brand/deep/nested/path/orphan.txt", "deeply nested orphan");
return Promise.resolve();
},
cwd: () => deepNestedCleanupDir,
@@ -772,7 +757,7 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(brandExtDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(brandExtDir);
return Promise.resolve();
},
cwd: () => brandExtDir,
@@ -807,7 +792,7 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(brandExtDryRunDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(brandExtDryRunDir);
return Promise.resolve();
},
cwd: () => brandExtDryRunDir,
@@ -853,7 +838,7 @@ testQuartoCmd(
],
{
setup: () => {
- Deno.writeTextFileSync(join(brandExtSubdirDir, "_quarto.yml"), "project:\n type: default\n");
+ writeDefaultProject(brandExtSubdirDir);
return Promise.resolve();
},
cwd: () => brandExtSubdirDir,
diff --git a/tests/smoke/use/template-ai-config.test.ts b/tests/smoke/use/template-ai-config.test.ts
index 904cad28042..a0104830822 100644
--- a/tests/smoke/use/template-ai-config.test.ts
+++ b/tests/smoke/use/template-ai-config.test.ts
@@ -9,6 +9,7 @@
import { testQuartoCmd } from "../../test.ts";
import { fileExists, noErrorsOrWarnings, pathDoNotExists } from "../../verify.ts";
+import { writeFixture } from "../../utils.ts";
import { join } from "../../../src/deno_ral/path.ts";
import { ensureDirSync } from "../../../src/deno_ral/fs.ts";
@@ -16,29 +17,34 @@ const tempDir = Deno.makeTempDirSync();
// Create a mock template source with AI config files
const templateSourceDir = join(tempDir, "template-source");
-ensureDirSync(templateSourceDir);
-Deno.writeTextFileSync(
- join(templateSourceDir, "template.qmd"),
+writeFixture(
+ templateSourceDir,
+ "template.qmd",
"---\ntitle: Template Document\n---\n\nThis is a template document."
);
-Deno.writeTextFileSync(
- join(templateSourceDir, "CLAUDE.md"),
+writeFixture(
+ templateSourceDir,
+ "CLAUDE.md",
"# Claude Configuration\n\nThis should be excluded."
);
-Deno.writeTextFileSync(
- join(templateSourceDir, "AGENTS.md"),
+writeFixture(
+ templateSourceDir,
+ "AGENTS.md",
"# Agents Configuration\n\nThis should be excluded."
);
-Deno.writeTextFileSync(
- join(templateSourceDir, "CLAUDE.local.md"),
+writeFixture(
+ templateSourceDir,
+ "CLAUDE.local.md",
"# Claude Local Configuration\n\nThis should be excluded."
);
-Deno.writeTextFileSync(
- join(templateSourceDir, "AGENTS.local.md"),
+writeFixture(
+ templateSourceDir,
+ "AGENTS.local.md",
"# Agents Local Configuration\n\nThis should be excluded."
);
-Deno.writeTextFileSync(
- join(templateSourceDir, "README.md"),
+writeFixture(
+ templateSourceDir,
+ "README.md",
"# Template README\n\nThis should also be excluded."
);
diff --git a/tests/unit/axe-artifacts.test.ts b/tests/unit/axe-artifacts.test.ts
index 8f690ffda91..6397a4d0998 100644
--- a/tests/unit/axe-artifacts.test.ts
+++ b/tests/unit/axe-artifacts.test.ts
@@ -14,7 +14,7 @@ import { unitTest } from "../test.ts";
import { assert, assertEquals } from "testing/asserts";
import { join, resolve } from "../../src/deno_ral/path.ts";
import { isMac, isWindows } from "../../src/deno_ral/platform.ts";
-import { withTempDir } from "../utils.ts";
+import { withTempDir, writeFixture } from "../utils.ts";
import {
effectiveReportFile,
reportDestinationError,
@@ -90,8 +90,7 @@ unitTest(
);
const fullDir = join(dir, "occupied");
- Deno.mkdirSync(fullDir);
- Deno.writeTextFileSync(join(fullDir, "keep.txt"), "keep");
+ writeFixture(dir, "occupied/keep.txt", "keep");
assert(
reportDestinationError(fullDir) !== undefined,
"a non-empty directory destination must be rejected",
@@ -177,13 +176,12 @@ unitTest(
await withTempDir(async (dir) => {
const outputDir = join(dir, "_axe-checks");
const cellsDir = join(outputDir, "cells");
- Deno.mkdirSync(cellsDir, { recursive: true });
// A cell the previous scan wrote — this run would regenerate it while
// scanning, then silently overwrite it with markdown once the report
// is written, corrupting a raw per-cell axe payload.
const existingCell = join(cellsDir, "index__1440x900__light.json");
- Deno.writeTextFileSync(existingCell, "{}");
+ writeFixture(cellsDir, "index__1440x900__light.json", "{}");
assert(
reportDestinationError(existingCell, [], cellsDir) !== undefined,
"an existing cell file must be rejected as a --report destination",
diff --git a/tests/unit/axe-mode-discovery.test.ts b/tests/unit/axe-mode-discovery.test.ts
index 461653cf499..01aeb11d79b 100644
--- a/tests/unit/axe-mode-discovery.test.ts
+++ b/tests/unit/axe-mode-discovery.test.ts
@@ -15,7 +15,6 @@
import { unitTest } from "../test.ts";
import { assertEquals, assertThrows } from "testing/asserts";
import { join } from "../../src/deno_ral/path.ts";
-import { ensureDirSync } from "../../src/deno_ral/fs.ts";
import {
applyThemesFilter,
AxePage,
@@ -24,7 +23,7 @@ import {
sniffRedirectStub,
} from "../../src/command/call/axe/discover.ts";
import { axeScanConfig } from "../../src/command/call/axe/config.ts";
-import { withTempDir } from "../utils.ts";
+import { withTempDir, writeFixture } from "../utils.ts";
// The inline before-body script, boiled down to its marker. Quarto emits it
// iff the page has two modes.
@@ -133,8 +132,7 @@ unitTest(
/** A site dir on disk: every entry is a page written with static one-mode HTML. */
function writeSite(dir: string, pages: string[]) {
for (const page of pages) {
- ensureDirSync(join(dir, page, ".."));
- Deno.writeTextFileSync(join(dir, page), kStaticHtml);
+ writeFixture(dir, page, kStaticHtml);
}
}
diff --git a/tests/unit/core/deno-std-cache.test.ts b/tests/unit/core/deno-std-cache.test.ts
index 4b0fca45572..ec3e514e573 100644
--- a/tests/unit/core/deno-std-cache.test.ts
+++ b/tests/unit/core/deno-std-cache.test.ts
@@ -5,17 +5,13 @@
*/
import { ensureDirSync } from "../../../src/deno_ral/fs.ts";
-import { dirname, join } from "../../../src/deno_ral/path.ts";
+import { join } from "../../../src/deno_ral/path.ts";
import { directoryListingsMatch } from "../../../src/core/run/deno.ts";
import { unitTest } from "../../test.ts";
import { assertEquals } from "../../asserts.ts";
-import { withTempDir } from "../../utils.ts";
+import { withTempDir, writeFixture } from "../../utils.ts";
-const touch = (root: string, rel: string) => {
- const file = join(root, rel);
- ensureDirSync(dirname(file));
- Deno.writeTextFileSync(file, "");
-};
+const touch = (root: string, rel: string) => writeFixture(root, rel, "");
const populate = (root: string, rels: string[]) => {
ensureDirSync(root);
diff --git a/tests/unit/path.test.ts b/tests/unit/path.test.ts
index 899a41102bb..2be987eae4f 100644
--- a/tests/unit/path.test.ts
+++ b/tests/unit/path.test.ts
@@ -18,7 +18,7 @@ import {
skipHiddenWithin,
} from "../../src/core/path.ts";
import { existsSync, walkSync } from "../../src/deno_ral/fs.ts";
-import { docs } from "../utils.ts";
+import { docs, writeFixture } from "../utils.ts";
const workingDir = Deno.makeTempDirSync({ prefix: "quarto-test" });
const emptyDir = join(workingDir, "empty");
@@ -42,8 +42,7 @@ unitTest("path - removeIfEmptyDir", async () => {
removeIfEmptyDir(emptyDir);
assert(!existsSync(emptyDir), "Empty directory was not removed");
- Deno.mkdirSync(emptyDir);
- Deno.writeTextFileSync(join(emptyDir, "foo.txt"), "Hello World");
+ writeFixture(workingDir, "empty/foo.txt", "Hello World");
removeIfEmptyDir(emptyDir);
assert(existsSync(emptyDir), "Non-empty directory was removed");
@@ -124,8 +123,7 @@ unitTest("path - skipHiddenWithin only skips hidden paths below dir", async () =
try {
const root = join(tmp, ".parent", "proj");
for (const file of ["a.qmd", "x.y/b.qmd", ".git/c", "sub/.venv/d"]) {
- Deno.mkdirSync(join(root, file, ".."), { recursive: true });
- Deno.writeTextFileSync(join(root, file), "");
+ writeFixture(tmp, `.parent/proj/${file}`, "");
}
for (
const dir of [root, root + SEP, root.replaceAll("\\", "/")]
diff --git a/tests/unit/preview-brand-cache.test.ts b/tests/unit/preview-brand-cache.test.ts
index a77b4ff7760..ab0bee1cb6e 100644
--- a/tests/unit/preview-brand-cache.test.ts
+++ b/tests/unit/preview-brand-cache.test.ts
@@ -23,6 +23,7 @@ import { projectContext } from "../../src/project/project-context.ts";
import { notebookContext } from "../../src/render/notebook/notebook-context.ts";
import { initYamlIntelligenceResourcesFromFilesystem } from "../../src/core/schema/utils.ts";
import { safeRemoveSync } from "../../src/core/path.ts";
+import { writeDefaultProject } from "../utils.ts";
const BRAND_YML = `color:
palette:
@@ -108,10 +109,7 @@ unitTest(
try {
// A real multi-file project with a _quarto.yml, no brand declared.
- Deno.writeTextFileSync(
- join(tmpDir, "_quarto.yml"),
- "project:\n type: default\n",
- );
+ writeDefaultProject(tmpDir);
Deno.writeTextFileSync(
join(tmpDir, "index.qmd"),
"---\ntitle: test\nformat: typst\n---\n",
@@ -150,10 +148,7 @@ unitTest(
try {
// A real multi-file project with a _quarto.yml and a _brand.yml present.
- Deno.writeTextFileSync(
- join(tmpDir, "_quarto.yml"),
- "project:\n type: default\n",
- );
+ writeDefaultProject(tmpDir);
Deno.writeTextFileSync(
join(tmpDir, "index.qmd"),
"---\ntitle: test\nformat: typst\n---\n",
diff --git a/tests/unit/preview-extension-brand.test.ts b/tests/unit/preview-extension-brand.test.ts
index 89ec76a5bfe..b22b74d41c1 100644
--- a/tests/unit/preview-extension-brand.test.ts
+++ b/tests/unit/preview-extension-brand.test.ts
@@ -15,7 +15,6 @@
import { unitTest } from "../test.ts";
import { assert, assertEquals, assertRejects } from "../asserts.ts";
-import { ensureDirSync } from "../../src/deno_ral/fs.ts";
import { join } from "../../src/deno_ral/path.ts";
import { LightDarkBrandDarkFlag } from "../../src/core/brand/brand.ts";
import { singleFileProjectContext } from "../../src/project/types/single-file/single-file.ts";
@@ -28,7 +27,7 @@ import { notebookContext } from "../../src/render/notebook/notebook-context.ts";
import { renderServices } from "../../src/command/render/render-services.ts";
import { RenderOptions } from "../../src/command/render/types.ts";
import { initYamlIntelligenceResourcesFromFilesystem } from "../../src/core/schema/utils.ts";
-import { withTempDir } from "../utils.ts";
+import { withTempDir, writeDefaultProject, writeFixture } from "../utils.ts";
const BRAND_YML = `color:
palette:
@@ -56,13 +55,13 @@ function writeExtension(
projectMetadata: string,
name = "test-extension",
) {
- const extensionDir = join(dir, "_extensions", name);
- ensureDirSync(extensionDir);
- Deno.writeTextFileSync(
- join(extensionDir, "_extension.yml"),
+ const extensionDir = `_extensions/${name}`;
+ writeFixture(
+ dir,
+ `${extensionDir}/_extension.yml`,
extensionYml(projectMetadata),
);
- Deno.writeTextFileSync(join(extensionDir, "brand.yml"), BRAND_YML);
+ writeFixture(dir, `${extensionDir}/brand.yml`, BRAND_YML);
}
// The palette entry is unique to the extension's brand.yml, so asserting it
@@ -92,7 +91,7 @@ unitTest(
let project;
try {
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, " brand: brand.yml\n");
// preview builds the context this way: no renderOptions.
@@ -120,11 +119,7 @@ unitTest(
let project;
try {
- Deno.writeTextFileSync(
- join(tmpDir, "_quarto.yml"),
- "project:\n type: default\n",
- );
- Deno.writeTextFileSync(join(tmpDir, "index.qmd"), DOCUMENT);
+ writeProject(tmpDir);
writeExtension(tmpDir, " brand: brand.yml\n");
// preview builds the context this way: no renderOptions.
@@ -155,7 +150,7 @@ unitTest(
let project;
try {
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, " brand: brand.yml\n");
// render builds the context this way: renderOptions present.
@@ -187,7 +182,7 @@ unitTest(
let project;
try {
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, ' output-dir: "_out"\n');
project = await singleFileProjectContext(
@@ -224,7 +219,7 @@ unitTest(
let project;
try {
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, ' output-dir: "_out"\n');
project = await singleFileProjectContext(file, notebookContext());
@@ -256,7 +251,7 @@ unitTest(
let project;
try {
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, MALFORMED_METADATA);
// preview and inspect must degrade to "metadata not applied" here.
@@ -283,11 +278,7 @@ unitTest(
let project;
try {
- Deno.writeTextFileSync(
- join(tmpDir, "_quarto.yml"),
- "project:\n type: default\n",
- );
- Deno.writeTextFileSync(join(tmpDir, "index.qmd"), DOCUMENT);
+ writeProject(tmpDir);
writeExtension(tmpDir, MALFORMED_METADATA);
project = await projectContext(tmpDir, notebookContext());
@@ -319,7 +310,7 @@ unitTest(
const renderOptions = { services, flags: {} } as RenderOptions;
try {
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, MALFORMED_METADATA);
await assertRejects(
@@ -348,11 +339,7 @@ unitTest(
const renderOptions = { services, flags: {} } as RenderOptions;
try {
- Deno.writeTextFileSync(
- join(tmpDir, "_quarto.yml"),
- "project:\n type: default\n",
- );
- Deno.writeTextFileSync(join(tmpDir, "index.qmd"), DOCUMENT);
+ writeProject(tmpDir);
writeExtension(tmpDir, MALFORMED_METADATA);
await assertRejects(
@@ -380,7 +367,7 @@ unitTest(
let project;
try {
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, MALFORMED_METADATA, "broken-extension");
writeExtension(tmpDir, " brand: brand.yml\n", "brand-extension");
@@ -425,11 +412,8 @@ async function recordWarnings(run: () => Promise): Promise {
}
function writeProject(dir: string) {
- Deno.writeTextFileSync(
- join(dir, "_quarto.yml"),
- "project:\n type: default\n",
- );
- Deno.writeTextFileSync(join(dir, "index.qmd"), DOCUMENT);
+ writeDefaultProject(dir);
+ writeFixture(dir, "index.qmd", DOCUMENT);
}
unitTest(
@@ -532,7 +516,7 @@ unitTest(
previous = await projectContext(tmpDir, nbContext);
assert(previous !== undefined, "projectContext must resolve");
- Deno.writeTextFileSync(join(tmpDir, "_quarto.yml"), "project: [\n");
+ writeFixture(tmpDir, "_quarto.yml", "project: [\n");
const refreshed = await refreshProjectContext(
previous,
@@ -584,7 +568,7 @@ unitTest(
await withTempDir(async (tmpDir) => {
const file = join(tmpDir, "test.qmd");
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, MALFORMED_METADATA, "fatal-single-extension");
await assertRejects(
@@ -609,7 +593,7 @@ unitTest(
let project: ProjectContext | undefined;
try {
- Deno.writeTextFileSync(file, DOCUMENT);
+ writeFixture(tmpDir, "test.qmd", DOCUMENT);
writeExtension(tmpDir, MALFORMED_METADATA, "message-extension");
const warnings = await recordWarnings(async () => {
diff --git a/tests/unit/project-cache.test.ts b/tests/unit/project-cache.test.ts
index 92864fa51dd..c4c87c5b667 100644
--- a/tests/unit/project-cache.test.ts
+++ b/tests/unit/project-cache.test.ts
@@ -14,11 +14,11 @@ import {
assertStringIncludes,
} from "../asserts.ts";
import { join } from "../../src/deno_ral/path.ts";
-import { ensureDirSync, existsSync } from "../../src/deno_ral/fs.ts";
+import { existsSync } from "../../src/deno_ral/fs.ts";
import { v8Branch } from "../../src/deno_ral/platform.ts";
import { md5HashBytes } from "../../src/core/hash.ts";
import { createProjectCache } from "../../src/core/cache/cache.ts";
-import { withTempDir } from "../utils.ts";
+import { withTempDir, writeFixture } from "../utils.ts";
import { noErrors, printsMessage } from "../verify.ts";
import {
damageKvRow,
@@ -35,9 +35,8 @@ unitTest(
async () => {
await withTempDir(async (scratch) => {
const legacyDir = join(scratch, "project-cache");
- ensureDirSync(legacyDir);
const legacy = join(legacyDir, "deno-kv-file");
- Deno.writeTextFileSync(legacy, LEGACY_SENTINEL);
+ writeFixture(legacyDir, "deno-kv-file", LEGACY_SENTINEL);
const cache = await createProjectCache(scratch);
try {
diff --git a/tests/unit/project/project-context-input-files.test.ts b/tests/unit/project/project-context-input-files.test.ts
index 5802618ecce..e569fcc3b91 100644
--- a/tests/unit/project/project-context-input-files.test.ts
+++ b/tests/unit/project/project-context-input-files.test.ts
@@ -10,13 +10,13 @@
import { unitTest } from "../../test.ts";
import { assert, assertEquals } from "testing/asserts";
-import { dirname, join, relative } from "../../../src/deno_ral/path.ts";
+import { join, relative } from "../../../src/deno_ral/path.ts";
import { normalizePath } from "../../../src/core/path.ts";
import { projectContext } from "../../../src/project/project-context.ts";
import { ProjectContext } from "../../../src/project/types.ts";
import { notebookContext } from "../../../src/render/notebook/notebook-context.ts";
import { initYamlIntelligenceResourcesFromFilesystem } from "../../../src/core/schema/utils.ts";
-import { docs, withTempDir } from "../../utils.ts";
+import { docs, withTempDir, writeFixture } from "../../utils.ts";
const kDoc = "---\ntitle: test\n---\n\nHello\n";
@@ -30,13 +30,11 @@ const kIgnored = [
];
function writeProject(dir: string, quartoYml: string) {
- Deno.writeTextFileSync(join(dir, "_quarto.yml"), quartoYml);
+ writeFixture(dir, "_quarto.yml", quartoYml);
for (const file of [...kInputs, ...kIgnored]) {
- const path = join(dir, file);
- Deno.mkdirSync(dirname(path), { recursive: true });
- Deno.writeTextFileSync(path, kDoc);
+ writeFixture(dir, file, kDoc);
}
- Deno.writeTextFileSync(join(dir, "notes.txt"), "not an input");
+ writeFixture(dir, "notes.txt", "not an input");
}
function relativeInputs(context: ProjectContext) {
diff --git a/tests/unit/project/project-context-unreadable-dir.test.ts b/tests/unit/project/project-context-unreadable-dir.test.ts
index 5e42b367b9f..b495ba83a42 100644
--- a/tests/unit/project/project-context-unreadable-dir.test.ts
+++ b/tests/unit/project/project-context-unreadable-dir.test.ts
@@ -30,6 +30,7 @@ import {
canMakeUnreadableDir,
makeUnreadableDir,
withTempDir,
+ writeFixture,
} from "../../utils.ts";
function sessionTempDirs(root: string) {
@@ -60,12 +61,11 @@ if (canMakeUnreadableDir) {
await withTempDir(async (tmp) => {
const root = normalizePath(tmp);
if (quartoYml) {
- Deno.writeTextFileSync(join(root, "_quarto.yml"), quartoYml);
+ writeFixture(root, "_quarto.yml", quartoYml);
}
- Deno.writeTextFileSync(join(root, "index.qmd"), "# Hello\n");
+ writeFixture(root, "index.qmd", "# Hello\n");
const locked = join(root, "locked");
- Deno.mkdirSync(locked);
- Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
+ writeFixture(root, "locked/doc.qmd", "# Locked\n");
const restore = makeUnreadableDir(locked);
let walkError: unknown;
try {
diff --git a/tests/unit/project/project-detect-denied-path.test.ts b/tests/unit/project/project-detect-denied-path.test.ts
index e0b510c18fd..ea9385bd42f 100644
--- a/tests/unit/project/project-detect-denied-path.test.ts
+++ b/tests/unit/project/project-detect-denied-path.test.ts
@@ -16,7 +16,7 @@ import { isWindows } from "../../../src/deno_ral/platform.ts";
import { projectContext } from "../../../src/project/project-context.ts";
import { notebookContext } from "../../../src/render/notebook/notebook-context.ts";
import { initYamlIntelligenceResourcesFromFilesystem } from "../../../src/core/schema/utils.ts";
-import { withTempDir } from "../../utils.ts";
+import { withTempDir, writeFixture } from "../../utils.ts";
// `config/` and `content/` at the root and `work/doc.qmd` below it, with no
// _quarto.yml, so only the Hugo detectors can claim the root.
@@ -24,14 +24,10 @@ function hugoLikeTree(tmp: string, configToml: boolean) {
const root = normalizePath(tmp);
Deno.mkdirSync(join(root, "config", "_default"), { recursive: true });
if (configToml) {
- Deno.writeTextFileSync(
- join(root, "config", "_default", "config.toml"),
- "",
- );
+ writeFixture(root, "config/_default/config.toml", "");
}
Deno.mkdirSync(join(root, "content"));
- Deno.mkdirSync(join(root, "work"));
- Deno.writeTextFileSync(join(root, "work", "doc.qmd"), "# Hello\n");
+ writeFixture(root, "work/doc.qmd", "# Hello\n");
return root;
}
diff --git a/tests/unit/render/cleanup.test.ts b/tests/unit/render/cleanup.test.ts
index f5c5e1a91ff..c060ee0cfb7 100644
--- a/tests/unit/render/cleanup.test.ts
+++ b/tests/unit/render/cleanup.test.ts
@@ -5,7 +5,8 @@
*/
import { assert } from "testing/asserts";
-import { ensureDirSync, existsSync } from "../../../src/deno_ral/fs.ts";
+import { existsSync } from "../../../src/deno_ral/fs.ts";
+import { writeFixture } from "../../utils.ts";
import { join } from "../../../src/deno_ral/path.ts";
import { unitTest } from "../../test.ts";
import { renderCleanup } from "../../../src/command/render/cleanup.ts";
@@ -46,11 +47,9 @@ unitTest("renderCleanup - narrows ipynb supporting despite path separator mismat
const filesDir = join(projectDir, "index_files");
const figureHtmlDir = join(filesDir, "figure-html");
const figureIpynbDir = join(filesDir, "figure-ipynb");
- ensureDirSync(figureHtmlDir);
- ensureDirSync(figureIpynbDir);
const figureHtmlPlot = join(figureHtmlDir, "plot.png");
- Deno.writeTextFileSync(figureHtmlPlot, "html-figure");
- Deno.writeTextFileSync(join(figureIpynbDir, "plot.png"), "ipynb-figure");
+ writeFixture(figureHtmlDir, "plot.png", "html-figure");
+ writeFixture(figureIpynbDir, "plot.png", "ipynb-figure");
// Engine reports the supporting dir with forward slashes (as knitr does).
const supportingForwardSlash = filesDir.replaceAll("\\", "/");
diff --git a/tests/unit/sass-cache.test.ts b/tests/unit/sass-cache.test.ts
index e75ae1f768b..3ea21e8a66a 100644
--- a/tests/unit/sass-cache.test.ts
+++ b/tests/unit/sass-cache.test.ts
@@ -23,7 +23,7 @@ import { v8Branch } from "../../src/deno_ral/platform.ts";
import { safeRemoveIfExists } from "../../src/core/path.ts";
import { createTempContext, TempContext } from "../../src/core/temp.ts";
import { sassCache } from "../../src/core/sass/cache.ts";
-import { withTempDir } from "../utils.ts";
+import { withTempDir, writeFixture } from "../utils.ts";
import { noErrors, printsMessage } from "../verify.ts";
import { md5HashAsync } from "../../src/core/hash.ts";
import {
@@ -86,9 +86,8 @@ unitTest(
async () => {
await withTempDir(async (root) => {
const cachePath = join(root, "sass");
- ensureDirSync(cachePath);
const legacy = join(cachePath, "sass.kv");
- Deno.writeTextFileSync(legacy, LEGACY_SENTINEL);
+ writeFixture(cachePath, "sass.kv", LEGACY_SENTINEL);
const temp = createTempContext();
try {
diff --git a/tests/unit/smoke-all-prerender-isolation.test.ts b/tests/unit/smoke-all-prerender-isolation.test.ts
index a7e163f548b..5c853e7c371 100644
--- a/tests/unit/smoke-all-prerender-isolation.test.ts
+++ b/tests/unit/smoke-all-prerender-isolation.test.ts
@@ -5,6 +5,7 @@
*/
import { assert, assertEquals } from "testing/asserts";
import { unitTest } from "../test.ts";
+import { writeFixture } from "../utils.ts";
import { dirname, fromFileUrl, join } from "../../src/deno_ral/path.ts";
import { safeExistsSync } from "../../src/core/path.ts";
@@ -67,10 +68,10 @@ unitTest(
try {
const smokeAllDir = join(tmpRoot, "smoke-all");
const projectDir = join(smokeAllDir, "_prerender-crash");
- Deno.mkdirSync(projectDir, { recursive: true });
- Deno.writeTextFileSync(
- join(projectDir, "_quarto.yml"),
+ writeFixture(
+ projectDir,
+ "_quarto.yml",
"project:\n type: default\n render:\n" +
" - broken-b.qmd\n - broken-c.qmd\n",
);
@@ -78,8 +79,9 @@ unitTest(
// This file does not request a project pre-render. It sorts before files
// that do, but project.render excludes it. Its HTML test spec registers
// cleanup paths for a skipped file.
- Deno.writeTextFileSync(
- join(projectDir, "broken-a.qmd"),
+ writeFixture(
+ projectDir,
+ "broken-a.qmd",
[
"---",
"title: a",
@@ -96,20 +98,14 @@ unitTest(
);
// Pre-create outputs for broken-a.qmd. Because project.render excludes
// the file, their removal verifies cleanup for a skipped file.
- Deno.writeTextFileSync(
- join(projectDir, "broken-a.html"),
- "sentinel\n",
- );
+ writeFixture(projectDir, "broken-a.html", "sentinel\n");
const supportDir = join(projectDir, "broken-a_files");
- Deno.mkdirSync(supportDir, { recursive: true });
- Deno.writeTextFileSync(
- join(supportDir, "sentinel.txt"),
- "sentinel\n",
- );
+ writeFixture(supportDir, "sentinel.txt", "sentinel\n");
// This file requests the project pre-render and makes it fail.
- Deno.writeTextFileSync(
- join(projectDir, "broken-b.qmd"),
+ writeFixture(
+ projectDir,
+ "broken-b.qmd",
[
"---",
"title: b",
@@ -125,8 +121,9 @@ unitTest(
);
// A second file requests the same project pre-render, verifying that it
// runs once per project.
- Deno.writeTextFileSync(
- join(projectDir, "broken-c.qmd"),
+ writeFixture(
+ projectDir,
+ "broken-c.qmd",
[
"---",
"title: c",
@@ -141,8 +138,9 @@ unitTest(
// This healthy control file sorts after the broken project and must
// still run.
- Deno.writeTextFileSync(
- join(smokeAllDir, "healthy-canary.qmd"),
+ writeFixture(
+ smokeAllDir,
+ "healthy-canary.qmd",
["---", "title: healthy", "---", "", "# healthy", ""].join("\n"),
);
diff --git a/tests/unit/tools/check-runtime-boundary.test.ts b/tests/unit/tools/check-runtime-boundary.test.ts
index c8f5f9c21b9..3ee4f97a53e 100644
--- a/tests/unit/tools/check-runtime-boundary.test.ts
+++ b/tests/unit/tools/check-runtime-boundary.test.ts
@@ -12,7 +12,8 @@ import { unitTest } from "../../test.ts";
import { assert, assertEquals, assertRejects, assertThrows } from "../../asserts.ts";
import { join, resolve } from "../../../src/deno_ral/path.ts";
import { quartoDevBinCmd } from "../../quarto-cmd.ts";
-import { ensureDirSync, safeRemoveSync } from "../../../src/deno_ral/fs.ts";
+import { safeRemoveSync } from "../../../src/deno_ral/fs.ts";
+import { writeFixture } from "../../utils.ts";
import { execProcess } from "../../../src/core/process.ts";
import { createTempContext } from "../../../src/core/temp.ts";
import {
@@ -43,12 +44,6 @@ const DENO = ["De", "no"].join("") + ".";
const FROM = ["fr", "om"].join("");
const IMPORT = ["im", "port"].join("");
-function writeFixture(root: string, rel: string, contents: string) {
- const parts = rel.split("/");
- ensureDirSync(join(root, ...parts.slice(0, -1)));
- Deno.writeTextFileSync(join(root, ...parts), contents);
-}
-
function makeRepo(root: string) {
writeFixture(root, "src/quarto.ts", "export {};\n");
// src: 2 calls, 1 std file (import-map name, double quotes)
diff --git a/tests/unit/tools/chrome-headless-shell.test.ts b/tests/unit/tools/chrome-headless-shell.test.ts
index 0b6df4fd6b4..559c6106d3e 100644
--- a/tests/unit/tools/chrome-headless-shell.test.ts
+++ b/tests/unit/tools/chrome-headless-shell.test.ts
@@ -5,7 +5,7 @@
*/
import { unitTest } from "../../test.ts";
-import { withTempDir } from "../../utils.ts";
+import { withTempDir, writeFixture } from "../../utils.ts";
import { assert, assertEquals } from "testing/asserts";
import { join } from "../../../src/deno_ral/path.ts";
import { existsSync, safeRemoveSync } from "../../../src/deno_ral/fs.ts";
@@ -104,10 +104,8 @@ unitTest("isInstalled - returns false when only binary exists (no version file)"
const { platform } = detectChromePlatform();
const binName = chromeHeadlessShellBinaryName();
// CfT layout (all platforms, including Playwright CDN arm64): chrome-headless-shell-{platform}/binary
- const subdir = join(tempDir, `chrome-headless-shell-${platform}`);
- Deno.mkdirSync(subdir);
const target = isWindows ? `${binName}.exe` : binName;
- Deno.writeTextFileSync(join(subdir, target), "fake");
+ writeFixture(tempDir, `chrome-headless-shell-${platform}/${target}`, "fake");
assertEquals(isInstalled(tempDir), false);
} finally {
safeRemoveSync(tempDir, { recursive: true });
@@ -120,10 +118,8 @@ unitTest("isInstalled - returns true when version file and binary exist", async
noteInstalledVersion(tempDir, "145.0.0.0");
const { platform } = detectChromePlatform();
const binName = chromeHeadlessShellBinaryName();
- const subdir = join(tempDir, `chrome-headless-shell-${platform}`);
- Deno.mkdirSync(subdir);
const target = isWindows ? `${binName}.exe` : binName;
- Deno.writeTextFileSync(join(subdir, target), "fake");
+ writeFixture(tempDir, `chrome-headless-shell-${platform}/${target}`, "fake");
assertEquals(isInstalled(tempDir), true);
} finally {
@@ -150,24 +146,19 @@ unitTest("isInstalled - returns true when version file and binary exist", async
// ".exe" whenever the host is Windows, so the fixture matches that to exercise
// the same code path off-Linux.
function writeLegacyPlaywrightFixture(dir: string): string {
- const legacyDir = join(dir, "chrome-linux");
- Deno.mkdirSync(legacyDir, { recursive: true });
const target = isWindows ? "headless_shell.exe" : "headless_shell";
- const path = join(legacyDir, target);
- Deno.writeTextFileSync(path, "fake");
- return path;
+ writeFixture(dir, `chrome-linux/${target}`, "fake");
+ return join(dir, "chrome-linux", target);
}
// Current CfT fixture: chrome-headless-shell-{platform}/chrome-headless-shell.
function writeCftFixture(dir: string): string {
const { platform } = detectChromePlatform();
const binName = chromeHeadlessShellBinaryName();
- const subdir = join(dir, `chrome-headless-shell-${platform}`);
- Deno.mkdirSync(subdir, { recursive: true });
const target = isWindows ? `${binName}.exe` : binName;
- const path = join(subdir, target);
- Deno.writeTextFileSync(path, "fake");
- return path;
+ const rel = `chrome-headless-shell-${platform}/${target}`;
+ writeFixture(dir, rel, "fake");
+ return join(dir, rel);
}
unitTest(
diff --git a/tests/unit/typst-staging.test.ts b/tests/unit/typst-staging.test.ts
index 0ced91a7700..679163a6e90 100644
--- a/tests/unit/typst-staging.test.ts
+++ b/tests/unit/typst-staging.test.ts
@@ -7,6 +7,7 @@
*/
import { unitTest } from "../test.ts";
+import { writeFixture } from "../utils.ts";
import { assert, assertEquals } from "testing/asserts";
import { join } from "../../src/deno_ral/path.ts";
import { existsSync } from "../../src/deno_ral/fs.ts";
@@ -27,12 +28,12 @@ function createFakePackage(
content = "default",
): string {
const pkgDir = join(baseDir, namespace, name, version);
- ensureDirSync(pkgDir);
- Deno.writeTextFileSync(
- join(pkgDir, "typst.toml"),
+ writeFixture(
+ pkgDir,
+ "typst.toml",
`[package]\nname = "${name}"\nversion = "${version}"\n`,
);
- Deno.writeTextFileSync(join(pkgDir, "lib.typ"), `// ${content}\n`);
+ writeFixture(pkgDir, "lib.typ", `// ${content}\n`);
return pkgDir;
}
@@ -270,12 +271,10 @@ unitTest("stageSelectedPackages - preserves package contents", async () => {
// Create package with subdirectory
const pkgDir = join(source, "preview/cetz/0.4.1");
- ensureDirSync(pkgDir);
- Deno.writeTextFileSync(join(pkgDir, "typst.toml"), '[package]\nname = "cetz"\n');
- Deno.writeTextFileSync(join(pkgDir, "lib.typ"), "// main\n");
- ensureDirSync(join(pkgDir, "src"));
- Deno.writeTextFileSync(join(pkgDir, "src/draw.typ"), "// draw\n");
- Deno.writeTextFileSync(join(pkgDir, "src/canvas.typ"), "// canvas\n");
+ writeFixture(pkgDir, "typst.toml", '[package]\nname = "cetz"\n');
+ writeFixture(pkgDir, "lib.typ", "// main\n");
+ writeFixture(pkgDir, "src/draw.typ", "// draw\n");
+ writeFixture(pkgDir, "src/canvas.typ", "// canvas\n");
const needed: NeededPackage[] = [
{ namespace: "preview", name: "cetz", version: "0.4.1" },
diff --git a/tests/utils.ts b/tests/utils.ts
index dd01ff6b18f..18a48728988 100644
--- a/tests/utils.ts
+++ b/tests/utils.ts
@@ -11,6 +11,7 @@ import { kMetadataFormat, kOutputExt, kOutputFile } from "../src/config/constant
import { pathWithForwardSlashes, safeExistsSync } from "../src/core/path.ts";
import { readYaml } from "../src/core/yaml.ts";
import { isWindows } from "../src/deno_ral/platform.ts";
+import { ensureDirSync } from "../src/deno_ral/fs.ts";
import { originalRealPathSync } from "../src/deno_ral/original-real-path.ts";
import { bookOutputStem } from "../src/project/types/book/book-shared.ts";
import { ProjectConfig } from "../src/project/types.ts";
@@ -33,6 +34,19 @@ export async function withTempDir(
}
}
+// Write contents at the slash-separated path rel under root, creating any
+// missing parent directories.
+export function writeFixture(root: string, rel: string, contents: string) {
+ const parts = rel.split("/");
+ ensureDirSync(join(root, ...parts.slice(0, -1)));
+ Deno.writeTextFileSync(join(root, ...parts), contents);
+}
+
+// Make dir a default-type project by writing its _quarto.yml.
+export function writeDefaultProject(dir: string) {
+ writeFixture(dir, "_quarto.yml", "project:\n type: default\n");
+}
+
// Run fn from dir and restore the process cwd afterward.
export async function withCwd(
dir: string,
@@ -313,9 +327,8 @@ export function makeUnreadableDir(dir: string): () => void {
// temp dirs live under the /var -> /private/var symlink).
export function tempProject(prefix: string): string {
const dir = originalRealPathSync(Deno.makeTempDirSync({ prefix }));
- Deno.writeTextFileSync(join(dir, "_quarto.yml"), "project:\n type: website\n");
- Deno.mkdirSync(join(dir, "sub"));
- Deno.writeTextFileSync(join(dir, "sub", "index.qmd"), "# Hello\n");
+ writeFixture(dir, "_quarto.yml", "project:\n type: website\n");
+ writeFixture(dir, "sub/index.qmd", "# Hello\n");
return dir;
}
diff --git a/tools/runtime-boundary-baseline.json b/tools/runtime-boundary-baseline.json
index 247451a29b4..cf99f8c67f6 100644
--- a/tools/runtime-boundary-baseline.json
+++ b/tools/runtime-boundary-baseline.json
@@ -16,7 +16,7 @@
"stdImportFiles": 3
},
"tests": {
- "denoCalls": 896,
+ "denoCalls": 774,
"stdImportFiles": 176
}
}