mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 06:40:50 +00:00
test: give every scanning guard a floor on what it found
A guard that compares a sweep against an allowlist, or against "none of
these may exist", passes when the sweep comes back empty. walkSourceFiles
already refuses a short walk; this adds the same refusal for what a guard
does with the walk.
- requireFloor(label, found, floor) throws below the floor and refuses a
floor of zero.
- scanSourceMatches(root, pattern, { fileFloor, matchFloor }) walks, matches
and floors both the files read and the hits found.
Floors added, pinned at the current counts:
- coach_usage owner columns: the clauses it actually examined (6).
- measurement reference index: the foreign keys it extracted (2).
- job outcome fact inventory: job files (130, floor 120) and fact keys
(399, floor 350).
- tone harness: assessment prompt modules (11).
- coach locale default: turn pipeline modules (15, floor 12).
- locale integrity: message bundles (7).
- settings card header coverage and settings anatomy: the walked cards.
- coach metric scope inventory: insight route sources.
- side-effect drift guard: both enums populated, since two empty keysets
are equal.
The pill-mapper guard walked with globSync, which skips dot-prefixed
directories; it now walks through walkSourceFiles like the rest.
This commit is contained in:
1 parent
a3b5480d04
commit
b4577f5c31
12 files changed
+166
-37
No files matched your search
@@ -4,6 +4,7 @@ import { join, resolve } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type { CoachScopeSource } from "@/lib/ai/coach/types";
|
||||
import { requireFloor } from "@/__tests__/helpers/source-files";
|
||||
import {
|
||||
scopeSourceFromMetricKey,
|
||||
scopeSourceMetricLabelKey,
|
||||
@@ -38,8 +39,10 @@ function sourceFilesBelow(directory: string): string[] {
|
||||
}
|
||||
|
||||
function genericMetricCardInventory(): Set<string> {
|
||||
const insightRouteSources = sourceFilesBelow(
|
||||
join(PROJECT_ROOT, "src/app/insights"),
|
||||
const insightRouteSources = requireFloor(
|
||||
"insight route sources",
|
||||
sourceFilesBelow(join(PROJECT_ROOT, "src/app/insights")),
|
||||
60,
|
||||
).map((path) => readFileSync(path, "utf8"));
|
||||
const recoverySource = readFileSync(
|
||||
join(PROJECT_ROOT, "src/components/insights/recovery/recovery-section.tsx"),
|
||||
|
||||
@@ -9,6 +9,7 @@ import { PageHeader } from "@/components/ui/page-header";
|
||||
import { SettingsCard } from "@/components/settings/settings-card";
|
||||
import { SettingsCardHeader } from "@/components/settings/_card-header";
|
||||
import { SettingsCardActions } from "@/components/settings/_card-actions";
|
||||
import { requireFloor } from "@/__tests__/helpers/source-files";
|
||||
|
||||
/**
|
||||
* Settings + Admin read as one surface. These pin the parts of that claim
|
||||
@@ -179,8 +180,12 @@ describe("the Settings and Admin shells route their heading through PageHeader",
|
||||
describe("the abolished body gutter stays abolished", () => {
|
||||
it("has no `pl-7` left under Settings or Admin", () => {
|
||||
const offenders: string[] = [];
|
||||
for (const dir of ["settings", "admin"]) {
|
||||
for (const file of walk(join(ROOT, "src", "components", dir))) {
|
||||
for (const [dir, floor] of [
|
||||
["settings", 130],
|
||||
["admin", 30],
|
||||
] as const) {
|
||||
const files = walk(join(ROOT, "src", "components", dir));
|
||||
for (const file of requireFloor(`${dir} components`, files, floor)) {
|
||||
const source = readFileSync(file, "utf8");
|
||||
for (const [i, line] of source.split("\n").entries()) {
|
||||
// Comments may name the class they retired; class strings may not.
|
||||
|
||||
@@ -23,6 +23,8 @@ import { describe, it, expect } from "vitest";
|
||||
import { readFileSync, readdirSync, statSync } from "node:fs";
|
||||
import { join, relative } from "node:path";
|
||||
|
||||
import { requireFloor } from "@/__tests__/helpers/source-files";
|
||||
|
||||
const ROOT = join(__dirname, "../../../..");
|
||||
const SETTINGS_DIR = join(ROOT, "src/components/settings");
|
||||
|
||||
@@ -59,7 +61,8 @@ describe("Settings card headers route through SettingsCardHeader", () => {
|
||||
it("has no hand-rolled <h2 text-lg> outside the primitive + allowlist", () => {
|
||||
const offenders: string[] = [];
|
||||
|
||||
for (const file of walk(SETTINGS_DIR)) {
|
||||
const files = requireFloor("settings cards", walk(SETTINGS_DIR), 80);
|
||||
for (const file of files) {
|
||||
const base = file.slice(file.lastIndexOf("/") + 1);
|
||||
if (base === PRIMITIVE) continue;
|
||||
if (ALLOWLIST.has(base)) continue;
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
*/
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "@/__tests__/helpers/source-files";
|
||||
|
||||
import type { SyncVerdict } from "@/lib/integrations/sync-verdict";
|
||||
import {
|
||||
@@ -113,14 +114,10 @@ describe("structural guard — no second pill dialect", () => {
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.filter(
|
||||
(p) => !p.startsWith(`generated${sep}`) && !p.startsWith("generated/"),
|
||||
)
|
||||
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"))
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user