08ea5fbe98
添加用户管理视图、API和状态管理文件
539 lines
16 KiB
TypeScript
539 lines
16 KiB
TypeScript
/**
|
|
* 角色管理工作流实现
|
|
* 实现角色管理相关的端到端业务流程
|
|
*/
|
|
|
|
import { Page } from '@playwright/test';
|
|
import { BusinessWorkflow } from '../core/business-workflows.js';
|
|
import { TestLogger } from '../core/test-logger.js';
|
|
import { TestDataManager, TestRole } from '../core/test-data-manager.js';
|
|
import { LoginPage } from '../pages/login-page.js';
|
|
import { RoleManagementPage } from '../pages/role-management-page.js';
|
|
|
|
export interface RoleWorkflowContext {
|
|
page: Page;
|
|
testLogger: TestLogger;
|
|
testDataManager: TestDataManager;
|
|
loginPage: LoginPage;
|
|
roleManagementPage: RoleManagementPage;
|
|
createdRole?: TestRole;
|
|
createdRoleId?: string;
|
|
}
|
|
|
|
/**
|
|
* 创建角色工作流
|
|
*/
|
|
export function createRoleWorkflow(context: RoleWorkflowContext): BusinessWorkflow {
|
|
const { page, testLogger, testDataManager, loginPage, roleManagementPage } = context;
|
|
|
|
return {
|
|
name: 'createRole',
|
|
description: '创建新角色的完整流程',
|
|
|
|
preconditions: async () => {
|
|
testLogger.info('🔍 检查前置条件: 用户已登录');
|
|
const currentUrl = page.url();
|
|
if (!currentUrl.includes('/dashboard') && !currentUrl.includes('/roles')) {
|
|
testLogger.info('用户未登录,执行登录');
|
|
await loginPage.navigate();
|
|
await loginPage.login('admin', 'admin123');
|
|
await page.waitForURL('**/dashboard', { timeout: 10000 });
|
|
}
|
|
return true;
|
|
},
|
|
|
|
steps: [
|
|
{
|
|
name: 'navigateToRoleManagement',
|
|
action: async () => {
|
|
testLogger.info('🌐 导航到角色管理页面');
|
|
await roleManagementPage.navigate();
|
|
await roleManagementPage.waitForLoad();
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'clickAddRoleButton',
|
|
action: async () => {
|
|
testLogger.info('🖱️ 点击新增角色按钮');
|
|
await roleManagementPage.clickAddRole();
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'fillRoleForm',
|
|
action: async () => {
|
|
testLogger.info('📝 填写角色表单');
|
|
context.createdRole = testDataManager.createTestRole();
|
|
|
|
await page.fill('input[name="name"]', context.createdRole.name);
|
|
await page.fill('input[name="roleKey"]', context.createdRole.code);
|
|
|
|
if (context.createdRole.description) {
|
|
await page.fill('textarea[name="description"]', context.createdRole.description);
|
|
}
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'submitRoleForm',
|
|
action: async () => {
|
|
testLogger.info('📤 提交角色表单');
|
|
await page.click('button[type="submit"]');
|
|
|
|
await page.waitForSelector('.el-message--success', {
|
|
state: 'visible',
|
|
timeout: 10000
|
|
});
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'verifyRoleCreated',
|
|
action: async () => {
|
|
testLogger.info('✅ 验证角色创建成功');
|
|
|
|
if (context.createdRole) {
|
|
await roleManagementPage.searchRole(context.createdRole.name);
|
|
const roleCount = await roleManagementPage.getRoleCount();
|
|
if (roleCount === 0) {
|
|
throw new Error('角色创建后未在列表中找到');
|
|
}
|
|
}
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
}
|
|
],
|
|
|
|
postconditions: async () => {
|
|
testLogger.info('🔍 检查后置条件: 角色创建成功');
|
|
return !!context.createdRole;
|
|
},
|
|
|
|
cleanup: async () => {
|
|
testLogger.info('🧹 执行清理操作');
|
|
if (context.createdRole) {
|
|
try {
|
|
await roleManagementPage.searchRole(context.createdRole.name);
|
|
const roleCount = await roleManagementPage.getRoleCount();
|
|
if (roleCount > 0) {
|
|
await roleManagementPage.clickDeleteRole(0);
|
|
await roleManagementPage.confirmDelete();
|
|
}
|
|
} catch (error) {
|
|
testLogger.warn('清理角色失败,可能角色不存在');
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 编辑角色工作流
|
|
*/
|
|
export function editRoleWorkflow(context: RoleWorkflowContext, targetRoleName?: string): BusinessWorkflow {
|
|
const { page, testLogger, testDataManager, loginPage, roleManagementPage } = context;
|
|
|
|
return {
|
|
name: 'editRole',
|
|
description: '编辑角色的完整流程',
|
|
|
|
preconditions: async () => {
|
|
testLogger.info('🔍 检查前置条件');
|
|
const currentUrl = page.url();
|
|
if (!currentUrl.includes('/dashboard') && !currentUrl.includes('/roles')) {
|
|
await loginPage.navigate();
|
|
await loginPage.login('admin', 'admin123');
|
|
await page.waitForURL('**/dashboard', { timeout: 10000 });
|
|
}
|
|
return true;
|
|
},
|
|
|
|
steps: [
|
|
{
|
|
name: 'navigateToRoleManagement',
|
|
action: async () => {
|
|
testLogger.info('🌐 导航到角色管理页面');
|
|
await roleManagementPage.navigate();
|
|
await roleManagementPage.waitForLoad();
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'searchRole',
|
|
action: async () => {
|
|
testLogger.info('🔍 搜索目标角色');
|
|
const searchRoleName = targetRoleName || context.createdRole?.name || 'admin';
|
|
await roleManagementPage.searchRole(searchRoleName);
|
|
|
|
const roleCount = await roleManagementPage.getRoleCount();
|
|
if (roleCount === 0) {
|
|
throw new Error(`未找到角色: ${searchRoleName}`);
|
|
}
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'clickEditButton',
|
|
action: async () => {
|
|
testLogger.info('🖱️ 点击编辑按钮');
|
|
await roleManagementPage.clickEditRole(0);
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'updateRoleForm',
|
|
action: async () => {
|
|
testLogger.info('📝 更新角色表单');
|
|
|
|
const newDescription = `Updated description ${Date.now()}`;
|
|
await page.fill('textarea[name="description"]', newDescription);
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'submitRoleForm',
|
|
action: async () => {
|
|
testLogger.info('📤 提交角色表单');
|
|
await page.click('button[type="submit"]');
|
|
|
|
await page.waitForSelector('.el-message--success', {
|
|
state: 'visible',
|
|
timeout: 10000
|
|
});
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'verifyRoleUpdated',
|
|
action: async () => {
|
|
testLogger.info('✅ 验证角色更新成功');
|
|
|
|
const successMessage = await roleManagementPage.getSuccessMessage();
|
|
if (!successMessage.includes('成功')) {
|
|
throw new Error('角色更新未显示成功消息');
|
|
}
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 删除角色工作流
|
|
*/
|
|
export function deleteRoleWorkflow(context: RoleWorkflowContext, targetRoleName?: string): BusinessWorkflow {
|
|
const { page, testLogger, roleManagementPage, loginPage } = context;
|
|
|
|
return {
|
|
name: 'deleteRole',
|
|
description: '删除角色的完整流程',
|
|
|
|
preconditions: async () => {
|
|
testLogger.info('🔍 检查前置条件');
|
|
const currentUrl = page.url();
|
|
if (!currentUrl.includes('/dashboard') && !currentUrl.includes('/roles')) {
|
|
await loginPage.navigate();
|
|
await loginPage.login('admin', 'admin123');
|
|
await page.waitForURL('**/dashboard', { timeout: 10000 });
|
|
}
|
|
return true;
|
|
},
|
|
|
|
steps: [
|
|
{
|
|
name: 'navigateToRoleManagement',
|
|
action: async () => {
|
|
testLogger.info('🌐 导航到角色管理页面');
|
|
await roleManagementPage.navigate();
|
|
await roleManagementPage.waitForLoad();
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'searchRole',
|
|
action: async () => {
|
|
testLogger.info('🔍 搜索目标角色');
|
|
const searchRoleName = targetRoleName || context.createdRole?.name;
|
|
if (!searchRoleName) {
|
|
throw new Error('未指定要删除的角色');
|
|
}
|
|
await roleManagementPage.searchRole(searchRoleName);
|
|
|
|
const roleCount = await roleManagementPage.getRoleCount();
|
|
if (roleCount === 0) {
|
|
throw new Error(`未找到角色: ${searchRoleName}`);
|
|
}
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'clickDeleteButton',
|
|
action: async () => {
|
|
testLogger.info('🖱️ 点击删除按钮');
|
|
await roleManagementPage.clickDeleteRole(0);
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'confirmDelete',
|
|
action: async () => {
|
|
testLogger.info('✅ 确认删除');
|
|
await roleManagementPage.confirmDelete();
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'verifyRoleDeleted',
|
|
action: async () => {
|
|
testLogger.info('✅ 验证角色删除成功');
|
|
|
|
const successMessage = await roleManagementPage.getSuccessMessage();
|
|
if (!successMessage.includes('成功')) {
|
|
throw new Error('角色删除未显示成功消息');
|
|
}
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 分配权限工作流
|
|
*/
|
|
export function assignPermissionsWorkflow(context: RoleWorkflowContext, targetRoleName?: string): BusinessWorkflow {
|
|
const { page, testLogger, roleManagementPage, loginPage } = context;
|
|
|
|
return {
|
|
name: 'assignPermissions',
|
|
description: '为角色分配权限的完整流程',
|
|
|
|
preconditions: async () => {
|
|
testLogger.info('🔍 检查前置条件');
|
|
const currentUrl = page.url();
|
|
if (!currentUrl.includes('/dashboard') && !currentUrl.includes('/roles')) {
|
|
await loginPage.navigate();
|
|
await loginPage.login('admin', 'admin123');
|
|
await page.waitForURL('**/dashboard', { timeout: 10000 });
|
|
}
|
|
return true;
|
|
},
|
|
|
|
steps: [
|
|
{
|
|
name: 'navigateToRoleManagement',
|
|
action: async () => {
|
|
testLogger.info('🌐 导航到角色管理页面');
|
|
await roleManagementPage.navigate();
|
|
await roleManagementPage.waitForLoad();
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'searchRole',
|
|
action: async () => {
|
|
testLogger.info('🔍 搜索目标角色');
|
|
const searchRoleName = targetRoleName || context.createdRole?.name || 'admin';
|
|
await roleManagementPage.searchRole(searchRoleName);
|
|
|
|
const roleCount = await roleManagementPage.getRoleCount();
|
|
if (roleCount === 0) {
|
|
throw new Error(`未找到角色: ${searchRoleName}`);
|
|
}
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'clickAssignPermissionsButton',
|
|
action: async () => {
|
|
testLogger.info('🖱️ 点击分配权限按钮');
|
|
await roleManagementPage.clickAssignPermissions(0);
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'selectPermissions',
|
|
action: async () => {
|
|
testLogger.info('📝 选择权限');
|
|
|
|
// 等待权限树加载
|
|
await page.waitForSelector('.el-tree', { timeout: 10000 });
|
|
|
|
// 选择一些权限节点(示例:选择第一个和第二个)
|
|
const checkboxes = await page.locator('.el-tree-node__content .el-checkbox').all();
|
|
if (checkboxes.length > 0) {
|
|
await checkboxes[0].click();
|
|
}
|
|
if (checkboxes.length > 1) {
|
|
await checkboxes[1].click();
|
|
}
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'savePermissions',
|
|
action: async () => {
|
|
testLogger.info('💾 保存权限设置');
|
|
await page.click('button:has-text("确定")');
|
|
|
|
await page.waitForSelector('.el-message--success', {
|
|
state: 'visible',
|
|
timeout: 10000
|
|
});
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'verifyPermissionsAssigned',
|
|
action: async () => {
|
|
testLogger.info('✅ 验证权限分配成功');
|
|
|
|
const successMessage = await roleManagementPage.getSuccessMessage();
|
|
if (!successMessage.includes('成功')) {
|
|
throw new Error('权限分配未显示成功消息');
|
|
}
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 角色生命周期工作流
|
|
*/
|
|
export function roleLifecycleWorkflow(context: RoleWorkflowContext): BusinessWorkflow {
|
|
const { testLogger, testDataManager } = context;
|
|
let createdRoleName: string | undefined;
|
|
|
|
return {
|
|
name: 'roleLifecycle',
|
|
description: '角色从创建到删除的完整生命周期',
|
|
|
|
steps: [
|
|
{
|
|
name: 'login',
|
|
action: async () => {
|
|
const loginWorkflow = createRoleWorkflow(context);
|
|
if (loginWorkflow.preconditions) {
|
|
await loginWorkflow.preconditions();
|
|
}
|
|
},
|
|
timeout: 20000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'createRole',
|
|
action: async () => {
|
|
const createWorkflow = createRoleWorkflow(context);
|
|
for (const step of createWorkflow.steps) {
|
|
await step.action();
|
|
}
|
|
createdRoleName = context.createdRole?.name;
|
|
},
|
|
timeout: 60000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'verifyRoleInList',
|
|
action: async () => {
|
|
if (!createdRoleName) {
|
|
throw new Error('角色创建失败');
|
|
}
|
|
await context.roleManagementPage.searchRole(createdRoleName);
|
|
const count = await context.roleManagementPage.getRoleCount();
|
|
if (count === 0) {
|
|
throw new Error('新创建的角色未在列表中');
|
|
}
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'assignPermissions',
|
|
action: async () => {
|
|
const permissionsWorkflow = assignPermissionsWorkflow(context, createdRoleName);
|
|
for (const step of permissionsWorkflow.steps.slice(2)) {
|
|
await step.action();
|
|
}
|
|
},
|
|
timeout: 45000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'editRole',
|
|
action: async () => {
|
|
const editWorkflow = editRoleWorkflow(context, createdRoleName);
|
|
for (const step of editWorkflow.steps.slice(2)) {
|
|
await step.action();
|
|
}
|
|
},
|
|
timeout: 45000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'verifyRoleUpdated',
|
|
action: async () => {
|
|
testLogger.info('✅ 验证角色更新成功');
|
|
const successMessage = await context.roleManagementPage.getSuccessMessage();
|
|
if (!successMessage.includes('成功')) {
|
|
throw new Error('角色更新验证失败');
|
|
}
|
|
},
|
|
timeout: 10000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'deleteRole',
|
|
action: async () => {
|
|
const deleteWorkflow = deleteRoleWorkflow(context, createdRoleName);
|
|
for (const step of deleteWorkflow.steps.slice(2)) {
|
|
await step.action();
|
|
}
|
|
},
|
|
timeout: 30000,
|
|
retryCount: 3
|
|
},
|
|
{
|
|
name: 'verifyRoleDeleted',
|
|
action: async () => {
|
|
testLogger.info('✅ 验证角色删除成功');
|
|
if (!createdRoleName) return;
|
|
|
|
await context.roleManagementPage.searchRole(createdRoleName);
|
|
const count = await context.roleManagementPage.getRoleCount();
|
|
if (count > 0) {
|
|
throw new Error('角色删除后仍存在于列表中');
|
|
}
|
|
},
|
|
timeout: 15000,
|
|
retryCount: 3
|
|
}
|
|
]
|
|
};
|
|
}
|