Add failing tests for the project name and build context
script/projectname still prints the pre-rename name, so make docker tags its image quack, and .dockerignore has drifted from .gitignore: a compiled bin/quak, the vitest and tsc caches, the CLI's runtime directory and the local worktree directory all reach the build context. Neither failure is visible in a build that exits 0. Red until the fixes land.
This commit is contained in:
49
test/packaging/build-context.test.ts
Normal file
49
test/packaging/build-context.test.ts
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// The Docker build context is load-bearing in two directions, and both
|
||||||
|
// failures are silent.
|
||||||
|
//
|
||||||
|
// Excluding too little: a worktree left under `.claude/` is copied into the
|
||||||
|
// image, vitest globs its `test/` tree as well as the real one, and the
|
||||||
|
// containerised `make check` runs the whole suite twice over while reporting
|
||||||
|
// success. A compiled `bin/quak` is ~100 MB of context nobody needs.
|
||||||
|
//
|
||||||
|
// Excluding too much: Prettier 3 reads `.gitignore` as a default ignore file,
|
||||||
|
// so dropping it from the context silently changes which files
|
||||||
|
// `make fmt-check` looks at inside the image compared to the host.
|
||||||
|
//
|
||||||
|
// Neither shows up as a build failure, so they are asserted here.
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
|
const repoRoot = fileURLToPath(new URL("../../", import.meta.url));
|
||||||
|
|
||||||
|
const patterns = (name: string): string[] =>
|
||||||
|
readFileSync(join(repoRoot, name), "utf-8")
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.filter((line) => line !== "" && !line.startsWith("#"));
|
||||||
|
|
||||||
|
const dockerignore = patterns(".dockerignore");
|
||||||
|
|
||||||
|
describe(".dockerignore", () => {
|
||||||
|
// Everything here is either generated, enormous, or secret. `.claude/` is
|
||||||
|
// the correctness one: see the header comment and issue #25.
|
||||||
|
it.each([
|
||||||
|
".claude/",
|
||||||
|
".quak/",
|
||||||
|
"bin/quak",
|
||||||
|
"node_modules",
|
||||||
|
"coverage",
|
||||||
|
"dist",
|
||||||
|
".vitest-cache/",
|
||||||
|
".nyc_output/",
|
||||||
|
"*.tsbuildinfo",
|
||||||
|
])("keeps %s out of the build context", (pattern) => {
|
||||||
|
expect(dockerignore).toContain(pattern);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("leaves .gitignore in the build context for prettier", () => {
|
||||||
|
expect(dockerignore).not.toContain(".gitignore");
|
||||||
|
});
|
||||||
|
});
|
||||||
30
test/packaging/projectname.test.ts
Normal file
30
test/packaging/projectname.test.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// `script/projectname` is the single source of the project's name for every
|
||||||
|
// script that needs one — `script/docker` builds its image tag from it, which
|
||||||
|
// is the whole reason that file exists. Nothing checked that it agreed with
|
||||||
|
// `package.json`, and after the repo was renamed it did not: the script still
|
||||||
|
// said "quack", so `make docker` produced an image tagged after a name this
|
||||||
|
// project has not used since May.
|
||||||
|
//
|
||||||
|
// The script is executed rather than read, because what matters is the string
|
||||||
|
// it prints, not the source it prints it from.
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { execFileSync } from "node:child_process";
|
||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
|
const repoRoot = fileURLToPath(new URL("../../", import.meta.url));
|
||||||
|
|
||||||
|
const pkg = JSON.parse(
|
||||||
|
readFileSync(join(repoRoot, "package.json"), "utf-8"),
|
||||||
|
) as { name: string };
|
||||||
|
|
||||||
|
describe("script/projectname", () => {
|
||||||
|
it("prints the name package.json declares", () => {
|
||||||
|
const printed = execFileSync(join(repoRoot, "script/projectname"), {
|
||||||
|
cwd: repoRoot,
|
||||||
|
encoding: "utf-8",
|
||||||
|
}).trim();
|
||||||
|
expect(printed).toBe(pkg.name);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user