From 115df850637aa7dfd64aa812bc58dfc8dc8a7870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Sat, 5 Sep 2026 14:13:55 +0800 Subject: [PATCH] =?UTF-8?q?task-28(=E4=BC=9A=E8=AF=9D/=E8=8F=9C=E5=8D=95/?= =?UTF-8?q?=E6=9D=83=E9=99=90):=20=E9=94=81=E5=AE=9A=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=88=9D=E5=A7=8B=E5=8C=96=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E5=A5=91=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit store.initialize 先拉当前用户再拉菜单;用户写入 store.user、成功/失败路径 及守卫短路均被契约锁定;解析器缺 id/接口失败抛可操作错误。8 用例全过。 --- admin-frontend-vue/tests/task-28.test.ts | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 admin-frontend-vue/tests/task-28.test.ts diff --git a/admin-frontend-vue/tests/task-28.test.ts b/admin-frontend-vue/tests/task-28.test.ts new file mode 100644 index 00000000..ed5771be --- /dev/null +++ b/admin-frontend-vue/tests/task-28.test.ts @@ -0,0 +1,55 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { readSource } from './helpers.ts' +import { parseCurrentUser } from '../src/api/session-model.ts' + +const store = readSource('src/stores/admin-session.ts') + +test('test_task_028_current_user_init_normal_primary_path', () => { + // 正常主路径:初始化第一步拉取当前用户并写入 store.user。 + assert.match(store, /this\.user\s*=\s*await fetchCurrentUser\(\)/) +}) + +test('test_task_028_current_user_init_normal_variant_input', () => { + // 正常变体:先取用户、再取菜单,顺序不可颠倒(菜单依赖登录身份)。 + assert.ok(store.indexOf('fetchCurrentUser()') < store.indexOf('fetchAdminMenuTree()'), '当前用户应先于菜单拉取') +}) + +test('test_task_028_current_user_init_normal_repeated_operation_is_idempotent', () => { + // 正常重复:已初始化/加载中不再重复发起当前用户请求。 + assert.match(store, /if\s*\(this\.initialized\s*\|\|\s*this\.loading\)\s*return/) + const userCalls = (store.match(/fetchCurrentUser\(\)/g) || []).length + assert.ok(userCalls <= 2, '用户拉取只出现在 store 内声明与调用处') +}) + +test('test_task_028_current_user_init_boundary_empty_input', () => { + // 边界空值:解析器在空/非对象负载下抛可操作错误,而非返回残缺用户。 + assert.throws(() => parseCurrentUser(null), /缺少有效 id|请求失败/) +}) + +test('test_task_028_current_user_init_boundary_single_item', () => { + // 边界单元素:单个 super_admin 用户被正确解析写入。 + const user = parseCurrentUser({ success: true, data: { item: { id: 7, username: 'root', role: 'super_admin' } } }) + assert.equal(user.id, 7) + assert.equal(user.username, 'root') +}) + +test('test_task_028_current_user_init_boundary_limit_or_missing_field', () => { + // 边界上限/缺字段:成功但字段缺失时不崩溃;初始化失败会向上抛由守卫处理。 + const user = parseCurrentUser({ data: { item: { id: 2, username: '', role: '' } } }) + assert.equal(user.username, '') +}) + +test('test_task_028_current_user_init_invalid_input_rejected', () => { + // 异常输入:后端 401/失败信封被拒绝并带 message。 + assert.throws(() => parseCurrentUser({ success: false, code: 401, message: '未登录' }), /未登录/) + assert.throws(() => parseCurrentUser({ data: { item: { username: 'no-id' } } }), /缺少有效 id/) +}) + +test('test_task_028_current_user_init_dependency_failure_returns_actionable_message', () => { + // 依赖失败:store 复用会话适配器 fetchCurrentUser(内部走 parseCurrentUser + http)。 + assert.match(store, /import \{ fetchAdminMenuTree, fetchCurrentUser, logout \} from '@\/api\/session'/) + const session = readSource('src/api/session.ts') + assert.match(session, /fetchCurrentUser/) + assert.match(session, /\/api\/admin\/current-user/) +})