import assert from 'node:assert/strict' import { Server } from 'node:http' import { AddressInfo } from 'node:net' import { afterEach, test } from 'node:test' import { createApp } from '../src' const servers: Server[] = [] afterEach(async () => { await Promise.all( servers.splice(0).map(server => new Promise((resolve, reject) => { server.close(error => error ? reject(error) : resolve()) })) ) }) async function start(options: Parameters[0] = {}) { const server = createApp(options).listen(0, '127.0.0.1') servers.push(server) await new Promise(resolve => server.once('listening', resolve)) const { port } = server.address() as AddressInfo return `http://127.0.0.1:${port}` } test('health 保持稳定响应契约', async () => { const baseUrl = await start() const response = await fetch(`${baseUrl}/health`) assert.equal(response.status, 200) assert.deepEqual(await response.json(), { status: 'ok', service: 'xuqm-symbolicator', version: '1.0.0', }) assert.equal(response.headers.get('x-powered-by'), null) }) test('配置 API Key 时拒绝未认证请求', async () => { const baseUrl = await start({ apiKey: 'test-only-key' }) const response = await fetch(`${baseUrl}/api/symbolicate`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ platform: 'android', stacktrace: 'sample' }), }) assert.equal(response.status, 401) assert.deepEqual(await response.json(), { success: false, error: 'Unauthorized: invalid or missing API key', }) }) test('Android 反混淆接口保持既有请求响应结构', async () => { const baseUrl = await start() const response = await fetch(`${baseUrl}/api/symbolicate`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ platform: 'android', stacktrace: 'at a.b.c.a(r8-map-id-sample:13)', mappingFile: [ 'com.example.Sample -> a.b.c:', ' 13:13:void com.example.Sample.run():42:42 -> a', ].join('\n'), }), }) assert.equal(response.status, 200) const body = await response.json() as { success: boolean; symbolicated: string } assert.equal(body.success, true) assert.match(body.symbolicated, /com\.example\.Sample\.[\w$]+\(Sample\.kt:42\)/) }) test('请求体超限返回受控错误且不进入业务处理', async () => { const baseUrl = await start({ bodyLimit: '1kb' }) const response = await fetch(`${baseUrl}/api/symbolicate`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ platform: 'rn', stacktrace: 'x'.repeat(2048), sourcemap: '{}', }), }) assert.equal(response.status, 413) assert.deepEqual(await response.json(), { success: false, error: 'request body too large', }) })