Files
X-Financial/web/tests/api-request.test.mjs
caoxiaozhu 96c2e1099a feat(web): 统一平台管理员判定与 AI 工作台申请预览动作接入
- authUser 抽出 resolveAuthUserAdminFlag,统一 isAdmin 解析(含 superadmin、role_codes、中英文角色名),accessControl 复用同一逻辑
- 登录态、应用外壳路由、系统状态接入统一管理员判定,LoginView 与相关 composable 配套调整
- AI 工作台申请提交改为调用新的 /application-preview-action 接口,草稿保存仍走 orchestrator;预审模型补充重叠冲突提示与阻断判断
- 同步更新 accessControl/api-request/ai 预览动作等前端测试
2026-06-20 14:42:04 +08:00

206 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
})