Files
admin-web/src/modules/iam/pages/PermissionsDialog.behavior.test.ts
T
2026-09-15 09:58:15 +08:00

70 lines
4.5 KiB
TypeScript

import ElementPlus, { type FormInstance } from 'element-plus'
import { createPinia, setActivePinia } from 'pinia'
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { useAuthStore } from '@/core/auth/auth'
import AppDialog from '@/shared/components/AppDialog.vue'
import { createPlatformPermission, listPlatformPermissions, updatePlatformPermission } from '../api/platformIam'
import PermissionsView from './PermissionsView.vue'
vi.mock('../api/platformIam', () => ({
listPlatformPermissions: vi.fn(), createPlatformPermission: vi.fn(), updatePlatformPermission: vi.fn(),
changePlatformPermissionStatus: vi.fn(), deletePlatformPermission: vi.fn(),
}))
enableAutoUnmount(afterEach)
afterEach(() => { document.body.innerHTML = ''; vi.unstubAllGlobals(); vi.clearAllMocks() })
describe('permission editor modal', () => {
it.each(['create', 'edit'])('keeps the %s form in the centered dialog and preserves failed writes', async mode => {
vi.stubGlobal('ResizeObserver', class { observe() {} unobserve() {} disconnect() {} })
const pinia = createPinia()
setActivePinia(pinia)
const auth = useAuthStore()
auth.isServerSession = true
auth.permissions = ['platform:permission:list', 'platform:permission:create', 'platform:permission:edit']
vi.mocked(listPlatformPermissions).mockResolvedValue([{
id: '90071992547409931', tenantId: 0, appCode: 'PLATFORM', permissionType: 'MENU', parentId: 0,
permissionCode: 'platform:sample:list', permissionName: '测试菜单', routePath: '/sample',
httpMethod: null, sortNo: 10, status: 'ACTIVE',
}])
vi.mocked(createPlatformPermission).mockRejectedValue(new Error('保存失败'))
vi.mocked(updatePlatformPermission).mockRejectedValue(new Error('保存失败'))
const wrapper = mount(PermissionsView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
await flushPromises()
await wrapper.findAll(mode === 'create' ? 'button' : '.el-table__body-wrapper button').find(button => button.text().trim() === (mode === 'create' ? '新增权限' : '编辑'))!.trigger('click')
await flushPromises()
const dialog = document.querySelector<HTMLElement>('.el-dialog.permission-editor-dialog.admin-density-dialog')!
expect(dialog).not.toBeNull()
expect(dialog.style.getPropertyValue('--el-dialog-width')).toBe('min(720px, calc(100vw - 28px))')
expect(document.querySelector('.el-drawer')).toBeNull()
expect(dialog.querySelectorAll('.el-form-item')).toHaveLength(6)
const codeInput = dialog.querySelector<HTMLInputElement>('input[placeholder="如:platform:customer:list"]')!
expect(codeInput.disabled).toBe(mode === 'edit')
// Vitest externalizes Element Plus: its CJS validator interop differs from the Vite browser bundle.
// Exercise the dialog's validation gate explicitly, without changing production rules.
const form = wrapper.findComponent({ name: 'ElForm' })
expect(form.props('rules').name).toEqual(expect.arrayContaining([expect.objectContaining({ required: true })]))
const validate = vi.spyOn(form.vm.$.exposed as FormInstance, 'validate').mockResolvedValue(true)
if (mode === 'create') {
validate.mockRejectedValueOnce({ name: [{ message: '请输入权限名称' }] })
wrapper.getComponent(AppDialog).vm.$emit('confirm')
await flushPromises()
expect(createPlatformPermission).not.toHaveBeenCalled()
for (const [placeholder, value] of [['用户可理解的中文名称', '新增菜单'], ['如:platform:customer:list', 'platform:new:list'], ['如:/customers', '/new']]) {
const input = dialog.querySelector<HTMLInputElement>(`input[placeholder="${placeholder}"]`)!
input.value = value!
input.dispatchEvent(new Event('input', { bubbles: true }))
}
}
await flushPromises()
wrapper.getComponent(AppDialog).vm.$emit('confirm')
await flushPromises()
if (mode === 'create') expect(createPlatformPermission).toHaveBeenCalledWith({ type: 'MENU', code: 'platform:new:list', name: '新增菜单', parentId: '0', routePath: '/new', httpMethod: null, sortNo: 10 })
else expect(updatePlatformPermission).toHaveBeenCalledWith('90071992547409931', { name: '测试菜单', parentId: null, routePath: '/sample', httpMethod: null, sortNo: 10 })
expect(wrapper.getComponent(AppDialog).props('modelValue')).toBe(true)
expect(codeInput.value).toBe(mode === 'create' ? 'platform:new:list' : 'platform:sample:list')
})
})