Files
novalon-manage-system/novalon-manage-web/e2e/role-based-tests/shared/permission-helper.ts
T
张翔 89ccb4e52f feat: 实现权限验证工具
- 创建 PermissionHelper 类
- 支持验证页面访问权限
- 支持验证CRUD操作权限
- 支持验证角色权限边界
- 添加基础单元测试(5个测试用例全部通过)
2026-04-04 20:56:35 +08:00

132 lines
4.3 KiB
TypeScript

import { Page, expect } from '@playwright/test';
import type { RoleDefinition } from '../roles/base.role';
export class PermissionHelper {
constructor(private page: Page) {}
async verifyCanAccess(path: string): Promise<void> {
await this.page.goto(path);
await expect(this.page).not.toHaveURL(/\/login/);
await expect(this.page).not.toHaveURL(/\/403/);
await expect(this.page).not.toHaveURL(/\/404/);
}
async verifyCannotAccess(path: string): Promise<void> {
await this.page.goto(path);
// 应该被重定向到登录页或显示403错误
const url = this.page.url();
const isForbidden = url.includes('/403') || url.includes('/login');
expect(isForbidden || await this.isAccessDenied()).toBeTruthy();
}
private async isAccessDenied(): Promise<boolean> {
const deniedMessage = this.page.locator('text=/无权限|权限不足|Access Denied|Forbidden/i');
return await deniedMessage.count() > 0;
}
async verifyCanCreate(resource: string, createButtonSelector: string): Promise<void> {
const createButton = this.page.locator(createButtonSelector);
await expect(createButton).toBeVisible();
await expect(createButton).toBeEnabled();
}
async verifyCannotCreate(resource: string, createButtonSelector: string): Promise<void> {
const createButton = this.page.locator(createButtonSelector);
const count = await createButton.count();
if (count > 0) {
await expect(createButton).not.toBeVisible();
}
}
async verifyCanEdit(resourceId: string, editButtonSelector: string): Promise<void> {
const editButton = this.page.locator(editButtonSelector);
await expect(editButton).toBeVisible();
await expect(editButton).toBeEnabled();
}
async verifyCannotEdit(resourceId: string, editButtonSelector: string): Promise<void> {
const editButton = this.page.locator(editButtonSelector);
const count = await editButton.count();
if (count > 0) {
await expect(editButton).not.toBeVisible();
}
}
async verifyCanDelete(resourceId: string, deleteButtonSelector: string): Promise<void> {
const deleteButton = this.page.locator(deleteButtonSelector);
await expect(deleteButton).toBeVisible();
await expect(deleteButton).toBeEnabled();
}
async verifyCannotDelete(resourceId: string, deleteButtonSelector: string): Promise<void> {
const deleteButton = this.page.locator(deleteButtonSelector);
const count = await deleteButton.count();
if (count > 0) {
await expect(deleteButton).not.toBeVisible();
}
}
async verifyRolePermissions(role: RoleDefinition): Promise<void> {
// 验证可访问的路径
for (const path of role.expectedBehaviors.canRead) {
if (path !== 'self') {
await this.verifyCanAccess(`/${path}`);
}
}
// 验证不可访问的路径
for (const path of role.cannotAccess) {
await this.verifyCannotAccess(path);
}
}
async verifyPermissionBoundary(
role: RoleDefinition,
testScenarios: {
resource: string;
path: string;
createButton?: string;
editButton?: string;
deleteButton?: string;
}
): Promise<void> {
await this.page.goto(testScenarios.path);
// 验证创建权限
if (testScenarios.createButton) {
if (role.expectedBehaviors.canCreate.includes(testScenarios.resource)) {
await this.verifyCanCreate(testScenarios.resource, testScenarios.createButton);
} else {
await this.verifyCannotCreate(testScenarios.resource, testScenarios.createButton);
}
}
// 验证编辑权限
if (testScenarios.editButton) {
if (role.expectedBehaviors.canUpdate.includes(testScenarios.resource)) {
await this.verifyCanEdit(testScenarios.resource, testScenarios.editButton);
} else {
await this.verifyCannotEdit(testScenarios.resource, testScenarios.editButton);
}
}
// 验证删除权限
if (testScenarios.deleteButton) {
if (role.expectedBehaviors.canDelete.includes(testScenarios.resource)) {
await this.verifyCanDelete(testScenarios.resource, testScenarios.deleteButton);
} else {
await this.verifyCannotDelete(testScenarios.resource, testScenarios.deleteButton);
}
}
}
}
export function createPermissionHelper(page: Page): PermissionHelper {
return new PermissionHelper(page);
}