mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 22:32:04 +00:00
Forty-two guard files carried their own comment stripper, block comments first in one non-greedy pass, so a /* inside a line comment opened a block that hid the code after it, and the stricter copies hid code behind a /* inside a string, which every e2e route glob has. They all read through the shared stripComments now, and it scans the way the parser does: strings, template literals and regular expressions keep every character, a comment inside a template expression goes, and line numbers are kept. A parity test strips every source file both ways, with the scanner and with the TypeScript parser, and fails on the first that differs. No guard reports anything new. Each one fails when the stripper returns nothing; three of them passed on an empty file and assert that the code they ban is read at all now.
88 lines
3.3 KiB
TypeScript
88 lines
3.3 KiB
TypeScript
/**
|
|
* Every ISO instant under `src/` goes through `isoDateTime()`.
|
|
*
|
|
* Since v1.43 a request instant must carry seconds, and the refusal is counted
|
|
* (`validation.datetime.no_seconds`) so a client on a minute-precision encoder
|
|
* shows up in the logs. Both live in `src/lib/validations/datetime.ts`. A
|
|
* schema that calls `z.iso.datetime(` or `z.string().datetime(` directly gets
|
|
* zod's default message and is invisible to the counter, so a direct call
|
|
* anywhere else is refused here.
|
|
*
|
|
* The matcher tolerates whitespace and line breaks between `z`, `.iso` /
|
|
* `.string()` and `.datetime(`, because prettier splits long chains, and it
|
|
* also refuses a bare `.datetime(` chained off anything, so an alias such as
|
|
* `const s = z.string(); s.datetime()` cannot route around it. Comments are
|
|
* stripped first so prose about the old form does not trip it.
|
|
*/
|
|
import { describe, expect, it } from "vitest";
|
|
import { readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
|
|
import { stripComments, walkSourceFiles } from "./helpers/source-files";
|
|
|
|
const SRC = join(process.cwd(), "src");
|
|
const HELPER = "lib/validations/datetime.ts";
|
|
|
|
function sourceFiles(): string[] {
|
|
return walkSourceFiles(SRC, { floor: 3000 })
|
|
.filter((p) => !p.startsWith("generated/"))
|
|
.filter((p) => !p.includes("__tests__"))
|
|
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"));
|
|
}
|
|
|
|
const DIRECT_DATETIME = /\.\s*datetime\s*\(/g;
|
|
const HELPER_CALL = /\bisoDateTime\s*\(/g;
|
|
|
|
function directDatetimeCalls(text: string): number {
|
|
return (stripComments(text).match(DIRECT_DATETIME) ?? []).length;
|
|
}
|
|
|
|
describe("datetime helper guard", () => {
|
|
const files = sourceFiles();
|
|
|
|
it("finds no direct zod datetime call outside the helper", () => {
|
|
const offenders = files
|
|
.filter((rel) => rel !== HELPER)
|
|
.flatMap((rel) => {
|
|
const n = directDatetimeCalls(readFileSync(join(SRC, rel), "utf8"));
|
|
return n > 0 ? [`${rel} (${n})`] : [];
|
|
});
|
|
expect(
|
|
offenders,
|
|
"use isoDateTime() from @/lib/validations/datetime instead",
|
|
).toEqual([]);
|
|
});
|
|
|
|
it("the helper itself is the one place that calls zod", () => {
|
|
expect(directDatetimeCalls(readFileSync(join(SRC, HELPER), "utf8"))).toBe(
|
|
1,
|
|
);
|
|
});
|
|
|
|
it("actually sees the call sites it guards", () => {
|
|
// An empty sweep agrees with an empty offender list. The helper has
|
|
// hundreds of callers; a count far below that means the walk or the
|
|
// matcher went blind, not that the tree is clean.
|
|
const calls = files
|
|
.filter((rel) => rel !== HELPER)
|
|
.reduce(
|
|
(sum, rel) =>
|
|
sum +
|
|
(readFileSync(join(SRC, rel), "utf8").match(HELPER_CALL) ?? [])
|
|
.length,
|
|
0,
|
|
);
|
|
expect(calls).toBeGreaterThan(350);
|
|
});
|
|
|
|
it("matches the forms prettier produces", () => {
|
|
expect(directDatetimeCalls("z.iso.datetime({ offset: true })")).toBe(1);
|
|
expect(directDatetimeCalls("z.iso\n .datetime({ offset: true })")).toBe(1);
|
|
expect(directDatetimeCalls("z\n .string()\n .datetime()")).toBe(1);
|
|
expect(directDatetimeCalls("s . datetime ()")).toBe(1);
|
|
expect(directDatetimeCalls("// z.iso.datetime() in prose")).toBe(0);
|
|
expect(directDatetimeCalls("/* z.string().datetime() */")).toBe(0);
|
|
expect(directDatetimeCalls("isoDateTime()")).toBe(0);
|
|
});
|
|
});
|