mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 07:12:12 +03:00
* test: realign catalog snapshot tests to current deliberate catalog state Six catalog/snapshot tests drifted behind deliberate catalog changes that were already validated by newer sibling tests. No production code touched; every change aligns a stale snapshot to behavior already validated by newer sibling tests. Root causes (all confirmed against the current code before editing): - tests/unit/providers-constants-split.test.ts: APIKEY_PROVIDERS grew from 187 to 195 entries via #8077 (clova-studio/internlm/ant-ling, regional), #8161 (sarvam/plamo → regional, writer → frontier-labs) and #8170 (typhoon → regional, inception → frontier-labs). Family counts verified to sum to 195 (gateways 60, frontier-labs 24, inference-hosts 28, enterprise-cloud 17, regional 40, specialty-media 26) with no duplicates. Updated the two assertions and extended the changelog comment. - tests/unit/qianfan-provider.test.ts: the expected Baidu Qianfan website URL was the pre-#8128 wenxinworkshop path. #8128/#6271 moved it to https://cloud.baidu.com/product-s/qianfan_home, already locked by the sibling regression test tests/unit/baidu-qianfan-website-urls-6271.test.ts. - tests/unit/t31-t33-t34-t38-model-specs.test.ts and tests/unit/auto-combo-credentialed-model-pool.test.ts: the Antigravity catalog refactor (#8013) retired gemini-3-pro-preview/claude-sonnet-5 and renamed the Gemini 3.5 Flash tiers (low/medium/high -> extra-low/low/gemini-3-flash-agent), confirmed against ANTIGRAVITY_PUBLIC_MODELS and tests/unit/antigravity-retired-public-models.test.ts. Swapped the retired IDs for currently-registered ones (gemini-3.6-flash-high, claude-sonnet-4-6, gemini-3-flash-agent, gemini-3.5-flash-low/extra-low) and moved the wildcard-exclusion prefix test from the now-2-tier "gemini-3.5-*" group to "gemini-3.6-*", which has 3 real tiers today (same >=3 semantics, just pointed at a prefix that still has 3 members). - tests/unit/model-alias-seed.test.ts: getModelInfo("gemini-3.1-pro") now canonicalizes through ALIAS_TO_PROVIDER_ID["agy"] = "antigravity" (#8050), the same pattern already applied to opencode -> opencode-zen. Updated the expected provider id. - tests/unit/video-dashscope.test.ts (deleted, 216 lines): #8266 reorganized the Alibaba video catalog so the flat wan2.7-t2v id no longer exists under the plain "alibaba" provider (only the dated wan2.7-t2v-2026-06-12 does); the flat id now lives only under "qwen-cloud". All 6 tests in the file failed because they built requests against alibaba/wan2.7-t2v, which the new allowlist now rejects with 400 ("unsupported alibaba video model") - verified directly against VIDEO_PROVIDERS in open-sse/config/videoRegistry.ts. Coverage already exists and was confirmed passing pre-deletion in tests/unit/alibaba-video-media.test.ts (including an explicit "Alibaba rejects video models outside its own allowlist" case for this exact id) and tests/unit/qwen-cloud-video-media.test.ts (covers the same id under qwen-cloud). Note: the deleted file's DashScope upstream error-path assertions (401 missing credentials, 502 missing task_id, 502 FAILED status, 504 poll timeout) don't have a byte-for-byte equivalent in the two replacement files, though the shared dashscopeHandler.ts code path they exercise remains covered by several sibling *-media.test.ts files for the happy path and local validation. - tests/unit/authz/spawn-capable-prefixes-client-safe.test.ts: #7892 added /api/vnc-session to the SPAWN_CAPABLE_PREFIXES deny-list (Hard Rules #15/#17 hardening). Bumped the expected length 10 -> 11 and added the entry to the test's named list for documentation. Refs #8013, #8050, #8266, #7892, #8128 * chore(quality): allowlist the video-dashscope.test.ts deletion with its replacements check:test-masking (pr-test-policy CI gate) requires a _deletedWithReplacement entry for any deleted test file, even when the deletion is a verified-legitimate supersession. Documents the same #8266 rationale from the prior commit in the machine-checked allowlist so the deletion is not flagged as unexplained masking. Refs #8266
92 lines
3.9 KiB
TypeScript
92 lines
3.9 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
import { dirname, join, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
import { SPAWN_CAPABLE_PREFIXES } from "@/shared/constants/spawnCapablePrefixes";
|
|
|
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
|
|
const VALIDATION_DIR = join(ROOT, "src/shared/validation");
|
|
|
|
function walkTsFiles(dir: string): string[] {
|
|
const out: string[] = [];
|
|
for (const entry of readdirSync(dir)) {
|
|
const full = join(dir, entry);
|
|
if (statSync(full).isDirectory()) out.push(...walkTsFiles(full));
|
|
else if (/\.tsx?$/.test(entry) && !/\.test\.tsx?$/.test(entry)) out.push(full);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* Returns the VALUE-import specifiers in `src` (i.e. imports that survive to the
|
|
* runtime bundle). `import type …` is excluded — it is erased by the compiler/SWC and
|
|
* never creates a webpack bundle edge, so it cannot leak a Node-only dep into a
|
|
* client bundle.
|
|
*/
|
|
function valueImportSpecifiers(src: string): string[] {
|
|
const specs: string[] = [];
|
|
// import [type] [<clause> from] "<spec>" — `[^"';]*?` spans multi-line clauses.
|
|
const re = /\bimport\s+(type\s+)?(?:[^"';]*?\bfrom\s*)?["']([^"']+)["']/g;
|
|
let m: RegExpExecArray | null;
|
|
while ((m = re.exec(src))) {
|
|
if (m[1]) continue; // `import type …` — erased, not a runtime edge
|
|
specs.push(m[2]);
|
|
}
|
|
return specs;
|
|
}
|
|
|
|
// Regression guard for the dast-smoke "Build CLI bundle" failure:
|
|
// Module not found: Can't resolve 'dns' / 'net' (./node_modules/ioredis/...)
|
|
// Root cause: `settingsSchemas.ts` VALUE-imported SPAWN_CAPABLE_PREFIXES from
|
|
// `@/server/authz/routeGuard`, whose server runtime (runtimeSettings → localDb →
|
|
// apiKeys → rateLimiter → ioredis) then got dragged into the client/CLI webpack bundle
|
|
// via the dashboard onboarding wizard → validation barrel chain. Validation schemas are
|
|
// client-reachable and MUST depend only on zod + `@/shared` leaves — never on the
|
|
// server (`@/server/…`) or server-side lib (`@/lib/…`, which reaches the DB/ioredis).
|
|
const FORBIDDEN_VALUE_ROOTS = ["@/server/", "@/lib/"];
|
|
|
|
test("validation schemas must not VALUE-import from server-side roots (client/CLI build safety)", () => {
|
|
const offenders: string[] = [];
|
|
for (const file of walkTsFiles(VALIDATION_DIR)) {
|
|
const rel = file.slice(ROOT.length + 1);
|
|
for (const spec of valueImportSpecifiers(readFileSync(file, "utf8"))) {
|
|
if (FORBIDDEN_VALUE_ROOTS.some((root) => spec.startsWith(root))) {
|
|
offenders.push(`${rel} → ${spec}`);
|
|
}
|
|
}
|
|
}
|
|
assert.deepEqual(
|
|
offenders,
|
|
[],
|
|
"Client-reachable validation schemas VALUE-import server-side modules, which drags the " +
|
|
"server runtime (→ ioredis) into the browser/CLI bundle and breaks the Next build with " +
|
|
`"Can't resolve 'dns'/'net'". Move the needed value to a server-free @/shared/constants ` +
|
|
`leaf (see src/shared/constants/spawnCapablePrefixes.ts). Offenders:\n ${offenders.join("\n ")}`
|
|
);
|
|
});
|
|
|
|
test("SPAWN_CAPABLE_PREFIXES is defined in the server-free constants leaf with the expected entries", () => {
|
|
assert.ok(Array.isArray(SPAWN_CAPABLE_PREFIXES));
|
|
// The full deny-list survived the extraction out of routeGuard.ts (Hard Rules #15/#17).
|
|
for (const prefix of [
|
|
"/api/cli-tools/runtime/",
|
|
"/api/services/",
|
|
"/api/tools/agent-bridge/",
|
|
"/api/tools/traffic-inspector/",
|
|
"/api/plugins/",
|
|
"/api/local/",
|
|
"/api/skills/collect/",
|
|
"/api/headroom/start",
|
|
"/api/headroom/stop",
|
|
"/api/vnc-session", // #7892: spawns Docker containers via child_process.spawn
|
|
]) {
|
|
assert.ok(
|
|
SPAWN_CAPABLE_PREFIXES.includes(prefix),
|
|
`SPAWN_CAPABLE_PREFIXES lost the spawn-capable prefix "${prefix}" during extraction`
|
|
);
|
|
}
|
|
assert.equal(SPAWN_CAPABLE_PREFIXES.length, 11);
|
|
});
|