From 5c4e8ea384ffa3ed7c8c6ce6097cc1678a2a5ea3 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 3 Apr 2025 13:09:47 +0200 Subject: [PATCH 01/12] Add more context in info log when running post render script --- src/command/render/project.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command/render/project.ts b/src/command/render/project.ts index cf16d99b5d..18e1844ae7 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -942,7 +942,7 @@ async function runScripts( const script = args[0]; if (progress && !quiet) { - info(colors.bold(colors.blue(`${script}`))); + info(colors.bold(colors.blue(`Running script '${script}'`))); } const handler = handlerForScript(script); From 8b7c0357edf3a342c17a3ef360fcd96c6185fc57 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 3 Apr 2025 13:23:03 +0200 Subject: [PATCH 02/12] Let pre/post render script know if progress should be shown. This will allows scripts to be quiet --- src/command/render/project.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/command/render/project.ts b/src/command/render/project.ts index 18e1844ae7..f31c6b5d23 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -303,6 +303,8 @@ export async function renderProject( ...(projectRenderConfig.behavior.renderAll ? { QUARTO_PROJECT_RENDER_ALL: "1" } : {}), + "QUARTO_PROJECT_SCRIPT_PROGRESS": + progress && !projectRenderConfig.options.flags?.quiet ? "1" : "0", }; // run pre-render step if we are rendering all files From 77ff31b18a2afcf6716bf8ebc7b8bd87a0a50817 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 3 Apr 2025 13:30:47 +0200 Subject: [PATCH 03/12] make it clearer that showing script progress consider also the `--quiet` option --- src/command/render/project.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/command/render/project.ts b/src/command/render/project.ts index f31c6b5d23..f68f452793 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -269,8 +269,10 @@ export async function renderProject( await ensureGitignore(context.dir); // determine whether pre and post render steps should show progress - const progress = !!projectRenderConfig.options.progress || - (projectRenderConfig.filesToRender.length > 1); + const progress = ( + !!projectRenderConfig.options.progress || + (projectRenderConfig.filesToRender.length > 1) + ) && !projectRenderConfig.options.flags?.quiet; // if there is an output dir then remove it if clean is specified if ( @@ -303,8 +305,7 @@ export async function renderProject( ...(projectRenderConfig.behavior.renderAll ? { QUARTO_PROJECT_RENDER_ALL: "1" } : {}), - "QUARTO_PROJECT_SCRIPT_PROGRESS": - progress && !projectRenderConfig.options.flags?.quiet ? "1" : "0", + "QUARTO_PROJECT_SCRIPT_PROGRESS": progress ? "1" : "0", }; // run pre-render step if we are rendering all files @@ -943,7 +944,7 @@ async function runScripts( const args = parseShellRunCommand(scripts[i]); const script = args[0]; - if (progress && !quiet) { + if (progress) { info(colors.bold(colors.blue(`Running script '${script}'`))); } From 21ee6a25ae5fe1cdbf4073dd5fe618ecb437bf7e Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 3 Apr 2025 13:41:15 +0200 Subject: [PATCH 04/12] Set the env var in `runScript` directly which seems a better way to take into account `quiet` option in addition to progress. --- src/command/render/project.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/command/render/project.ts b/src/command/render/project.ts index f68f452793..1e902d2523 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -269,10 +269,8 @@ export async function renderProject( await ensureGitignore(context.dir); // determine whether pre and post render steps should show progress - const progress = ( - !!projectRenderConfig.options.progress || - (projectRenderConfig.filesToRender.length > 1) - ) && !projectRenderConfig.options.flags?.quiet; + const progress = !!projectRenderConfig.options.progress || + (projectRenderConfig.filesToRender.length > 1); // if there is an output dir then remove it if clean is specified if ( @@ -305,7 +303,6 @@ export async function renderProject( ...(projectRenderConfig.behavior.renderAll ? { QUARTO_PROJECT_RENDER_ALL: "1" } : {}), - "QUARTO_PROJECT_SCRIPT_PROGRESS": progress ? "1" : "0", }; // run pre-render step if we are rendering all files @@ -940,24 +937,27 @@ async function runScripts( quiet: boolean, env?: { [key: string]: string }, ) { + // initialize the environment if needed + if (env) { + env = { + ...env, + }; + } else { + env = {}; + } + if (!env) throw new Error("should never get here"); + for (let i = 0; i < scripts.length; i++) { const args = parseShellRunCommand(scripts[i]); const script = args[0]; - if (progress) { + if (progress && !quiet) { info(colors.bold(colors.blue(`Running script '${script}'`))); + env["QUARTO_PROJECT_SCRIPT_PROGRESS"] = "1"; } const handler = handlerForScript(script); if (handler) { - if (env) { - env = { - ...env, - }; - } else { - env = {}; - } - if (!env) throw new Error("should never get here"); const input = Deno.env.get("QUARTO_USE_FILE_FOR_PROJECT_INPUT_FILES"); const output = Deno.env.get("QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES"); if (input) { From 8214b7ed3d61196de16db64b0ea50b2ec625d271 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 8 Apr 2025 20:49:35 +0200 Subject: [PATCH 05/12] Refactor by using a default handler --- src/command/render/project.ts | 38 ++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/command/render/project.ts b/src/command/render/project.ts index 1e902d2523..6b256de478 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -78,6 +78,7 @@ import { Format } from "../../config/types.ts"; import { fileExecutionEngine } from "../../execute/engine.ts"; import { projectContextForDirectory } from "../../project/project-context.ts"; import { ProjectType } from "../../project/types/types.ts"; +import { RunHandlerOptions } from "../../core/run/types.ts"; const noMutationValidations = ( projType: ProjectType, @@ -956,16 +957,30 @@ async function runScripts( env["QUARTO_PROJECT_SCRIPT_PROGRESS"] = "1"; } - const handler = handlerForScript(script); - if (handler) { - const input = Deno.env.get("QUARTO_USE_FILE_FOR_PROJECT_INPUT_FILES"); - const output = Deno.env.get("QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES"); - if (input) { - env["QUARTO_USE_FILE_FOR_PROJECT_INPUT_FILES"] = input; - } - if (output) { - env["QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES"] = output; - } + const handler = handlerForScript(script) ?? { + run: async ( + script: string, + args: string[], + _stdin?: string, + options?: RunHandlerOptions, + ) => { + return await execProcess({ + cmd: [script, ...args], + cwd: options?.cwd, + stdout: options?.stdout, + env: options?.env, + }); + }, + }; + + const input = Deno.env.get("QUARTO_USE_FILE_FOR_PROJECT_INPUT_FILES"); + const output = Deno.env.get("QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES"); + if (input) { + env["QUARTO_USE_FILE_FOR_PROJECT_INPUT_FILES"] = input; + } + if (output) { + env["QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES"] = output; + } const result = await handler.run(script, args.splice(1), undefined, { cwd: projDir, @@ -977,8 +992,7 @@ async function runScripts( } } else { const result = await execProcess({ - cmd: args[0], - args: args.slice(1), + cmd: args, cwd: projDir, stdout: quiet ? "piped" : "inherit", env, From 1b7882b5421404e6d91fa12a27f06f459172e9a2 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 8 Apr 2025 20:53:38 +0200 Subject: [PATCH 06/12] Use one env var per argument QUIET VS PROGRESS --- src/command/render/project.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/command/render/project.ts b/src/command/render/project.ts index 6b256de478..bdaca07db8 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -948,13 +948,16 @@ async function runScripts( } if (!env) throw new Error("should never get here"); + // Pass some argument as environment + env["QUARTO_PROJECT_SCRIPT_PROGRESS"] = progress ? "1" : "0"; + env["QUARTO_PROJECT_SCRIPT_QUIET"] = quiet ? "1" : "0"; + for (let i = 0; i < scripts.length; i++) { const args = parseShellRunCommand(scripts[i]); const script = args[0]; if (progress && !quiet) { info(colors.bold(colors.blue(`Running script '${script}'`))); - env["QUARTO_PROJECT_SCRIPT_PROGRESS"] = "1"; } const handler = handlerForScript(script) ?? { From f5330c11ff722e3df78fb39d238189758945c2ed Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Wed, 18 Jun 2025 17:33:59 +0200 Subject: [PATCH 07/12] fix bad merge conflict in rebasing --- src/command/render/project.ts | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/command/render/project.ts b/src/command/render/project.ts index bdaca07db8..9b0dfe69fa 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -968,7 +968,8 @@ async function runScripts( options?: RunHandlerOptions, ) => { return await execProcess({ - cmd: [script, ...args], + cmd: script, + args: args, cwd: options?.cwd, stdout: options?.stdout, env: options?.env, @@ -985,24 +986,13 @@ async function runScripts( env["QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES"] = output; } - const result = await handler.run(script, args.splice(1), undefined, { - cwd: projDir, - stdout: quiet ? "piped" : "inherit", - env, - }); - if (!result.success) { - throw new Error(); - } - } else { - const result = await execProcess({ - cmd: args, - cwd: projDir, - stdout: quiet ? "piped" : "inherit", - env, - }); - if (!result.success) { - throw new Error(); - } + const result = await handler.run(script, args.splice(1), undefined, { + cwd: projDir, + stdout: quiet ? "piped" : "inherit", + env, + }); + if (!result.success) { + throw new Error(); } } if (scripts.length > 0) { From b1d5648efcf08dd3c078971fa02161955e3865db Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 19 Feb 2026 18:40:45 +0100 Subject: [PATCH 08/12] Use slice instead of splice and add changelog entry Use args.slice(1) instead of args.splice(1) to avoid unnecessary array mutation. Add changelog entry for new env vars and logging. --- news/changelog-1.9.md | 1 + src/command/render/project.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/news/changelog-1.9.md b/news/changelog-1.9.md index ee4e744b22..8c1e5fafb8 100644 --- a/news/changelog-1.9.md +++ b/news/changelog-1.9.md @@ -109,6 +109,7 @@ All changes included in 1.9: ## Projects +- ([#12444](https://github.com/quarto-dev/quarto-cli/pull/12444)): Improve pre/post render script logging with `Running script` prefix and add `QUARTO_PROJECT_SCRIPT_PROGRESS` and `QUARTO_PROJECT_SCRIPT_QUIET` environment variables so scripts can adapt their output. - ([#13892](https://github.com/quarto-dev/quarto-cli/issues/13892)): Fix `output-dir: ./` deleting entire project directory. `output-dir` must be a subdirectory of the project directory and check is now better to avoid deleting the project itself when it revolves to the same path. ### `website` diff --git a/src/command/render/project.ts b/src/command/render/project.ts index 9b0dfe69fa..9093275bab 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -986,7 +986,7 @@ async function runScripts( env["QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES"] = output; } - const result = await handler.run(script, args.splice(1), undefined, { + const result = await handler.run(script, args.slice(1), undefined, { cwd: projDir, stdout: quiet ? "piped" : "inherit", env, From e94697b8f603d1c572c2daa1c00bed5f6ae77950 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Sat, 21 Feb 2026 11:24:06 +0100 Subject: [PATCH 09/12] 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 --- llm-docs/testing-patterns.md | 93 +++++++++++++++++++ .../prepost/script-env-vars/.gitignore | 2 + .../prepost/script-env-vars/_quarto.yml | 10 ++ .../project/prepost/script-env-vars/about.qmd | 5 + .../prepost/script-env-vars/check-env.ts | 6 ++ .../project/prepost/script-env-vars/index.qmd | 5 + tests/smoke/project/project-prepost.test.ts | 31 ++++++- 7 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 tests/docs/project/prepost/script-env-vars/.gitignore create mode 100644 tests/docs/project/prepost/script-env-vars/_quarto.yml create mode 100644 tests/docs/project/prepost/script-env-vars/about.qmd create mode 100644 tests/docs/project/prepost/script-env-vars/check-env.ts create mode 100644 tests/docs/project/prepost/script-env-vars/index.qmd diff --git a/llm-docs/testing-patterns.md b/llm-docs/testing-patterns.md index aa961a4fce..b2ee391346 100644 --- a/llm-docs/testing-patterns.md +++ b/llm-docs/testing-patterns.md @@ -88,6 +88,62 @@ testQuartoCmd( - Use absolute paths with `join()` for file verification - Clean up output directories in teardown +### Pre/Post Render Script Tests + +For testing pre-render or post-render scripts that run during project rendering: + +```typescript +import { docs } from "../../utils.ts"; +import { join } from "../../../src/deno_ral/path.ts"; +import { existsSync } from "../../../src/deno_ral/fs.ts"; +import { testQuartoCmd } from "../../test.ts"; +import { noErrors, validJsonWithFields } from "../../verify.ts"; +import { safeRemoveIfExists } from "../../../src/core/path.ts"; + +const projectDir = docs("project/prepost/my-test"); +const projectDirAbs = join(Deno.cwd(), projectDir); +const dumpPath = join(projectDirAbs, "output.json"); +const outDir = join(projectDirAbs, "_site"); + +testQuartoCmd( + "render", + [projectDir], + [ + noErrors, + validJsonWithFields(dumpPath, { + expected: "value", + }), + ], + { + teardown: async () => { + safeRemoveIfExists(dumpPath); + if (existsSync(outDir)) { + await Deno.remove(outDir, { recursive: true }); + } + }, + }, +); +``` + +**Fixture structure:** + +``` +tests/docs/project/prepost/my-test/ +├── _quarto.yml # project config with pre-render/post-render scripts +├── index.qmd # minimal page (website needs at least one) +├── check-env.ts # pre/post-render script (Deno TypeScript) +└── .gitignore # exclude .quarto/ and *.quarto_ipynb +``` + +**Key points:** +- Pre/post-render scripts run as subprocesses with `cwd` set to the project directory +- Scripts access environment variables via `Deno.env.get()` and can write files for verification +- Use `validJsonWithFields` for JSON file verification (parses and compares field values exactly) +- Use `ensureFileRegexMatches` for non-JSON files or when regex matching is needed +- The file dump pattern (script writes JSON, test reads it) is useful for verifying env vars and other runtime state +- Clean up both the dump file and the output directory in teardown +- Existing fixtures: `tests/docs/project/prepost/` (mutate-render-list, invalid-mutate, extension, issue-10828, script-env-vars) + ### Extension Template Tests For testing `quarto use template`: @@ -164,6 +220,43 @@ folderExists(path: string) directoryEmptyButFor(dir: string, allowedFiles: string[]) ``` +### Content Verifiers + +```typescript +// Regex match on file contents (matches required, noMatches must be absent) +ensureFileRegexMatches(file: string, matches: (string | RegExp)[], noMatches?: (string | RegExp)[]) + +// Regex match on CSS files linked from HTML +ensureCssRegexMatches(file: string, matches: (string | RegExp)[], noMatches?: (string | RegExp)[]) + +// Check HTML elements exist or don't exist (CSS selectors) +ensureHtmlElements(file: string, noElements: string[], elements: string[]) + +// Verify JSON structure has expected fields +validJsonWithFields(file: string, fields: string[]) + +// Check output message at specific log level +printsMessage(options: { level: string, regex: RegExp }) +``` + +### Assertion Helpers + +```typescript +// Assert path exists (throws if missing) +verifyPath(path: string) + +// Assert path does NOT exist (throws if present) +verifyNoPath(path: string) +``` + +### Cleanup Helpers + +```typescript +// Safe file removal (no error if missing) - from src/core/path.ts +import { safeRemoveIfExists } from "../../../src/core/path.ts"; +safeRemoveIfExists(path: string) +``` + ### Path Helpers ```typescript diff --git a/tests/docs/project/prepost/script-env-vars/.gitignore b/tests/docs/project/prepost/script-env-vars/.gitignore new file mode 100644 index 0000000000..ad293093b0 --- /dev/null +++ b/tests/docs/project/prepost/script-env-vars/.gitignore @@ -0,0 +1,2 @@ +/.quarto/ +**/*.quarto_ipynb diff --git a/tests/docs/project/prepost/script-env-vars/_quarto.yml b/tests/docs/project/prepost/script-env-vars/_quarto.yml new file mode 100644 index 0000000000..99d9860417 --- /dev/null +++ b/tests/docs/project/prepost/script-env-vars/_quarto.yml @@ -0,0 +1,10 @@ +project: + type: website + pre-render: check-env.ts + +website: + title: "script-env-vars" + +format: + html: + theme: cosmo diff --git a/tests/docs/project/prepost/script-env-vars/about.qmd b/tests/docs/project/prepost/script-env-vars/about.qmd new file mode 100644 index 0000000000..29d83a0e11 --- /dev/null +++ b/tests/docs/project/prepost/script-env-vars/about.qmd @@ -0,0 +1,5 @@ +--- +title: About +--- + +About page diff --git a/tests/docs/project/prepost/script-env-vars/check-env.ts b/tests/docs/project/prepost/script-env-vars/check-env.ts new file mode 100644 index 0000000000..2753be45e0 --- /dev/null +++ b/tests/docs/project/prepost/script-env-vars/check-env.ts @@ -0,0 +1,6 @@ +const env = { + progress: Deno.env.get("QUARTO_PROJECT_SCRIPT_PROGRESS") ?? null, + quiet: Deno.env.get("QUARTO_PROJECT_SCRIPT_QUIET") ?? null, +}; + +Deno.writeTextFileSync("env-dump.json", JSON.stringify(env)); diff --git a/tests/docs/project/prepost/script-env-vars/index.qmd b/tests/docs/project/prepost/script-env-vars/index.qmd new file mode 100644 index 0000000000..2af2fce5ba --- /dev/null +++ b/tests/docs/project/prepost/script-env-vars/index.qmd @@ -0,0 +1,5 @@ +--- +title: Test +--- + +Hello diff --git a/tests/smoke/project/project-prepost.test.ts b/tests/smoke/project/project-prepost.test.ts index 3caf6d7241..da0f7054bf 100644 --- a/tests/smoke/project/project-prepost.test.ts +++ b/tests/smoke/project/project-prepost.test.ts @@ -9,7 +9,7 @@ import { docs } from "../../utils.ts"; import { join } from "../../../src/deno_ral/path.ts"; import { existsSync } from "../../../src/deno_ral/fs.ts"; import { testQuartoCmd } from "../../test.ts"; -import { fileExists, noErrors, printsMessage, verifyNoPath, verifyPath } from "../../verify.ts"; +import { fileExists, noErrors, printsMessage, validJsonWithFields, verifyNoPath, verifyPath } from "../../verify.ts"; import { normalizePath, safeRemoveIfExists } from "../../../src/core/path.ts"; const renderDir = docs("project/prepost/mutate-render-list"); @@ -96,4 +96,31 @@ testQuartoCmd( safeRemoveIfExists(outputPath); } } - ) \ No newline at end of file + ) + +// Verify that pre-render scripts receive QUARTO_PROJECT_SCRIPT_PROGRESS +// and QUARTO_PROJECT_SCRIPT_QUIET environment variables +const scriptEnvDir = docs("project/prepost/script-env-vars"); +const scriptEnvDirAbs = join(Deno.cwd(), scriptEnvDir); +const envDumpPath = join(scriptEnvDirAbs, "env-dump.json"); +const scriptEnvOutDir = join(scriptEnvDirAbs, "_site"); + +testQuartoCmd( + "render", + [scriptEnvDir], + [ + noErrors, + validJsonWithFields(envDumpPath, { + progress: "1", + quiet: "0", + }), + ], + { + teardown: async () => { + safeRemoveIfExists(envDumpPath); + if (existsSync(scriptEnvOutDir)) { + await Deno.remove(scriptEnvOutDir, { recursive: true }); + } + }, + }, +); \ No newline at end of file From 88abe51dc9562076a4f9a759e8bcfe84a43a0986 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Sat, 21 Feb 2026 11:25:42 +0100 Subject: [PATCH 10/12] Update gitignores in test created by newest quarto --- tests/docs/project/prepost/extension/.gitignore | 2 ++ tests/docs/project/prepost/invalid-mutate/.gitignore | 2 ++ tests/docs/project/prepost/issue-10828/.gitignore | 2 ++ tests/docs/project/prepost/mutate-render-list/.gitignore | 2 ++ 4 files changed, 8 insertions(+) create mode 100644 tests/docs/project/prepost/extension/.gitignore diff --git a/tests/docs/project/prepost/extension/.gitignore b/tests/docs/project/prepost/extension/.gitignore new file mode 100644 index 0000000000..ad293093b0 --- /dev/null +++ b/tests/docs/project/prepost/extension/.gitignore @@ -0,0 +1,2 @@ +/.quarto/ +**/*.quarto_ipynb diff --git a/tests/docs/project/prepost/invalid-mutate/.gitignore b/tests/docs/project/prepost/invalid-mutate/.gitignore index 075b2542af..0e3521a7d0 100644 --- a/tests/docs/project/prepost/invalid-mutate/.gitignore +++ b/tests/docs/project/prepost/invalid-mutate/.gitignore @@ -1 +1,3 @@ /.quarto/ + +**/*.quarto_ipynb diff --git a/tests/docs/project/prepost/issue-10828/.gitignore b/tests/docs/project/prepost/issue-10828/.gitignore index 075b2542af..0e3521a7d0 100644 --- a/tests/docs/project/prepost/issue-10828/.gitignore +++ b/tests/docs/project/prepost/issue-10828/.gitignore @@ -1 +1,3 @@ /.quarto/ + +**/*.quarto_ipynb diff --git a/tests/docs/project/prepost/mutate-render-list/.gitignore b/tests/docs/project/prepost/mutate-render-list/.gitignore index 075b2542af..0e3521a7d0 100644 --- a/tests/docs/project/prepost/mutate-render-list/.gitignore +++ b/tests/docs/project/prepost/mutate-render-list/.gitignore @@ -1 +1,3 @@ /.quarto/ + +**/*.quarto_ipynb From 7d06bfd6d49cdc14c7b56020fafdc0598d1db10c Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Sat, 21 Feb 2026 11:29:35 +0100 Subject: [PATCH 11/12] Fix missing _site cleanup in extension and issue-10828 prepost test teardowns Both tests render website projects but only cleaned up their specific side-effect files, leaving _site/ directories behind after each run. Co-Authored-By: Claude Opus 4.6 --- tests/smoke/project/project-prepost.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/smoke/project/project-prepost.test.ts b/tests/smoke/project/project-prepost.test.ts index da0f7054bf..10b5b485a1 100644 --- a/tests/smoke/project/project-prepost.test.ts +++ b/tests/smoke/project/project-prepost.test.ts @@ -75,6 +75,10 @@ testQuartoCmd( const path = join(docs("project/prepost/extension"), "i-was-created.txt"); verifyPath(path); safeRemoveIfExists(path); + const siteDir = join(docs("project/prepost/extension"), "_site"); + if (existsSync(siteDir)) { + await Deno.remove(siteDir, { recursive: true }); + } } }); @@ -94,6 +98,10 @@ testQuartoCmd( safeRemoveIfExists(inputPath); verifyPath(outputPath); safeRemoveIfExists(outputPath); + const siteDir = join(docs("project/prepost/issue-10828"), "_site"); + if (existsSync(siteDir)) { + await Deno.remove(siteDir, { recursive: true }); + } } } ) From d59c890f16949843687fcfd88fff5e3910c5179b Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Sat, 21 Feb 2026 11:31:23 +0100 Subject: [PATCH 12/12] Fix validJsonWithFields signature in docs and add trailing newline The llm-docs documented validJsonWithFields with fields: string[] but the actual signature takes Record. Also adds missing trailing newline to project-prepost.test.ts. Co-Authored-By: Claude Opus 4.6 --- llm-docs/testing-patterns.md | 4 ++-- tests/smoke/project/project-prepost.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llm-docs/testing-patterns.md b/llm-docs/testing-patterns.md index b2ee391346..3d0c65a084 100644 --- a/llm-docs/testing-patterns.md +++ b/llm-docs/testing-patterns.md @@ -232,8 +232,8 @@ ensureCssRegexMatches(file: string, matches: (string | RegExp)[], noMatches?: (s // Check HTML elements exist or don't exist (CSS selectors) ensureHtmlElements(file: string, noElements: string[], elements: string[]) -// Verify JSON structure has expected fields -validJsonWithFields(file: string, fields: string[]) +// Verify JSON structure has expected fields (parses JSON, compares values with deep equality) +validJsonWithFields(file: string, fields: Record) // Check output message at specific log level printsMessage(options: { level: string, regex: RegExp }) diff --git a/tests/smoke/project/project-prepost.test.ts b/tests/smoke/project/project-prepost.test.ts index 10b5b485a1..b7895f4a5f 100644 --- a/tests/smoke/project/project-prepost.test.ts +++ b/tests/smoke/project/project-prepost.test.ts @@ -131,4 +131,4 @@ testQuartoCmd( } }, }, -); \ No newline at end of file +);