import { readdirSync, readFileSync } from "node:fs";
import path from "node:path";
import { componentName, transform } from "./testids.ts";
const web = path.resolve(import.meta.dirname, "..");
const e2e = path.resolve(web, "../e2e");
const walk = (dir: string, keep: (file: string) => boolean): string[] =>
readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
const file = path.join(dir, entry.name);
if (entry.isDirectory()) return entry.name === "node_modules" ? [] : walk(file, keep);
return keep(file) ? [file] : [];
});
const ids = new Set<string>();
const components = new Set<string>();
for (const file of walk(
path.join(web, "src"),
(f) => f.endsWith(".svelte") && !f.endsWith(".stories.svelte")
)) {
const name = componentName(file);
const { seen, inserts } = transform(readFileSync(file, "utf8"), { component: name });
if (inserts.some((insert) => insert.text.includes("data-component="))) components.add(name);
for (const item of seen) if (item.id) ids.add(item.id);
}
const unknown: string[] = [];
const uses =
/(testid|component)\(\s*"([^"]+)"|data-(testid|component)=\\?"([A-Za-z0-9_:/.[\]()-]+)/g;
for (const file of walk(e2e, (f) => f.endsWith(".ts"))) {
readFileSync(file, "utf8")
.split("\n")
.forEach((line, index) => {
for (const match of line.matchAll(uses)) {
const kind = match[1] ?? match[3];
const name = match[2] ?? match[4];
if (kind === "component" ? !components.has(name) : !ids.has(name))
unknown.push(
`${kind} ${name} ${path.relative(path.dirname(e2e), file)}:${index + 1}`
);
}
});
}
if (unknown.length) console.error(`not in the web:\n ${unknown.join("\n ")}`);
process.exit(unknown.length ? 1 : 0);