import { createPinia, setActivePinia } from 'pinia' import { flushPromises, shallowMount } from '@vue/test-utils' import { beforeEach, describe, expect, it, vi } from 'vitest' import { listPlatformPermissions, type PlatformPermissionResource } from '@/modules/iam/api/platformIam' import { useAuthStore } from '@/core/auth/auth' import PermissionsView from './PermissionsView.vue' vi.mock('@/modules/iam/api/platformIam', () => ({ changePlatformPermissionStatus: vi.fn(), createPlatformPermission: vi.fn(), deletePlatformPermission: vi.fn(), listPlatformPermissions: vi.fn(), updatePlatformPermission: vi.fn(), })) const permission: PlatformPermissionResource = { id: 5100010, tenantId: 0, appCode: 'PLATFORM', permissionType: 'MENU', parentId: 0, permissionCode: 'platform:customer:list', permissionName: '企业客户', routePath: '/customers', httpMethod: null, sortNo: 10, status: 'ACTIVE', } const allActionPermissions = [ 'platform:permission:list', 'platform:permission:create', 'platform:permission:edit', 'platform:permission:status', 'platform:permission:delete', ] function mountServerView(permissionCodes = ['platform:permission:list', 'platform:permission:create']) { const pinia = createPinia() setActivePinia(pinia) const auth = useAuthStore() auth.isServerSession = true auth.permissions = permissionCodes return shallowMount(PermissionsView, { global: { plugins: [pinia], directives: { loading: () => undefined }, stubs: { AdminPage: { template: '
' }, ListPageLayout: { template: '
' }, FormSection: { template: '
' }, AppDrawer: { template: '
' }, LoadErrorState: { props: ['message'], template: '
{{ message }}
' }, DataTable: { props: ['data'], template: '
{{ data.length }}
', }, 'el-alert': { props: ['title'], template: '
{{ title }}
' }, 'el-input': true, 'el-option': true, 'el-select': true, 'el-button': { props: ['disabled'], template: '' }, 'el-dropdown': { template: '' }, 'el-dropdown-menu': { template: '
' }, 'el-dropdown-item': { props: ['disabled'], template: '' }, 'el-table': true, 'el-table-column': true, 'el-input-number': true, 'el-radio-group': true, 'el-radio-button': true, 'el-drawer': { template: '
' }, 'el-form': { template: '
' }, 'el-form-item': { template: '' }, }, }, }) } describe('PermissionsView IAM mode', () => { beforeEach(() => { vi.mocked(listPlatformPermissions).mockReset() }) it('loads the platform permission resource tree from IAM', async () => { vi.mocked(listPlatformPermissions).mockResolvedValue([permission]) const wrapper = mountServerView() await flushPromises() expect(listPlatformPermissions).toHaveBeenCalledTimes(1) expect(wrapper.text()).not.toContain('权限资源树') }) it('shows a recoverable state when the permission list fails', async () => { vi.mocked(listPlatformPermissions).mockRejectedValue(new Error('IAM unavailable')) const wrapper = mountServerView() await flushPromises() const alertText = wrapper.findAll('[role="alert"]').map((item) => item.text()).join(' ') expect(alertText).toContain('权限资源加载失败,请稍后重试') expect(alertText).not.toContain('IAM unavailable') }) it('shows only add-child directly for a built-in menu even with all permissions', async () => { vi.mocked(listPlatformPermissions).mockResolvedValue([{ ...permission, builtIn: true }]) const wrapper = mountServerView(allActionPermissions) await flushPromises() const actions = wrapper.get('[data-row-id="5100010"]') expect(actions.text()).toContain('添加下级') expect(actions.text()).not.toContain('系统内置') expect(actions.text()).not.toContain('编辑') expect(actions.text()).not.toContain('停用') expect(actions.text()).not.toContain('删除') expect(actions.find('.dropdown').exists()).toBe(false) }) it('keeps three frequent actions direct and moves delete into more for a custom menu', async () => { vi.mocked(listPlatformPermissions).mockResolvedValue([{ ...permission, builtIn: false }]) const wrapper = mountServerView(allActionPermissions) await flushPromises() const actions = wrapper.get('[data-row-id="5100010"]') expect(actions.text()).toContain('添加下级') expect(actions.text()).toContain('编辑') expect(actions.text()).toContain('停用') expect(actions.get('.dropdown').text()).toContain('删除') expect(actions.get('.dropdown-item').classes()).toContain('danger-menu-item') expect(actions.get('[aria-label="企业客户的更多操作"]').attributes('title')).toBe('企业客户的更多操作') }) it('shows edit, status, and delete directly for a custom non-menu resource', async () => { vi.mocked(listPlatformPermissions).mockResolvedValue([{ ...permission, permissionType: 'BUTTON', permissionCode: 'platform:customer:edit', permissionName: '编辑企业客户', routePath: null, builtIn: false, }]) const wrapper = mountServerView(allActionPermissions) await flushPromises() const actions = wrapper.get('[data-row-id="5100010"]') expect(actions.text()).not.toContain('添加下级') expect(actions.text()).toContain('编辑') expect(actions.text()).toContain('停用') expect(actions.text()).toContain('删除') expect(actions.find('.dropdown').exists()).toBe(false) }) it('shows all three actually available menu actions directly when permissions are reduced', async () => { vi.mocked(listPlatformPermissions).mockResolvedValue([{ ...permission, builtIn: false }]) const wrapper = mountServerView([ 'platform:permission:list', 'platform:permission:create', 'platform:permission:edit', 'platform:permission:delete', ]) await flushPromises() const actions = wrapper.get('[data-row-id="5100010"]') expect(actions.text()).toContain('添加下级') expect(actions.text()).toContain('编辑') expect(actions.text()).toContain('删除') expect(actions.text()).not.toContain('停用') expect(actions.find('.dropdown').exists()).toBe(false) }) it('falls back from a missing name and code to the row id for the more-action label', async () => { vi.mocked(listPlatformPermissions).mockResolvedValue([{ ...permission, permissionName: '', permissionCode: '', builtIn: false, }]) const wrapper = mountServerView(allActionPermissions) await flushPromises() const moreButton = wrapper.get('[data-row-id="5100010"] [aria-label="当前权限的更多操作"]') expect(moreButton.attributes('title')).toBe('当前权限的更多操作') expect(moreButton.attributes('aria-label')).not.toMatch(/undefined|null/) }) it('gives more-action buttons distinct accessible names across rows', async () => { vi.mocked(listPlatformPermissions).mockResolvedValue([ { ...permission, builtIn: false }, { ...permission, id: 5100020, permissionCode: 'platform:role:list', permissionName: '角色管理', routePath: '/roles', builtIn: false, }, ]) const wrapper = mountServerView(allActionPermissions) await flushPromises() const labels = wrapper.findAll('[aria-label$="的更多操作"]').map((button) => button.attributes('aria-label')) expect(labels).toEqual(['企业客户的更多操作', '角色管理的更多操作']) expect(new Set(labels).size).toBe(labels.length) }) })