test(guards): derive the provider directories from the connection keys

This commit is contained in:
Marc-André Bombeck committed 2026-10-20 09:51:12 +02:00
1 parent 5fdddaec0a
commit 9b05d8c215
2 files changed
+33 -19

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
/**
* The directories under `src/lib` that hold a provider's client and sync,
* derived from the connection keys the product knows (`CONNECTION_KEYS`),
* so a guard over provider code cannot keep a list of its own that a new
* integration slips past. Each key is checked to be a directory: a key that
* names none fails here rather than narrowing a guard in silence.
*/
import { statSync } from "node:fs";
import { join } from "node:path";
import { CONNECTION_KEYS } from "@/lib/integrations/connection-health";
const LIB = join(process.cwd(), "src", "lib");
export const PROVIDER_DIRS: readonly string[] = CONNECTION_KEYS.map((key) => {
if (!statSync(join(LIB, key), { throwIfNoEntry: false })?.isDirectory()) {
throw new Error(`provider-dirs: src/lib/${key} is not a directory`);
}
return key;
});
+13 -19
View File
@@ -11,20 +11,10 @@ import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { walkSourceFiles } from "./helpers/source-files";
import { PROVIDER_DIRS } from "./helpers/provider-dirs";
import { stripComments, walkSourceFiles } from "./helpers/source-files";
const LIB = join(process.cwd(), "src", "lib");
const PROVIDER_DIRS = [
"dawarich",
"fitbit",
"google-health",
"nightscout",
"oura",
"polar",
"strava",
"whoop",
"withings",
];
/**
* Page loops that stay outside `walkPages` on purpose, with how many matches
* each file may hold and why. A file with more matches than its allowance has
@@ -58,12 +48,6 @@ const EXCEPTIONS: Readonly<Record<string, { matches: number; why: string }>> = {
const PAGE_LOOP =
/\b(?:pages?|pageCount|pagesRead|page)(?:\s*-\s*[A-Za-z_]\w*)?\s*(?:<|<=|>|>=)\s*(?:[A-Z_][A-Z0-9_]*|maxPages|[2-9]|[1-9]\d+)\b/g;
function strip(text: string): string {
return text
.replace(/\/\*[\s\S]*?\*\//g, "")
.replace(/(^|[^:])\/\/.*$/gm, "$1");
}
describe("provider clients walk pages through walkPages", () => {
const files = walkSourceFiles(LIB, { floor: 1000 }).filter(
(f) =>
@@ -72,10 +56,20 @@ describe("provider clients walk pages through walkPages", () => {
!f.endsWith(".test.ts"),
);
const matches = (f: string) =>
strip(readFileSync(join(LIB, f), "utf8")).match(PAGE_LOOP)?.length ?? 0;
stripComments(readFileSync(join(LIB, f), "utf8")).match(PAGE_LOOP)
?.length ?? 0;
it("walks the provider directories", () => {
expect(files.length).toBeGreaterThanOrEqual(60);
expect(PROVIDER_DIRS).toEqual(
expect.arrayContaining(["strava", "whoop", "withings", "google-health"]),
);
for (const dir of PROVIDER_DIRS) {
expect(
files.some((f) => f.startsWith(`${dir}/`)),
dir,
).toBe(true);
}
});
it("finds no page loop of their own beyond the exceptions", () => {