/** * component-loader:`hash` 零件解析測試(Arcrun#91)。 * * 背景:workflow 寫 `component: hash` 時,component-loader 解析鏈 step 1-6 都不命中 * (非 builtin / 非 URL / 非 hash-id / 非 LOGIC_BINDING_MAP 邏輯零件 / 非 recipe), * 必須靠 step 7 的 WASM_HTTP_RUNNER_IDS 白名單 → wasmWorkerUrl 通用推導。 * 白名單漏 `hash` 就會落到 step 8 直接丟「找不到零件」——與 #29 的 `code` 缺口同形狀。 * * 驗證: * 1. `hash` 能被解析成 runner(不 throw)。 * 2. runner 打的 URL = arcrun-hash.{WORKER_SUBDOMAIN}.workers.dev(通用推導、無寫死 * 官方 hash.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-loader:hash 零件解析(WASM HTTP runner 白名單,Arcrun#91)', () => { it('wasmWorkerUrl 通用推導:hash → arcrun-hash.{subdomain}.workers.dev(self-hosted 換 subdomain 即成立)', () => { expect(wasmWorkerUrl('hash', 'uncle6-me')).toBe('https://arcrun-hash.uncle6-me.workers.dev'); expect(wasmWorkerUrl('hash', 'my-selfhosted-sub')).toBe('https://arcrun-hash.my-selfhosted-sub.workers.dev'); }); it('component: hash 能被解析成 runner,且 fetch 打 subdomain 推導的 URL', async () => { const fakeEnv = { ...env, WORKER_SUBDOMAIN: 'test-sub', } as unknown as Bindings; const loader = createComponentLoader(fakeEnv); // 白名單漏 `hash` 時這裡就 throw「找不到零件 "hash"」 const runner = await loader('hash'); 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: { result: '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824', algorithm: 'sha256', encoding: 'hex' }, }), { status: 200, headers: { 'Content-Type': 'application/json' } } ); }); vi.stubGlobal('fetch', fetchSpy); const result = await runner({ algorithm: 'sha256', input: 'hello', encoding: 'hex' }) as Record; expect(fetchSpy).toHaveBeenCalledTimes(1); expect(calledUrls[0]).toBe('https://arcrun-hash.test-sub.workers.dev'); expect(result.success).toBe(true); }); });