task-3: callJava() 统一响应解包(JavaApiResponse/Legacy 兼容、success=false 抛错);开启 allowImportingTsExtensions 支持 node --test
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import { http, type RequestOptions } from './http.ts'
|
||||
|
||||
export interface JavaApiResponse<T> {
|
||||
success: boolean
|
||||
message: string
|
||||
data: T | null
|
||||
}
|
||||
|
||||
export interface LegacyApiSuccess<T> {
|
||||
success: true
|
||||
msg?: string
|
||||
data?: T
|
||||
}
|
||||
|
||||
export async function callJava<T = unknown, D = unknown>(
|
||||
config: RequestOptions<D>,
|
||||
): Promise<T> {
|
||||
const body = await http.request<unknown, unknown, D>(config)
|
||||
const data = (body as { data?: unknown }).data ?? body
|
||||
|
||||
if (
|
||||
data &&
|
||||
typeof data === 'object' &&
|
||||
'success' in data &&
|
||||
typeof (data as { success: unknown }).success === 'boolean'
|
||||
) {
|
||||
const wrapped = data as { success: boolean; message?: string; msg?: string; error?: string; data?: T }
|
||||
if (!wrapped.success) {
|
||||
throw new Error(wrapped.message || wrapped.msg || wrapped.error || '请求失败')
|
||||
}
|
||||
return wrapped.data as T
|
||||
}
|
||||
|
||||
return data as T
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { test } from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { http } from '../src/shared/api/http.ts'
|
||||
import { callJava } from '../src/shared/api/call.ts'
|
||||
|
||||
function mockResponse(t: Parameters<typeof test>[1] extends (t: infer T) => unknown ? T : never, body: unknown) {
|
||||
t.mock.method(http, 'request', async () => ({ data: body }) as never)
|
||||
}
|
||||
|
||||
test('test_call_java_success_unwraps', async (t) => {
|
||||
mockResponse(t, { success: true, message: 'ok', data: { taskId: 1, status: 'RUNNING' } })
|
||||
const result = await callJava<{ taskId: number; status: string }>({
|
||||
url: '/newApi/api/dedupe/run',
|
||||
method: 'POST',
|
||||
})
|
||||
assert.deepEqual(result, { taskId: 1, status: 'RUNNING' })
|
||||
})
|
||||
|
||||
test('test_call_java_legacy_msg_unwraps', async (t) => {
|
||||
mockResponse(t, { success: true, msg: 'ok', data: [1, 2, 3] })
|
||||
const result = await callJava<number[]>({ url: '/newApi/api/x', method: 'GET' })
|
||||
assert.deepEqual(result, [1, 2, 3])
|
||||
})
|
||||
|
||||
test('test_call_java_success_false_throws', async (t) => {
|
||||
mockResponse(t, { success: false, message: '任务不存在' })
|
||||
await assert.rejects(
|
||||
callJava({ url: '/newApi/api/x', method: 'GET' }),
|
||||
/任务不存在/,
|
||||
)
|
||||
})
|
||||
|
||||
test('test_call_java_message_precedence', async (t) => {
|
||||
mockResponse(t, { success: false, message: 'm1', msg: 'm2', error: 'm3' })
|
||||
await assert.rejects(callJava({ url: '/newApi/api/x', method: 'GET' }), /m1/, 'message 应优先于 msg/error')
|
||||
|
||||
mockResponse(t, { success: false, msg: 'm2', error: 'm3' })
|
||||
await assert.rejects(callJava({ url: '/newApi/api/x', method: 'GET' }), /m2/, '无 message 时 msg 优先于 error')
|
||||
|
||||
mockResponse(t, { success: false, error: 'm3' })
|
||||
await assert.rejects(callJava({ url: '/newApi/api/x', method: 'GET' }), /m3/, '仅 error 时回退 error')
|
||||
})
|
||||
|
||||
test('test_call_java_non_wrapped_passthrough', async (t) => {
|
||||
mockResponse(t, { hello: 'world', count: 3 })
|
||||
const result = await callJava<{ hello: string; count: number }>({
|
||||
url: '/newApi/api/x',
|
||||
method: 'GET',
|
||||
})
|
||||
assert.deepEqual(result, { hello: 'world', count: 3 })
|
||||
})
|
||||
|
||||
test('test_call_java_null_data', async (t) => {
|
||||
mockResponse(t, { success: true, message: 'ok', data: null })
|
||||
const result = await callJava<null>({ url: '/newApi/api/x', method: 'GET' })
|
||||
assert.equal(result, null)
|
||||
})
|
||||
|
||||
test('test_call_java_network_error', async (t) => {
|
||||
t.mock.method(http, 'request', async () => {
|
||||
throw new Error('Network Error')
|
||||
})
|
||||
await assert.rejects(
|
||||
callJava({ url: '/newApi/api/x', method: 'GET' }),
|
||||
/Network Error/,
|
||||
)
|
||||
})
|
||||
|
||||
test('test_call_java_http_error_status', async (t) => {
|
||||
t.mock.method(http, 'request', async () => {
|
||||
throw new Error('404 接口不存在')
|
||||
})
|
||||
await assert.rejects(
|
||||
callJava({ url: '/newApi/api/x', method: 'GET' }),
|
||||
/404 接口不存在/,
|
||||
)
|
||||
})
|
||||
@@ -8,6 +8,7 @@
|
||||
"jsx": "preserve",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"ES2020",
|
||||
|
||||
Reference in New Issue
Block a user