Files
frontend/scripts/test-pre-commit.mjs
T
ksv741 72d7835227 chore: finish frontend ESLint migration #18
Enable every plugin recommended preset and replace Biome with ESLint formatting.

Preserve API contracts and JSX whitespace; verify source, tests, builds and tooling.
2026-09-28 16:36:40 +03:00

71 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import { execFileSync, spawnSync } from "node:child_process";
import { randomBytes } from "node:crypto";
import {
existsSync,
mkdirSync,
mkdtempSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import nodePath from "node:path";
import { test } from "node:test";
const GITHUB_TOKEN_RANDOM_BYTES = 18;
test("pre-commit scans the index, redacts findings and fails closed", () => {
const hook = nodePath.resolve(".husky/pre-commit");
const cwd = mkdtempSync(nodePath.join(tmpdir(), "frontend-hook-"));
const bin = nodePath.join(cwd, "bin");
const marker = nodePath.join(cwd, "downstream");
const token = `ghp_${randomBytes(GITHUB_TOKEN_RANDOM_BYTES).toString("hex")}`;
// eslint-disable-next-line sonarjs/no-os-command-from-path -- Repository checks use the developer/CI Git installation; arguments never invoke a shell.
const git = (...arguments_) => execFileSync("git", arguments_, { cwd, stdio: "pipe" });
const run = (path = `${bin}${nodePath.delimiter}${process.env.PATH}`) =>
spawnSync("/bin/sh", ["-e", hook], {
cwd,
encoding: "utf8",
env: { ...process.env, PATH: path },
});
try {
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Path is built from this check’s private mkdtemp directory and fixed filenames.
mkdirSync(bin);
for (const command of ["npx", "npm"]) {
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Path is built from this check’s private mkdtemp directory and fixed filenames.
writeFileSync(nodePath.join(bin, command), "#!/bin/sh\necho ran >> downstream\n", {
mode: 0o755,
});
}
git("init", "--quiet");
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Path is built from this check’s private mkdtemp directory and fixed filenames.
writeFileSync(nodePath.join(cwd, "sample.txt"), "safe staged content\n");
git("add", "sample.txt");
// An unstaged secret must not be mistaken for the index being committed.
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Path is built from this check’s private mkdtemp directory and fixed filenames.
writeFileSync(nodePath.join(cwd, "sample.txt"), `token=${token}\n`);
let result = run();
assert.equal(
result.status,
0,
"clean index must pass; install Gitleaks first",
);
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Path is built from this check’s private mkdtemp directory and fixed filenames.
assert.ok(existsSync(marker));
rmSync(marker);
git("add", "sample.txt");
result = run();
assert.equal(result.status, 1, "staged secret must block commit");
assert.ok(!`${result.stdout}${result.stderr}`.includes(token));
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Path is built from this check’s private mkdtemp directory and fixed filenames.
assert.ok(!existsSync(marker), "formatting/dependency checks must not run");
result = run(bin);
assert.notEqual(result.status, 0, "missing Gitleaks must block commit");
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Path is built from this check’s private mkdtemp directory and fixed filenames.
assert.ok(!existsSync(marker));
}
finally {
rmSync(cwd, { force: true, recursive: true });
}
});