Initial Commit
This commit is contained in:
79
packages/ui/react/react-audio-stream/tests/purity.test.ts
Normal file
79
packages/ui/react/react-audio-stream/tests/purity.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
||||
import { join, resolve } from "node:path";
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
|
||||
const PKG_ROOT = resolve(__dirname, "..");
|
||||
const DIST = join(PKG_ROOT, "dist");
|
||||
|
||||
/**
|
||||
* Chunk-A runtime dependency allowlist. Chunks B/C/D may extend this
|
||||
* (`@suaveplan/network-transport-websockets`, `@suaveplan/retry`, etc.);
|
||||
* the parent spec's `tests/exports.test.ts` enforces the full union
|
||||
* once every chunk has landed.
|
||||
*/
|
||||
const ALLOWED_RUNTIME_DEPS = new Set([
|
||||
"@suaveplan/audio-fx-plugin-base",
|
||||
"@suaveplan/audio-transport",
|
||||
"@suaveplan/error",
|
||||
"@suaveplan/events",
|
||||
"@suaveplan/fsm",
|
||||
"@suaveplan/network-transport-websockets",
|
||||
"@suaveplan/opentelemetry",
|
||||
"@suaveplan/react-audio",
|
||||
"@suaveplan/retry",
|
||||
"@suaveplan/types",
|
||||
"@opentelemetry/api",
|
||||
"tslib",
|
||||
"zod",
|
||||
"zustand",
|
||||
]);
|
||||
|
||||
function walk(dir: string, out: string[] = []): string[] {
|
||||
if (!existsSync(dir)) return out;
|
||||
for (const name of readdirSync(dir)) {
|
||||
const p = join(dir, name);
|
||||
if (statSync(p).isDirectory()) walk(p, out);
|
||||
else if (/\.(js|mjs|cjs)$/.test(name)) out.push(p);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
describe("react-audio-stream purity gates", () => {
|
||||
it("runtime dependency set matches the allowlist", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const pkg = JSON.parse(
|
||||
readFileSync(join(PKG_ROOT, "package.json"), "utf8")
|
||||
) as { dependencies?: Record<string, string> };
|
||||
const deps = Object.keys(pkg.dependencies ?? {});
|
||||
for (const dep of deps) {
|
||||
expect(ALLOWED_RUNTIME_DEPS.has(dep)).toBe(true);
|
||||
}
|
||||
for (const allowed of ALLOWED_RUNTIME_DEPS) {
|
||||
expect(deps.includes(allowed)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("dist references no audio context", { timeout: 30000 }, () => {
|
||||
if (!existsSync(DIST)) {
|
||||
// Skip pre-build — the package's own test stage runs before
|
||||
// `vite build`; the CI pipeline reruns this after `turbo
|
||||
// build` so the negative gate is enforced there.
|
||||
return;
|
||||
}
|
||||
const files = walk(DIST);
|
||||
const forbidden = [
|
||||
/\bnew\s+AudioContext\b/,
|
||||
/\bnew\s+OfflineAudioContext\b/,
|
||||
/\binstanceof\s+AudioNode\b/,
|
||||
/\bAudioWorkletNode\b/,
|
||||
/\bregisterProcessor\b/,
|
||||
];
|
||||
for (const file of files) {
|
||||
const text = readFileSync(file, "utf8");
|
||||
for (const rx of forbidden) {
|
||||
expect(rx.test(text)).toBe(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user