/** * P0-00: HTTP client method/body/headers 可信度测试。 * 运行: node --experimental-strip-types frontend/src/lib/http.test.ts * * 最小环境 polyfill:Node 22 自带 fetch/AbortController,本测试不触发 401 路径, * 故 window.dispatchEvent 不会被调用,无需完整 DOM。 */ import { test } from 'node:test' import assert from 'node:assert/strict' // 最小浏览器环境 polyfill(仅覆盖 http.ts 在 happy path 用到的全局) const store: Record = {} // @ts-expect-error 测试用最小 window stub globalThis.window = { dispatchEvent: () => false, localStorage: { getItem: (k: string) => store[k] ?? null, setItem: (k: string, v: string) => { store[k] = v }, removeItem: (k: string) => { delete store[k] }, }, } // 捕获每次 fetch 的入参供断言 let lastInit: RequestInit | undefined globalThis.fetch = async (_url: string, init?: RequestInit) => { lastInit = init return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'content-type': 'application/json' } }) } const { http } = await import('./http.ts') test('GET: method=GET, 无 body, 无 Content-Type', async () => { await http.get('/api/v1/matches') assert.equal(lastInit?.method, 'GET') assert.equal(lastInit?.body, undefined) assert.equal((lastInit?.headers as Record)?.['Content-Type'], undefined) }) test('POST: method=POST, 序列化 body, 有 Content-Type', async () => { await http.post('/api/v1/matches', { a: 1 }) assert.equal(lastInit?.method, 'POST') assert.equal(lastInit?.body, JSON.stringify({ a: 1 })) assert.equal((lastInit?.headers as Record)?.['Content-Type'], 'application/json') }) test('POST 空 body: 不设 Content-Type', async () => { await http.post('/api/v1/matches', undefined) assert.equal(lastInit?.method, 'POST') assert.equal(lastInit?.body, undefined) assert.equal((lastInit?.headers as Record)?.['Content-Type'], undefined) }) test('PUT: method=PUT, 有 body 与 Content-Type', async () => { await http.put('/api/v1/x', { b: 2 }) assert.equal(lastInit?.method, 'PUT') assert.equal(lastInit?.body, JSON.stringify({ b: 2 })) assert.equal((lastInit?.headers as Record)?.['Content-Type'], 'application/json') }) test('DELETE: method=DELETE, 无 body, 无 Content-Type', async () => { await http.delete('/api/v1/x/1') assert.equal(lastInit?.method, 'DELETE') assert.equal(lastInit?.body, undefined) assert.equal((lastInit?.headers as Record)?.['Content-Type'], undefined) })