Files
Arcrun/cypher-executor/tests/component-loader-code.test.ts
T
Leo 06ff0e21ce fix(cypher-executor): component-loader 白名單補 code 零件(#29 發現)
WASM_HTTP_RUNNER_IDS 漏 'code',導致 workflow 寫 `component: code` 在解析鏈
step 1-6 全不命中後落到 step 8 直接「找不到零件」——本 PR 的 graph_neighbors
範例正用 code 節點,故歸此分支。

URL 推導:走既有 wasmWorkerUrl 通用推導 arcrun-code.{WORKER_SUBDOMAIN}.workers.dev
(WORKER_SUBDOMAIN 來自 wrangler.toml [vars],self-hosted 由 deploy 注入自己的
subdomain)——無寫死官方 code.arcrun.dev,self-hosted 天然成立。

測試:tests/component-loader-code.test.ts(2 測)——`code` 解析成 runner 不 throw、
stub fetch 證 runner 打 arcrun-code.{sub}.workers.dev;wasmWorkerUrl 對任意 subdomain
推導正確。tsc 乾淨、全套 50 passed(1 失敗為 main 既有、無關)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015d5jDbuqT5Htwv3Q88XXKk
2026-07-07 08:42:51 +00:00

57 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* component-loader`code` 零件解析測試(#29 發現的白名單缺口)。
*
* 背景:workflow 寫 `component: code` 時,component-loader 解析鏈 step 1-6 都不命中
* (非 builtin / 非 URL / 非 hash / 非邏輯零件 binding / 非 recipe),必須靠 step 7 的
* WASM_HTTP_RUNNER_IDS 白名單 → wasmWorkerUrl 通用推導。白名單漏 `code` 就會落到
* step 8 直接丟「找不到零件」——graph_neighbors 等用 code 節點的 workflow 全滅。
*
* 驗證:
* 1. `code` 能被解析成 runner(不 throw)。
* 2. runner 打的 URL = arcrun-code.{WORKER_SUBDOMAIN}.workers.dev(通用推導、無寫死
* 官方 code.arcrun.dev → self-hosted 換 WORKER_SUBDOMAIN 即落地)。
*/
import { describe, it, expect, vi, afterEach } from 'vitest';
import { env } from 'cloudflare:test';
import { createComponentLoader, wasmWorkerUrl } from '../src/lib/component-loader';
import type { Bindings } from '../src/types';
afterEach(() => {
vi.unstubAllGlobals();
});
describe('component-loadercode 零件解析(WASM HTTP runner 白名單)', () => {
it('wasmWorkerUrl 通用推導:code → arcrun-code.{subdomain}.workers.devself-hosted 換 subdomain 即成立)', () => {
expect(wasmWorkerUrl('code', 'uncle6-me')).toBe('https://arcrun-code.uncle6-me.workers.dev');
expect(wasmWorkerUrl('code', 'my-selfhosted-sub')).toBe('https://arcrun-code.my-selfhosted-sub.workers.dev');
});
it('component: code 能被解析成 runner,且 fetch 打 subdomain 推導的 URL', async () => {
const fakeEnv = {
...env,
WORKER_SUBDOMAIN: 'test-sub',
} as unknown as Bindings;
const loader = createComponentLoader(fakeEnv);
// 白名單漏 `code` 時這裡就 throw「找不到零件 "code"」(#29 的故障型態)
const runner = await loader('code');
expect(typeof runner).toBe('function');
// stub fetch 捕 URL:證明 runner 打的是通用推導 URL,非寫死官方域名
const calledUrls: string[] = [];
const fetchSpy = vi.fn(async (url: unknown) => {
calledUrls.push(String(url));
return new Response(JSON.stringify({ success: true, data: { ok: true } }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
});
vi.stubGlobal('fetch', fetchSpy);
const result = await runner({ code: 'return {ok:true}', input: {} }) as Record<string, unknown>;
expect(fetchSpy).toHaveBeenCalledTimes(1);
expect(calledUrls[0]).toBe('https://arcrun-code.test-sub.workers.dev');
expect(result.success).toBe(true);
});
});