| | |
| | | import assert from 'node:assert/strict' |
| | | import fs from 'node:fs' |
| | | import test from 'node:test' |
| | | |
| | | import { |
| | | buildScopeTreeNodes, |
| | | buildScopeSavePayload, |
| | | SCOPE_TYPES |
| | | } from '../src/views/system/role/roleScope.config.js' |
| | | buildRoleDialogModel, |
| | | buildRolePageQueryParams, |
| | | buildRoleSavePayload, |
| | | buildRoleScopeSubmitPayload, |
| | | buildRoleSearchParams, |
| | | getRoleScopeConfig, |
| | | normalizeRoleScopeTreeData, |
| | | normalizeRoleListRow, |
| | | createRoleSearchState |
| | | } from '../src/views/system/role/rolePage.helpers.js' |
| | | import { resolveBackendMenuTitle } from '../src/utils/backend-menu-title.js' |
| | | |
| | | test('menu scope nodes preserve backend ids for save', () => { |
| | | const tree = buildScopeTreeNodes(SCOPE_TYPES.menu, [{ id: 1, label: '系统管理' }]) |
| | | assert.equal(tree[0].id, 1) |
| | | const rolePermissionDialogSource = fs.readFileSync( |
| | | new URL('../src/views/system/role/modules/role-permission-dialog.vue', import.meta.url), |
| | | 'utf8' |
| | | ) |
| | | const roleEditDialogSource = fs.readFileSync( |
| | | new URL('../src/views/system/role/modules/role-edit-dialog.vue', import.meta.url), |
| | | 'utf8' |
| | | ) |
| | | const roleIndexSource = fs.readFileSync( |
| | | new URL('../src/views/system/role/index.vue', import.meta.url), |
| | | 'utf8' |
| | | ) |
| | | |
| | | test('buildRoleSearchParams keeps real role search fields', () => { |
| | | assert.deepEqual( |
| | | buildRoleSearchParams({ |
| | | name: '管理员', |
| | | code: 'R_ADMIN', |
| | | memo: '核心角色', |
| | | status: 1, |
| | | condition: 'admin' |
| | | }), |
| | | { |
| | | name: '管理员', |
| | | code: 'R_ADMIN', |
| | | memo: '核心角色', |
| | | status: 1, |
| | | condition: 'admin' |
| | | } |
| | | ) |
| | | }) |
| | | |
| | | test('scope save payload is delegated per scope type', () => { |
| | | const payload = buildScopeSavePayload(SCOPE_TYPES.menu, { |
| | | roleId: 9, |
| | | selectedIds: [1, 2], |
| | | authType: 0 |
| | | test('buildRolePageQueryParams merges paging and search fields', () => { |
| | | assert.deepEqual( |
| | | buildRolePageQueryParams({ |
| | | current: 3, |
| | | size: 20, |
| | | name: '管理员' |
| | | }), |
| | | { |
| | | current: 3, |
| | | pageSize: 20, |
| | | name: '管理员' |
| | | } |
| | | ) |
| | | }) |
| | | assert.equal(payload.id, 9) |
| | | |
| | | test('buildRoleDialogModel normalizes backend role data into the form model', () => { |
| | | assert.deepEqual( |
| | | buildRoleDialogModel({ |
| | | id: 7, |
| | | name: '管理员', |
| | | code: 'R_ADMIN', |
| | | memo: '核心角色', |
| | | status: 0 |
| | | }), |
| | | { |
| | | id: 7, |
| | | name: '管理员', |
| | | code: 'R_ADMIN', |
| | | memo: '核心角色', |
| | | status: 0 |
| | | } |
| | | ) |
| | | }) |
| | | |
| | | test('buildRoleSavePayload submits backend role fields', () => { |
| | | assert.deepEqual( |
| | | buildRoleSavePayload({ |
| | | id: 7, |
| | | name: '管理员', |
| | | code: 'R_ADMIN', |
| | | memo: '核心角色', |
| | | status: 1 |
| | | }), |
| | | { |
| | | id: 7, |
| | | name: '管理员', |
| | | code: 'R_ADMIN', |
| | | memo: '核心角色', |
| | | status: 1 |
| | | } |
| | | ) |
| | | }) |
| | | |
| | | test('normalizeRoleListRow exposes table friendly fields', () => { |
| | | const normalized = normalizeRoleListRow({ |
| | | id: 7, |
| | | name: '管理员', |
| | | code: 'R_ADMIN', |
| | | memo: '核心角色', |
| | | status: 1, |
| | | createTime: '2025-03-28 10:00:00', |
| | | updateTime: '2025-03-28 11:00:00' |
| | | }) |
| | | |
| | | assert.equal(normalized.name, '管理员') |
| | | assert.equal(normalized.statusBool, true) |
| | | assert.equal(normalized.statusText, '正常') |
| | | assert.equal(normalized.statusType, 'success') |
| | | assert.equal(normalized.createTimeText, '2025-03-28 10:00:00') |
| | | assert.equal(normalized.updateTimeText, '2025-03-28 11:00:00') |
| | | }) |
| | | |
| | | test('buildRoleScopeSubmitPayload normalizes checked keys for backend scope update', () => { |
| | | assert.deepEqual( |
| | | buildRoleScopeSubmitPayload(7, ['1', 2], ['3']), |
| | | { |
| | | id: 7, |
| | | menuIds: { |
| | | checked: [1, 2], |
| | | halfChecked: [3] |
| | | } |
| | | } |
| | | ) |
| | | }) |
| | | |
| | | test('getRoleScopeConfig resolves the four backend scope contracts', () => { |
| | | assert.deepEqual(getRoleScopeConfig('menu'), { |
| | | scopeType: 'menu', |
| | | title: '网页权限', |
| | | listUrl: '/role/scope/list', |
| | | treeUrl: '/menu/tree' |
| | | }) |
| | | assert.deepEqual(getRoleScopeConfig('warehouse'), { |
| | | scopeType: 'warehouse', |
| | | title: '仓库权限', |
| | | listUrl: '/roleWarehouse/scope/list', |
| | | treeUrl: '/menuWarehouse/tree' |
| | | }) |
| | | assert.throws(() => getRoleScopeConfig('invalid'), /Unsupported scope type/i) |
| | | }) |
| | | |
| | | test('normalizeRoleScopeTreeData folds menu auth buttons into child nodes', () => { |
| | | const tree = normalizeRoleScopeTreeData('menu', [ |
| | | { |
| | | id: 1, |
| | | name: 'menu.role', |
| | | type: 0, |
| | | children: [ |
| | | { |
| | | id: 2, |
| | | name: 'Query Role', |
| | | type: 1, |
| | | authority: 'system:role:list' |
| | | } |
| | | ] |
| | | } |
| | | ]) |
| | | |
| | | assert.equal(tree[0].label, 'menus.role') |
| | | assert.equal(tree[0].children[0].isAuthButton, true) |
| | | assert.equal(tree[0].children[0].authMark, 'system:role:list') |
| | | }) |
| | | |
| | | test('resolveBackendMenuTitle translates legacy backend menu keys into readable labels', () => { |
| | | assert.equal(resolveBackendMenuTitle('menu.role'), '角色管理') |
| | | assert.equal(resolveBackendMenuTitle('menus.aiParam'), 'AI 参数') |
| | | assert.equal(resolveBackendMenuTitle('AI管理中心'), 'AI管理中心') |
| | | }) |
| | | |
| | | test('role permission dialog only loads the active scope instead of all scopes together', () => { |
| | | assert.match(rolePermissionDialogSource, /ensureScopeLoaded\(activeScopeType\.value, \{ force: true \}\)/) |
| | | assert.doesNotMatch(rolePermissionDialogSource, /loadAllScopeData/) |
| | | }) |
| | | |
| | | test('role permission dialog keeps scope tree search and readable labels', () => { |
| | | assert.match(rolePermissionDialogSource, /placeholder="搜索权限树"/) |
| | | assert.match(rolePermissionDialogSource, /reloadSelection: false/) |
| | | assert.match(rolePermissionDialogSource, /resolveBackendMenuTitle/) |
| | | }) |
| | | |
| | | test('role edit dialog keeps code optional to match the backend contract', () => { |
| | | assert.match(roleEditDialogSource, /name: \[\{ required: true, message: '请输入角色名称'/) |
| | | assert.doesNotMatch(roleEditDialogSource, /code: \[\{ required: true, message: '请输入角色编码'/) |
| | | }) |
| | | |
| | | test('role page uses semantic auth aliases so backend permissions render actions', () => { |
| | | assert.match(roleIndexSource, /v-auth=\"'add'\"/) |
| | | assert.match(roleIndexSource, /v-auth=\"'delete'\"/) |
| | | assert.match(roleIndexSource, /v-auth=\"'query'\"/) |
| | | assert.match(roleIndexSource, /auth: 'edit'/) |
| | | assert.match(roleIndexSource, /auth: 'delete'/) |
| | | }) |
| | | |
| | | test('createRoleSearchState exposes the role search form model', () => { |
| | | assert.deepEqual(createRoleSearchState(), { |
| | | name: '', |
| | | code: '', |
| | | memo: '', |
| | | status: void 0, |
| | | condition: '' |
| | | }) |
| | | }) |