Files
everything-is-suitable/everything-is-suitable-test/e2e/business-flows/auth-e2e.spec.ts
T
张翔 08ea5fbe98 feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
2026-03-28 14:37:29 +08:00

219 lines
6.8 KiB
TypeScript

/**
* 认证模块端到端测试
* 测试登录、登出、Token刷新等认证流程
*/
import { test, expect, Page } from '@playwright/test';
import { TestLogger } from '../core/test-logger.js';
import { TestDataManager } from '../core/test-data-manager.js';
import { WorkflowExecutor } from '../core/workflow-executor.js';
import { TestReporter } from '../core/test-reporter.js';
import { LoginPage } from '../pages/login-page.js';
import { DashboardPage } from '../pages/dashboard-page.js';
test.describe('认证模块端到端测试', () => {
let page: Page;
let testLogger: TestLogger;
let testDataManager: TestDataManager;
let workflowExecutor: WorkflowExecutor;
let testReporter: TestReporter;
let loginPage: LoginPage;
let dashboardPage: DashboardPage;
test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
testLogger = new TestLogger();
testDataManager = TestDataManager.getInstance(testLogger);
workflowExecutor = new WorkflowExecutor(testLogger);
testReporter = new TestReporter(testLogger);
loginPage = new LoginPage(page, testLogger);
dashboardPage = new DashboardPage(page);
testReporter.startSuite('认证模块端到端测试');
});
test.afterAll(async () => {
testReporter.endSuite();
testReporter.generateHTMLReport('认证模块E2E测试报告');
await page.close();
});
test.afterEach(async ({}, testInfo) => {
if (testInfo.status === 'failed') {
const screenshotPath = `test-results/screenshots/${testInfo.title}-${Date.now()}.png`;
await page.screenshot({ path: screenshotPath, fullPage: true });
testReporter.addScreenshot(screenshotPath);
}
});
test('应该成功登录并跳转到仪表盘', async () => {
testReporter.startTest('成功登录');
try {
await loginPage.navigate();
await loginPage.login('admin', 'admin123');
await loginPage.waitForLoginSuccess();
// 验证仪表盘页面
const pageTitle = await dashboardPage.getPageTitle();
expect(pageTitle).toContain('仪表盘');
testReporter.endTest('passed');
} catch (error) {
testReporter.endTest('failed', error as Error);
throw error;
}
});
test('应该拒绝错误的用户名', async () => {
testReporter.startTest('拒绝错误用户名');
try {
await loginPage.navigate();
await loginPage.login('wronguser', 'admin123');
const errorText = await loginPage.waitForError();
expect(errorText).toContain('错误');
testReporter.endTest('passed');
} catch (error) {
testReporter.endTest('failed', error as Error);
throw error;
}
});
test('应该拒绝错误的密码', async () => {
testReporter.startTest('拒绝错误密码');
try {
await loginPage.navigate();
await loginPage.login('admin', 'wrongpassword');
const errorText = await loginPage.waitForError();
expect(errorText).toContain('错误');
testReporter.endTest('passed');
} catch (error) {
testReporter.endTest('failed', error as Error);
throw error;
}
});
test('应该验证用户名不能为空', async () => {
testReporter.startTest('验证用户名不能为空');
try {
await loginPage.navigate();
await loginPage.clickLoginButton();
const hasError = await page.locator('[role="alert"]').isVisible();
expect(hasError).toBe(true);
testReporter.endTest('passed');
} catch (error) {
testReporter.endTest('failed', error as Error);
throw error;
}
});
test('应该成功登出', async () => {
testReporter.startTest('成功登出');
try {
// 先登录
await loginPage.navigate();
await loginPage.login('admin', 'admin123');
await loginPage.waitForLoginSuccess();
// 执行登出
await page.click('.ant-dropdown-link');
await page.waitForTimeout(500);
await page.click('.ant-dropdown-menu-item:has-text("退出")');
await page.waitForURL(/.*login/, { timeout: 10000 });
// 验证返回登录页面
const isLoginFormVisible = await loginPage.verifyLoginFormExists();
expect(isLoginFormVisible).toBe(true);
testReporter.endTest('passed');
} catch (error) {
testReporter.endTest('failed', error as Error);
throw error;
}
});
test('应该保持登录状态在页面刷新后', async () => {
testReporter.startTest('刷新后保持登录');
try {
// 先登录
await loginPage.navigate();
await loginPage.login('admin', 'admin123');
await loginPage.waitForLoginSuccess();
// 刷新页面
await page.reload();
await dashboardPage.waitForLoad();
// 验证仍在仪表盘
const isDashboardVisible = await dashboardPage.isDashboardVisible();
expect(isDashboardVisible).toBe(true);
testReporter.endTest('passed');
} catch (error) {
testReporter.endTest('failed', error as Error);
throw error;
}
});
test('应该完成完整的登录-操作-登出流程', async () => {
testReporter.startTest('完整认证流程');
try {
// 步骤1: 登录
testLogger.startStep('用户登录');
await loginPage.navigate();
await loginPage.login('admin', 'admin123');
await loginPage.waitForLoginSuccess();
testLogger.endStep('用户登录', 'passed');
// 步骤2: 访问仪表盘
testLogger.startStep('访问仪表盘');
await dashboardPage.waitForLoad();
const isDashboardVisible = await dashboardPage.isDashboardVisible();
expect(isDashboardVisible).toBe(true);
testLogger.endStep('访问仪表盘', 'passed');
// 步骤3: 访问用户管理
testLogger.startStep('访问用户管理');
await page.click('.ant-menu-item:has-text("用户管理")');
await page.waitForURL(/.*users/, { timeout: 10000 });
testLogger.endStep('访问用户管理', 'passed');
// 步骤4: 返回仪表盘
testLogger.startStep('返回仪表盘');
await page.click('.ant-menu-item:has-text("仪表盘")');
await page.waitForURL(/.*dashboard/, { timeout: 10000 });
testLogger.endStep('返回仪表盘', 'passed');
// 步骤5: 登出
testLogger.startStep('用户登出');
await page.click('.ant-dropdown-link');
await page.waitForTimeout(500);
await page.click('.ant-dropdown-menu-item:has-text("退出")');
await page.waitForURL(/.*login/, { timeout: 10000 });
testLogger.endStep('用户登出', 'passed');
// 验证返回登录页面
const isLoginFormVisible = await loginPage.verifyLoginFormExists();
expect(isLoginFormVisible).toBe(true);
testReporter.endTest('passed');
} catch (error) {
testReporter.endTest('failed', error as Error);
throw error;
}
});
});