Files
pleno-vue/scripts/pre-commit-format-tests.mjs
T
Jeppe Bundgaard a9a5137515 Add pre-commit formatting hooks for test files and configure Husky integration:
- Added Husky pre-commit hook to enforce formatting on JavaScript and TypeScript test files.
- Implemented `pre-commit-format-tests.mjs` to check for unstaged changes, format test files using Prettier, and re-stage them.
- Included `prepare-husky.mjs` to verify Husky installation in the git worktree.
- Updated `package-lock.json` to include `husky` as a dependency.
2026-04-15 12:18:49 +02:00

112 lines
3.1 KiB
JavaScript

import path from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, "..");
const gitPathspecs = [":(glob)tests/**/*.js", ":(glob)tests/**/*.ts"];
function run(command, args, options = {}) {
const result = spawnSync(command, args, {
cwd: repoRoot,
encoding: "utf8",
...options,
});
if (result.error) {
throw result.error;
}
return result;
}
function fail(message) {
console.error(message);
process.exit(1);
}
function runNpmScript(scriptName) {
if (process.env.npm_execpath) {
return run(process.execPath, [process.env.npm_execpath, "run", scriptName], { stdio: "inherit" });
}
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
return run(npmCommand, ["run", scriptName], {
shell: process.platform === "win32",
stdio: "inherit",
});
}
function parseLines(output) {
return output
.split(/\r?\n/)
.map((line) => line.trim())
.filter(Boolean);
}
const worktreeResult = run("git", ["rev-parse", "--show-toplevel"]);
if (worktreeResult.status !== 0) {
fail("Pre-commit formatting must run inside the front-end-vue Git worktree.");
}
const gitRoot = path.resolve(worktreeResult.stdout.trim());
if (gitRoot !== repoRoot) {
fail(`Expected front-end-vue to be the Git root, but git reported: ${gitRoot}`);
}
const unstagedTrackedResult = run("git", ["diff", "--name-only", "--", ...gitPathspecs]);
if (unstagedTrackedResult.status !== 0) {
fail("Unable to inspect unstaged test-file changes before running Prettier.");
}
const untrackedResult = run("git", ["ls-files", "--others", "--exclude-standard", "--", ...gitPathspecs]);
if (untrackedResult.status !== 0) {
fail("Unable to inspect untracked test files before running Prettier.");
}
const unsafePaths = [
...parseLines(unstagedTrackedResult.stdout),
...parseLines(untrackedResult.stdout),
];
if (unsafePaths.length > 0) {
const formattedPaths = unsafePaths.map((filePath) => ` - ${filePath}`).join("\n");
fail(
[
"Pre-commit formatting aborted because tests contain unstaged changes.",
"Stage or discard these files before committing so the hook does not add unrelated work:",
formattedPaths,
].join("\n")
);
}
console.log("Running Prettier for frontend test files...");
const formatResult = runNpmScript("format:tests");
if (formatResult.status !== 0) {
process.exit(formatResult.status ?? 1);
}
console.log("Restaging formatted frontend test files...");
const knownFilesResult = run("git", ["ls-files", "--cached", "--others", "--exclude-standard", "--", ...gitPathspecs]);
if (knownFilesResult.status !== 0) {
fail("Prettier completed, but the hook could not resolve test files for restaging.");
}
const filesToStage = parseLines(knownFilesResult.stdout);
if (filesToStage.length === 0) {
process.exit(0);
}
const addResult = run("git", ["add", "--", ...filesToStage], { stdio: "inherit" });
if (addResult.status !== 0) {
fail("Prettier completed, but git add failed while restaging formatted test files.");
}