Path: blob/main/tests/smoke/project/project-output-dir-safety.test.ts
12925 views
/*1* project-output-dir-safety.test.ts2*3* Test for issue #13892: output-dir configurations should not delete project files4*5* Copyright (C) 2020-2025 Posit Software, PBC6*/7import { docs } from "../../utils.ts";89import { join } from "../../../src/deno_ral/path.ts";10import { existsSync } from "../../../src/deno_ral/fs.ts";11import { testQuartoCmd } from "../../test.ts";12import { fileExists, noErrors } from "../../verify.ts";1314// Helper to clean up website output files from a directory15// Used when output-dir points to the project directory itself16async function cleanWebsiteOutput(dir: string) {17const filesToRemove = ["index.html", "test.html", "search.json"];18const dirsToRemove = ["site_libs", ".quarto"];1920for (const file of filesToRemove) {21const path = join(dir, file);22if (existsSync(path)) {23await Deno.remove(path);24}25}26for (const subdir of dirsToRemove) {27const path = join(dir, subdir);28if (existsSync(path)) {29await Deno.remove(path, { recursive: true });30}31}32}3334// Helper to create output-dir safety tests35function testOutputDirSafety(36name: string,37outputDir: string | null, // null means output is in project dir (website type)38) {39const testDir = docs(`project/output-dir-${name}`);40const dir = join(Deno.cwd(), testDir);41const outputPath = outputDir ? join(dir, outputDir) : dir;4243testQuartoCmd(44"render",45[testDir],46[47noErrors,48fileExists(join(dir, "marker.txt")), // Project file must survive49fileExists(join(outputPath, "test.html")), // Output created correctly50],51{52teardown: async () => {53// Clean up rendered output54if (outputDir) {55// Subdirectory case - remove the whole output dir56if (existsSync(outputPath)) {57await Deno.remove(outputPath, { recursive: true });58}59// Clean up .quarto directory60const quartoDir = join(dir, ".quarto");61if (existsSync(quartoDir)) {62await Deno.remove(quartoDir, { recursive: true });63}64} else {65// In-place website case - clean up website output files only66await cleanWebsiteOutput(dir);67}68},69},70);71}7273// Test 1: output-dir: ./ (the bug case from #13892)74testOutputDirSafety("safety", null);7576// Test 2: output-dir: . (without trailing slash)77testOutputDirSafety("dot", null);7879// Test 3: output-dir: _output (normal subdirectory case)80testOutputDirSafety("subdir", "_output");8182// Test 4: output-dir: ../dirname (parent traversal back to project dir)83// This tests the case where output-dir references the project directory84// via parent traversal (e.g., project in "quarto-proj", output-dir: "../quarto-proj")85testOutputDirSafety("parent-ref", null);868788