Path: blob/main/tests/smoke/create/create.test.ts
12926 views
/*1* create.test.ts2*3* Copyright (C) 2020-2022 Posit Software, PBC4*5*/67import { execProcess } from "../../../src/core/process.ts";8import { join } from "../../../src/deno_ral/path.ts";9import { walkSync } from "../../../src/deno_ral/fs.ts";10import { CreateResult } from "../../../src/command/create/cmd-types.ts";11import { assert } from "testing/asserts";12import { quartoDevCmd } from "../../utils.ts";1314const kCreateTypes: Record<string, string[]> = {15"project": ["website", "default", "book", "website:blog"],16"extension": [17"filter",18"shortcode",19"revealjs-plugin",20"journal",21"format:html",22"format:pdf",23"format:docx",24"format:revealjs",25"engine",26],27};2829const tempDir = Deno.makeTempDirSync();30for (const type of Object.keys(kCreateTypes)) {31for (const template of kCreateTypes[type]) {32Deno.test(`quarto create ${type} ${template}`, async (t) => {33// Configure the item to test34const artifactName = template.replaceAll(/:/gm, "");35const artifactPath = join(tempDir, artifactName);36const createDirective = {37type,38directive: {39directory: artifactPath,40template,41name: artifactName,42},43};4445// Create the artifact46let result: CreateResult | undefined = undefined;47await t.step(`> quarto ${type} ${template}`, async () => {48// test quarto cmd render49const cmd = [quartoDevCmd(), "create", "--json"];50const stdIn = JSON.stringify(createDirective);51const process = await execProcess({52cmd: cmd[0],53args: cmd.slice(1),54stdout: "piped",55stderr: "piped",56}, stdIn);57assert(process.success, process.stderr);58if (process.stdout) {59result = JSON.parse(process.stdout) as CreateResult;60}61assert(process.success, process.stderr);62});6364// Verify all created files are user-writable.65// NOTE: In dev environments, resource files are already writable (0o644),66// so this test passes even without ensureUserWritable. It guards against67// regressions; the unit test in file-permissions.test.ts covers the68// read-only → writable transition directly.69await t.step({70name: `> check writable ${type} ${template}`,71ignore: Deno.build.os === "windows",72fn: () => {73for (const entry of walkSync(artifactPath)) {74if (entry.isFile) {75const stat = Deno.statSync(entry.path);76assert(77stat.mode !== null && (stat.mode! & 0o200) !== 0,78`File ${entry.path} is not user-writable (mode: ${stat.mode?.toString(8)})`,79);80}81}82},83});8485// Render the artifact86await t.step(`> render ${type} ${template}`, async () => {87const path = result!.path;88const openfiles = result!.openfiles;89assert(90openfiles.length > 0,91`Artifact ${type} ${template} failed to produce any files to open.`,92);9394// Build engine extensions before rendering95if (template === "engine") {96const buildCmd = [quartoDevCmd(), "call", "build-ts-extension"];97const buildProcess = await execProcess({98cmd: buildCmd[0],99args: buildCmd.slice(1),100cwd: path,101stdout: "piped",102stderr: "piped",103});104assert(buildProcess.success, buildProcess.stderr);105}106107for (const file of openfiles) {108if (file.endsWith(".qmd")) {109// provide a step name and function110const cmd = [quartoDevCmd(), "render", file];111const process = await execProcess({112cmd: cmd[0],113args: cmd.slice(1),114cwd: path,115stdout: "piped",116stderr: "piped",117});118assert(process.success, process.stderr);119}120}121});122123// Cleanup the artifact dir124Deno.removeSync(artifactPath, { recursive: true });125});126}127}128129130