Skip to content

Commit e94697b

Browse files
cdervclaude
andcommitted
Add test for QUARTO_PROJECT_SCRIPT_PROGRESS and QUARTO_PROJECT_SCRIPT_QUIET env vars
Pre/post render scripts now receive these env vars but had no test coverage. The new test fixture uses a pre-render script to dump the env var values to a JSON file, then verifies the values match expectations (progress=1 for multi-file projects, quiet=0 without --quiet flag). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b1d5648 commit e94697b

7 files changed

Lines changed: 150 additions & 2 deletions

File tree

llm-docs/testing-patterns.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,62 @@ testQuartoCmd(
8888
- Use absolute paths with `join()` for file verification
8989
- Clean up output directories in teardown
9090

91+
### Pre/Post Render Script Tests
92+
93+
For testing pre-render or post-render scripts that run during project rendering:
94+
95+
```typescript
96+
import { docs } from "../../utils.ts";
97+
import { join } from "../../../src/deno_ral/path.ts";
98+
import { existsSync } from "../../../src/deno_ral/fs.ts";
99+
import { testQuartoCmd } from "../../test.ts";
100+
import { noErrors, validJsonWithFields } from "../../verify.ts";
101+
import { safeRemoveIfExists } from "../../../src/core/path.ts";
102+
103+
const projectDir = docs("project/prepost/my-test");
104+
const projectDirAbs = join(Deno.cwd(), projectDir);
105+
const dumpPath = join(projectDirAbs, "output.json");
106+
const outDir = join(projectDirAbs, "_site");
107+
108+
testQuartoCmd(
109+
"render",
110+
[projectDir],
111+
[
112+
noErrors,
113+
validJsonWithFields(dumpPath, {
114+
expected: "value",
115+
}),
116+
],
117+
{
118+
teardown: async () => {
119+
safeRemoveIfExists(dumpPath);
120+
if (existsSync(outDir)) {
121+
await Deno.remove(outDir, { recursive: true });
122+
}
123+
},
124+
},
125+
);
126+
```
127+
128+
**Fixture structure:**
129+
130+
```
131+
tests/docs/project/prepost/my-test/
132+
├── _quarto.yml # project config with pre-render/post-render scripts
133+
├── index.qmd # minimal page (website needs at least one)
134+
├── check-env.ts # pre/post-render script (Deno TypeScript)
135+
└── .gitignore # exclude .quarto/ and *.quarto_ipynb
136+
```
137+
138+
**Key points:**
139+
- Pre/post-render scripts run as subprocesses with `cwd` set to the project directory
140+
- Scripts access environment variables via `Deno.env.get()` and can write files for verification
141+
- Use `validJsonWithFields` for JSON file verification (parses and compares field values exactly)
142+
- Use `ensureFileRegexMatches` for non-JSON files or when regex matching is needed
143+
- The file dump pattern (script writes JSON, test reads it) is useful for verifying env vars and other runtime state
144+
- Clean up both the dump file and the output directory in teardown
145+
- Existing fixtures: `tests/docs/project/prepost/` (mutate-render-list, invalid-mutate, extension, issue-10828, script-env-vars)
146+
91147
### Extension Template Tests
92148

93149
For testing `quarto use template`:
@@ -164,6 +220,43 @@ folderExists(path: string)
164220
directoryEmptyButFor(dir: string, allowedFiles: string[])
165221
```
166222

223+
### Content Verifiers
224+
225+
```typescript
226+
// Regex match on file contents (matches required, noMatches must be absent)
227+
ensureFileRegexMatches(file: string, matches: (string | RegExp)[], noMatches?: (string | RegExp)[])
228+
229+
// Regex match on CSS files linked from HTML
230+
ensureCssRegexMatches(file: string, matches: (string | RegExp)[], noMatches?: (string | RegExp)[])
231+
232+
// Check HTML elements exist or don't exist (CSS selectors)
233+
ensureHtmlElements(file: string, noElements: string[], elements: string[])
234+
235+
// Verify JSON structure has expected fields
236+
validJsonWithFields(file: string, fields: string[])
237+
238+
// Check output message at specific log level
239+
printsMessage(options: { level: string, regex: RegExp })
240+
```
241+
242+
### Assertion Helpers
243+
244+
```typescript
245+
// Assert path exists (throws if missing)
246+
verifyPath(path: string)
247+
248+
// Assert path does NOT exist (throws if present)
249+
verifyNoPath(path: string)
250+
```
251+
252+
### Cleanup Helpers
253+
254+
```typescript
255+
// Safe file removal (no error if missing) - from src/core/path.ts
256+
import { safeRemoveIfExists } from "../../../src/core/path.ts";
257+
safeRemoveIfExists(path: string)
258+
```
259+
167260
### Path Helpers
168261

169262
```typescript
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/.quarto/
2+
**/*.quarto_ipynb
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
project:
2+
type: website
3+
pre-render: check-env.ts
4+
5+
website:
6+
title: "script-env-vars"
7+
8+
format:
9+
html:
10+
theme: cosmo
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
title: About
3+
---
4+
5+
About page
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const env = {
2+
progress: Deno.env.get("QUARTO_PROJECT_SCRIPT_PROGRESS") ?? null,
3+
quiet: Deno.env.get("QUARTO_PROJECT_SCRIPT_QUIET") ?? null,
4+
};
5+
6+
Deno.writeTextFileSync("env-dump.json", JSON.stringify(env));
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
title: Test
3+
---
4+
5+
Hello

tests/smoke/project/project-prepost.test.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { docs } from "../../utils.ts";
99
import { join } from "../../../src/deno_ral/path.ts";
1010
import { existsSync } from "../../../src/deno_ral/fs.ts";
1111
import { testQuartoCmd } from "../../test.ts";
12-
import { fileExists, noErrors, printsMessage, verifyNoPath, verifyPath } from "../../verify.ts";
12+
import { fileExists, noErrors, printsMessage, validJsonWithFields, verifyNoPath, verifyPath } from "../../verify.ts";
1313
import { normalizePath, safeRemoveIfExists } from "../../../src/core/path.ts";
1414

1515
const renderDir = docs("project/prepost/mutate-render-list");
@@ -96,4 +96,31 @@ testQuartoCmd(
9696
safeRemoveIfExists(outputPath);
9797
}
9898
}
99-
)
99+
)
100+
101+
// Verify that pre-render scripts receive QUARTO_PROJECT_SCRIPT_PROGRESS
102+
// and QUARTO_PROJECT_SCRIPT_QUIET environment variables
103+
const scriptEnvDir = docs("project/prepost/script-env-vars");
104+
const scriptEnvDirAbs = join(Deno.cwd(), scriptEnvDir);
105+
const envDumpPath = join(scriptEnvDirAbs, "env-dump.json");
106+
const scriptEnvOutDir = join(scriptEnvDirAbs, "_site");
107+
108+
testQuartoCmd(
109+
"render",
110+
[scriptEnvDir],
111+
[
112+
noErrors,
113+
validJsonWithFields(envDumpPath, {
114+
progress: "1",
115+
quiet: "0",
116+
}),
117+
],
118+
{
119+
teardown: async () => {
120+
safeRemoveIfExists(envDumpPath);
121+
if (existsSync(scriptEnvOutDir)) {
122+
await Deno.remove(scriptEnvOutDir, { recursive: true });
123+
}
124+
},
125+
},
126+
);

0 commit comments

Comments
 (0)