Files
X-Financial/web/tests/api-request.test.mjs

206 lines
5.0 KiB
JavaScript
Raw Normal View History

import assert from 'node:assert/strict'
import { apiRequest } from '../src/services/api.js'
async function testUsesCustomContentTypeHeader() {
let capturedOptions = null
global.fetch = async (_url, options) => {
capturedOptions = options
return {
ok: true,
async json() {
return { ok: true }
}
}
}
await apiRequest('/knowledge/documents', {
method: 'POST',
body: 'payload',
contentType: 'application/octet-stream'
})
assert.equal(capturedOptions.headers['Content-Type'], 'application/octet-stream')
}
async function testSupportsBlobResponses() {
const blob = new Blob(['preview'])
global.fetch = async () => ({
ok: true,
async blob() {
return blob
},
async json() {
throw new Error('json parser should not be used for blob responses')
}
})
const payload = await apiRequest('/knowledge/documents/demo/content', {
responseType: 'blob',
contentType: null
})
assert.equal(payload, blob)
}
async function testInjectsAuthenticatedUserHeaders() {
const sessionStorage = new Map([
[
'x-financial-auth-user',
JSON.stringify({
username: 'admin',
name: 'Admin User',
employeePosition: 'System Manager',
employeeGrade: 'M5',
employeeNo: 'E-001',
managerName: 'Approver User',
roleCodes: ['manager'],
isAdmin: true
})
]
])
global.window = {
sessionStorage: {
getItem(key) {
return sessionStorage.get(key) ?? null
}
}
}
let capturedOptions = null
global.fetch = async (_url, options) => {
capturedOptions = options
return {
ok: true,
async json() {
return { ok: true }
}
}
}
await apiRequest('/knowledge/library')
assert.equal(capturedOptions.headers['x-auth-username'], 'admin')
assert.equal(capturedOptions.headers['x-auth-name'], 'Admin User')
assert.equal(capturedOptions.headers['x-auth-position'], 'System Manager')
assert.equal(capturedOptions.headers['x-auth-grade'], 'M5')
assert.equal(capturedOptions.headers['x-auth-employee-no'], 'E-001')
assert.equal(capturedOptions.headers['x-auth-manager-name'], 'Approver User')
assert.equal(capturedOptions.headers['x-auth-role-codes'], 'manager')
assert.equal(capturedOptions.headers['x-auth-is-admin'], 'true')
}
async function testInjectsLegacyAdminHeaderFromSnakeCaseFlag() {
const sessionStorage = new Map([
[
'x-financial-auth-user',
JSON.stringify({
username: 'superadmin',
name: 'superadmin',
roleCodes: ['manager'],
is_admin: true
})
]
])
global.window = {
sessionStorage: {
getItem(key) {
return sessionStorage.get(key) ?? null
}
}
}
let capturedOptions = null
global.fetch = async (_url, options) => {
capturedOptions = options
return {
ok: true,
async json() {
return { ok: true }
}
}
}
await apiRequest('/reimbursements/claims/demo', { method: 'DELETE' })
assert.equal(capturedOptions.headers['x-auth-username'], 'superadmin')
assert.equal(capturedOptions.headers['x-auth-role-codes'], 'manager')
assert.equal(capturedOptions.headers['x-auth-is-admin'], 'true')
}
async function testFormatsValidationErrors() {
global.fetch = async () => ({
ok: false,
async json() {
return {
detail: [
{
loc: ['body', 'email'],
msg: 'value is not a valid email address'
},
{
loc: ['body', 'password'],
msg: 'String should have at least 5 characters'
}
]
}
}
})
await assert.rejects(
() => apiRequest('/employees/demo', { method: 'PATCH', body: '{}' }),
(error) => {
assert.equal(
error.message,
'email: value is not a valid email addresspassword: String should have at least 5 characters'
)
return true
}
)
}
async function testRejectsWithCustomTimeoutMessage() {
global.fetch = async (_url, options) =>
new Promise((_, reject) => {
options.signal.addEventListener('abort', () => {
const error = new Error('aborted')
error.name = 'AbortError'
reject(error)
})
})
await assert.rejects(
() =>
apiRequest('/knowledge/library', {
timeoutMs: 1,
timeoutMessage: '知识问答整理超时,已停止等待。'
}),
(error) => {
assert.equal(error.message, '知识问答整理超时,已停止等待。')
assert.equal(error.code, 'REQUEST_TIMEOUT')
return true
}
)
}
async function run() {
await testUsesCustomContentTypeHeader()
await testSupportsBlobResponses()
await testInjectsAuthenticatedUserHeaders()
await testInjectsLegacyAdminHeaderFromSnakeCaseFlag()
await testFormatsValidationErrors()
await testRejectsWithCustomTimeoutMessage()
console.log('api-request tests passed')
}
run().catch((error) => {
console.error(error)
process.exit(1)
})