Skip to content

Commit bd5161d

Browse files
authored
Share fixture-writing helpers across tests (#15267)
Many unit tests created a directory only to write one file into it, or repeated the same default-type _quarto.yml by hand. Move the fixture helpers into tests/utils.ts so they share one implementation: writeFixture creates parent directories and writes a file at a slash-separated path, and writeDefaultProject writes the default project config. Directories that matter on their own (a cwd, a directory made unreadable later, an empty directory a test asserts on) keep their explicit creation. - Add writeFixture and writeDefaultProject to tests/utils.ts - Use them in about 20 test files in place of direct Deno writes - Update the runtime boundary baseline (tests count 895 -> 773) Related to #14784 See #15223 for the runtime boundary baseline
1 parent 2a6d12a commit bd5161d

25 files changed

Lines changed: 175 additions & 229 deletions

‎tests/smoke/axe/axe-exit-codes.test.ts‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,20 @@ import { existsSync } from "../../../src/deno_ral/fs.ts";
2121
import { join } from "../../../src/deno_ral/path.ts";
2222
import { execProcess } from "../../../src/core/process.ts";
2323
import { unitTest } from "../../test.ts";
24+
import { writeFixture } from "../../utils.ts";
2425
import { quartoDevBinCmd, quartoSpawnEnvOptions } from "../../quarto-cmd.ts";
2526
import { AxeFindings } from "../../../src/command/call/axe/schemas.ts";
2627

2728
const workingDir = Deno.makeTempDirSync({ prefix: "quarto-axe-exit" });
28-
Deno.mkdirSync(join(workingDir, "site"));
29-
Deno.writeTextFileSync(
30-
join(workingDir, "site", "index.html"),
29+
writeFixture(
30+
workingDir,
31+
"site/index.html",
3132
`<!DOCTYPE html>
3233
<html lang="en"><head><title>exit codes</title></head>
3334
<body><main><h1>Exit codes</h1><img src="dot.png"></main></body></html>
3435
`,
3536
);
36-
Deno.writeTextFileSync(join(workingDir, "site", "dot.png"), "not-really-a-png");
37+
writeFixture(workingDir, "site/dot.png", "not-really-a-png");
3738

3839
function findings(): AxeFindings {
3940
return JSON.parse(
@@ -158,10 +159,8 @@ unitTest(
158159
const notABrowser = join(workingDir, "not-a-browser");
159160
Deno.writeTextFileSync(notABrowser, "");
160161
// a previous scan's summary must not survive to be read as current
161-
const artifacts = join(workingDir, "_axe-checks");
162-
Deno.mkdirSync(artifacts, { recursive: true });
163-
const staleFindings = join(artifacts, "findings.json");
164-
Deno.writeTextFileSync(staleFindings, `{"stale": true}`);
162+
writeFixture(workingDir, "_axe-checks/findings.json", `{"stale": true}`);
163+
const staleFindings = join(workingDir, "_axe-checks", "findings.json");
165164

166165
const result = await execProcess({
167166
cmd: quartoDevBinCmd(),

‎tests/smoke/check/check-info-project.test.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
import { dirname, join, resolve } from "../../../src/deno_ral/path.ts";
12+
import { writeDefaultProject } from "../../utils.ts";
1213
import { execProcess } from "../../../src/core/process.ts";
1314
import { originalRealPathSync } from "../../../src/deno_ral/original-real-path.ts";
1415
import { isWindows } from "../../../src/deno_ral/platform.ts";
@@ -30,7 +31,7 @@ function tempDir(prefix: string): string {
3031
// The tree must exist at registration: the harness enters `cwd` before setup.
3132
function tempProject(): string {
3233
const dir = tempDir("quarto-check-info-project");
33-
Deno.writeTextFileSync(join(dir, "_quarto.yml"), "project:\n type: default\n");
34+
writeDefaultProject(dir);
3435
Deno.mkdirSync(join(dir, "sub"));
3536
return dir;
3637
}

‎tests/smoke/check/check-project-config-only.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
makeUnreadableDir,
1616
removeProject,
1717
tempProject,
18+
writeFixture,
1819
} from "../../utils.ts";
1920
import { assert, assertEquals } from "testing/asserts";
2021

@@ -23,8 +24,7 @@ import { assert, assertEquals } from "testing/asserts";
2324
if (canMakeUnreadableDir) {
2425
const projectDir = tempProject("quarto-check-project");
2526
const locked = join(projectDir, "locked");
26-
Deno.mkdirSync(locked);
27-
Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
27+
writeFixture(projectDir, "locked/doc.qmd", "# Locked\n");
2828
const output = join(projectDir, "check-info.json");
2929
let restore: (() => void) | undefined;
3030
testQuartoCmdJson(

‎tests/smoke/check/check-render-temp-in-project.test.ts‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
canMakeUnreadableDir,
2222
makeUnreadableDir,
2323
tempProject,
24+
writeFixture,
2425
} from "../../utils.ts";
2526
import { checkRender } from "../../../src/command/check/check-render.ts";
2627
import { renderServices } from "../../../src/command/render/render-services.ts";
@@ -36,8 +37,7 @@ unitTest(
3637
async () => {
3738
const projectDir = tempProject("quarto-check-render-temp");
3839
const locked = join(projectDir, "locked");
39-
Deno.mkdirSync(locked);
40-
Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
40+
writeFixture(projectDir, "locked/doc.qmd", "# Locked\n");
4141
const tmp = join(projectDir, "tmp");
4242
Deno.mkdirSync(tmp);
4343
const restore = makeUnreadableDir(locked);
@@ -72,8 +72,7 @@ unitTest(
7272
await initYamlIntelligenceResourcesFromFilesystem();
7373
const projectDir = tempProject("quarto-check-render-temp");
7474
const locked = join(projectDir, "locked");
75-
Deno.mkdirSync(locked);
76-
Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
75+
writeFixture(projectDir, "locked/doc.qmd", "# Locked\n");
7776
const restore = makeUnreadableDir(locked);
7877
const services = {
7978
...renderServices(notebookContext()),

‎tests/smoke/project/project-unreadable-dir.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
makeUnreadableDir,
1717
removeProject,
1818
tempProject,
19+
writeFixture,
1920
} from "../../utils.ts";
2021
import { assert, assertEquals } from "testing/asserts";
2122

@@ -42,11 +43,10 @@ function registerUnreadableDirTest(
4243
) {
4344
const root = normalizePath(tempProject("quarto-unreadable-project"));
4445
if (quartoYml) {
45-
Deno.writeTextFileSync(join(root, "_quarto.yml"), quartoYml);
46+
writeFixture(root, "_quarto.yml", quartoYml);
4647
}
4748
const locked = join(root, "locked");
48-
Deno.mkdirSync(locked);
49-
Deno.writeTextFileSync(join(locked, "doc.qmd"), "# Locked\n");
49+
writeFixture(root, "locked/doc.qmd", "# Locked\n");
5050
let restore: (() => void) | undefined;
5151
testQuartoCmd(cmd, ["index.qmd"], [verify(root, locked)], {
5252
cwd: () => join(root, "sub"),

‎tests/smoke/use/brand.test.ts‎

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { testQuartoCmd, ExecuteOutput, Verify } from "../../test.ts";
22
import { fileExists, folderExists, noErrorsOrWarnings, printsMessage } from "../../verify.ts";
33
import { join, fromFileUrl, dirname } from "../../../src/deno_ral/path.ts";
4+
import { writeDefaultProject, writeFixture } from "../../utils.ts";
45
import { ensureDirSync, existsSync } from "../../../src/deno_ral/fs.ts";
56
import { pathWithForwardSlashes } from "../../../src/core/path.ts";
67

@@ -90,7 +91,7 @@ testQuartoCmd(
9091
],
9192
{
9293
setup: () => {
93-
Deno.writeTextFileSync(join(basicDir, "_quarto.yml"), "project:\n type: default\n");
94+
writeDefaultProject(basicDir);
9495
return Promise.resolve();
9596
},
9697
cwd: () => basicDir,
@@ -137,7 +138,7 @@ testQuartoCmd(
137138
],
138139
{
139140
setup: () => {
140-
Deno.writeTextFileSync(join(dryRunDir, "_quarto.yml"), "project:\n type: default\n");
141+
writeDefaultProject(dryRunDir);
141142
return Promise.resolve();
142143
},
143144
cwd: () => dryRunDir,
@@ -188,14 +189,12 @@ testQuartoCmd(
188189
],
189190
{
190191
setup: () => {
191-
Deno.writeTextFileSync(join(forceOverwriteDir, "_quarto.yml"), "project:\n type: default\n");
192+
writeDefaultProject(forceOverwriteDir);
192193
// Create existing _brand directory with files
193-
const brandDir = join(forceOverwriteDir, "_brand");
194-
ensureDirSync(brandDir);
195194
// This file exists in source - should be overwritten
196-
Deno.writeTextFileSync(join(brandDir, "_brand.yml"), "meta:\n name: Old Brand\n");
195+
writeFixture(forceOverwriteDir, "_brand/_brand.yml", "meta:\n name: Old Brand\n");
197196
// This file does NOT exist in source - should be preserved
198-
Deno.writeTextFileSync(join(brandDir, "unrelated.txt"), "keep me");
197+
writeFixture(forceOverwriteDir, "_brand/unrelated.txt", "keep me");
199198
return Promise.resolve();
200199
},
201200
cwd: () => forceOverwriteDir,
@@ -257,12 +256,10 @@ testQuartoCmd(
257256
],
258257
{
259258
setup: () => {
260-
Deno.writeTextFileSync(join(dryRunOverwriteDir, "_quarto.yml"), "project:\n type: default\n");
259+
writeDefaultProject(dryRunOverwriteDir);
261260
// Create existing _brand directory with _brand.yml and extra.txt (not logo.png)
262-
const brandDir = join(dryRunOverwriteDir, "_brand");
263-
ensureDirSync(brandDir);
264-
Deno.writeTextFileSync(join(brandDir, "_brand.yml"), "meta:\n name: Old Brand\n");
265-
Deno.writeTextFileSync(join(brandDir, "extra.txt"), "extra file not in source");
261+
writeFixture(dryRunOverwriteDir, "_brand/_brand.yml", "meta:\n name: Old Brand\n");
262+
writeFixture(dryRunOverwriteDir, "_brand/extra.txt", "extra file not in source");
266263
return Promise.resolve();
267264
},
268265
cwd: () => dryRunOverwriteDir,
@@ -285,7 +282,7 @@ testQuartoCmd(
285282
],
286283
{
287284
setup: () => {
288-
Deno.writeTextFileSync(join(errorFlagDir, "_quarto.yml"), "project:\n type: default\n");
285+
writeDefaultProject(errorFlagDir);
289286
return Promise.resolve();
290287
},
291288
cwd: () => errorFlagDir,
@@ -336,7 +333,7 @@ testQuartoCmd(
336333
],
337334
{
338335
setup: () => {
339-
Deno.writeTextFileSync(join(multiFileDir, "_quarto.yml"), "project:\n type: default\n");
336+
writeDefaultProject(multiFileDir);
340337
return Promise.resolve();
341338
},
342339
cwd: () => multiFileDir,
@@ -384,7 +381,7 @@ testQuartoCmd(
384381
],
385382
{
386383
setup: () => {
387-
Deno.writeTextFileSync(join(nestedDir, "_quarto.yml"), "project:\n type: default\n");
384+
writeDefaultProject(nestedDir);
388385
return Promise.resolve();
389386
},
390387
cwd: () => nestedDir,
@@ -464,14 +461,12 @@ testQuartoCmd(
464461
],
465462
{
466463
setup: () => {
467-
Deno.writeTextFileSync(join(nestedOverwriteDir, "_quarto.yml"), "project:\n type: default\n");
464+
writeDefaultProject(nestedOverwriteDir);
468465
// Create existing _brand/images directory with files
469-
const imagesDir = join(nestedOverwriteDir, "_brand", "images");
470-
ensureDirSync(imagesDir);
471466
// This file exists in source - should be overwritten
472-
Deno.writeTextFileSync(join(imagesDir, "logo.png"), "old logo\n");
467+
writeFixture(nestedOverwriteDir, "_brand/images/logo.png", "old logo\n");
473468
// This file does NOT exist in source - should be preserved
474-
Deno.writeTextFileSync(join(imagesDir, "unrelated.png"), "keep me nested");
469+
writeFixture(nestedOverwriteDir, "_brand/images/unrelated.png", "keep me nested");
475470
return Promise.resolve();
476471
},
477472
cwd: () => nestedOverwriteDir,
@@ -521,13 +516,11 @@ testQuartoCmd(
521516
],
522517
{
523518
setup: () => {
524-
Deno.writeTextFileSync(join(dryRunNestedDir, "_quarto.yml"), "project:\n type: default\n");
519+
writeDefaultProject(dryRunNestedDir);
525520
// Create existing _brand/images directory with only logo.png (not header.png)
526-
const imagesDir = join(dryRunNestedDir, "_brand", "images");
527-
ensureDirSync(imagesDir);
528-
Deno.writeTextFileSync(join(imagesDir, "logo.png"), "old logo\n");
521+
writeFixture(dryRunNestedDir, "_brand/images/logo.png", "old logo\n");
529522
// Also create _brand.yml so we're only testing nested behavior
530-
Deno.writeTextFileSync(join(dryRunNestedDir, "_brand", "_brand.yml"), "meta:\n name: Old\n");
523+
writeFixture(dryRunNestedDir, "_brand/_brand.yml", "meta:\n name: Old\n");
531524
return Promise.resolve();
532525
},
533526
cwd: () => dryRunNestedDir,
@@ -565,11 +558,9 @@ testQuartoCmd(
565558
],
566559
{
567560
setup: () => {
568-
Deno.writeTextFileSync(join(nestedNewSubdirDir, "_quarto.yml"), "project:\n type: default\n");
561+
writeDefaultProject(nestedNewSubdirDir);
569562
// Create _brand/ but NOT images/ subdirectory
570-
const brandDir = join(nestedNewSubdirDir, "_brand");
571-
ensureDirSync(brandDir);
572-
Deno.writeTextFileSync(join(brandDir, "_brand.yml"), "meta:\n name: Old Brand\n");
563+
writeFixture(nestedNewSubdirDir, "_brand/_brand.yml", "meta:\n name: Old Brand\n");
573564
return Promise.resolve();
574565
},
575566
cwd: () => nestedNewSubdirDir,
@@ -610,11 +601,9 @@ testQuartoCmd(
610601
],
611602
{
612603
setup: () => {
613-
Deno.writeTextFileSync(join(dryRunNewSubdirDir, "_quarto.yml"), "project:\n type: default\n");
604+
writeDefaultProject(dryRunNewSubdirDir);
614605
// Create _brand/ but NOT images/ subdirectory
615-
const brandDir = join(dryRunNewSubdirDir, "_brand");
616-
ensureDirSync(brandDir);
617-
Deno.writeTextFileSync(join(brandDir, "_brand.yml"), "meta:\n name: Old\n");
606+
writeFixture(dryRunNewSubdirDir, "_brand/_brand.yml", "meta:\n name: Old\n");
618607
return Promise.resolve();
619608
},
620609
cwd: () => dryRunNewSubdirDir,
@@ -659,11 +648,9 @@ testQuartoCmd(
659648
],
660649
{
661650
setup: () => {
662-
Deno.writeTextFileSync(join(emptyDirCleanupDir, "_quarto.yml"), "project:\n type: default\n");
651+
writeDefaultProject(emptyDirCleanupDir);
663652
// Create _brand/extras/ with a file not in source
664-
const extrasDir = join(emptyDirCleanupDir, "_brand", "extras");
665-
ensureDirSync(extrasDir);
666-
Deno.writeTextFileSync(join(extrasDir, "orphan.txt"), "this file will be removed");
653+
writeFixture(emptyDirCleanupDir, "_brand/extras/orphan.txt", "this file will be removed");
667654
return Promise.resolve();
668655
},
669656
cwd: () => emptyDirCleanupDir,
@@ -708,11 +695,9 @@ testQuartoCmd(
708695
],
709696
{
710697
setup: () => {
711-
Deno.writeTextFileSync(join(deepNestedCleanupDir, "_quarto.yml"), "project:\n type: default\n");
698+
writeDefaultProject(deepNestedCleanupDir);
712699
// Create _brand/deep/nested/path/ with a file not in source
713-
const deepDir = join(deepNestedCleanupDir, "_brand", "deep", "nested", "path");
714-
ensureDirSync(deepDir);
715-
Deno.writeTextFileSync(join(deepDir, "orphan.txt"), "deeply nested orphan");
700+
writeFixture(deepNestedCleanupDir, "_brand/deep/nested/path/orphan.txt", "deeply nested orphan");
716701
return Promise.resolve();
717702
},
718703
cwd: () => deepNestedCleanupDir,
@@ -772,7 +757,7 @@ testQuartoCmd(
772757
],
773758
{
774759
setup: () => {
775-
Deno.writeTextFileSync(join(brandExtDir, "_quarto.yml"), "project:\n type: default\n");
760+
writeDefaultProject(brandExtDir);
776761
return Promise.resolve();
777762
},
778763
cwd: () => brandExtDir,
@@ -807,7 +792,7 @@ testQuartoCmd(
807792
],
808793
{
809794
setup: () => {
810-
Deno.writeTextFileSync(join(brandExtDryRunDir, "_quarto.yml"), "project:\n type: default\n");
795+
writeDefaultProject(brandExtDryRunDir);
811796
return Promise.resolve();
812797
},
813798
cwd: () => brandExtDryRunDir,
@@ -853,7 +838,7 @@ testQuartoCmd(
853838
],
854839
{
855840
setup: () => {
856-
Deno.writeTextFileSync(join(brandExtSubdirDir, "_quarto.yml"), "project:\n type: default\n");
841+
writeDefaultProject(brandExtSubdirDir);
857842
return Promise.resolve();
858843
},
859844
cwd: () => brandExtSubdirDir,

‎tests/smoke/use/template-ai-config.test.ts‎

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,42 @@
99

1010
import { testQuartoCmd } from "../../test.ts";
1111
import { fileExists, noErrorsOrWarnings, pathDoNotExists } from "../../verify.ts";
12+
import { writeFixture } from "../../utils.ts";
1213
import { join } from "../../../src/deno_ral/path.ts";
1314
import { ensureDirSync } from "../../../src/deno_ral/fs.ts";
1415

1516
const tempDir = Deno.makeTempDirSync();
1617

1718
// Create a mock template source with AI config files
1819
const templateSourceDir = join(tempDir, "template-source");
19-
ensureDirSync(templateSourceDir);
20-
Deno.writeTextFileSync(
21-
join(templateSourceDir, "template.qmd"),
20+
writeFixture(
21+
templateSourceDir,
22+
"template.qmd",
2223
"---\ntitle: Template Document\n---\n\nThis is a template document."
2324
);
24-
Deno.writeTextFileSync(
25-
join(templateSourceDir, "CLAUDE.md"),
25+
writeFixture(
26+
templateSourceDir,
27+
"CLAUDE.md",
2628
"# Claude Configuration\n\nThis should be excluded."
2729
);
28-
Deno.writeTextFileSync(
29-
join(templateSourceDir, "AGENTS.md"),
30+
writeFixture(
31+
templateSourceDir,
32+
"AGENTS.md",
3033
"# Agents Configuration\n\nThis should be excluded."
3134
);
32-
Deno.writeTextFileSync(
33-
join(templateSourceDir, "CLAUDE.local.md"),
35+
writeFixture(
36+
templateSourceDir,
37+
"CLAUDE.local.md",
3438
"# Claude Local Configuration\n\nThis should be excluded."
3539
);
36-
Deno.writeTextFileSync(
37-
join(templateSourceDir, "AGENTS.local.md"),
40+
writeFixture(
41+
templateSourceDir,
42+
"AGENTS.local.md",
3843
"# Agents Local Configuration\n\nThis should be excluded."
3944
);
40-
Deno.writeTextFileSync(
41-
join(templateSourceDir, "README.md"),
45+
writeFixture(
46+
templateSourceDir,
47+
"README.md",
4248
"# Template README\n\nThis should also be excluded."
4349
);
4450

0 commit comments

Comments
 (0)