|
@@ -0,0 +1,532 @@
|
|
|
|
|
+import { TIMEOUTS } from '../../utils/timeouts';
|
|
|
|
|
+import { test, expect } from '../../utils/test-setup';
|
|
|
|
|
+import { UserType } from '@d8d/shared-types';
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 人才用户创建 E2E 测试
|
|
|
|
|
+ *
|
|
|
|
|
+ * 测试后台创建人才用户功能的正确性
|
|
|
|
|
+ * 验证创建基本人才用户、完整信息人才用户、残疾人关联验证、表单验证等功能
|
|
|
|
|
+ *
|
|
|
|
|
+ * @see {@link ../pages/admin/user-management.page.ts} UserManagementPage
|
|
|
|
|
+ * @see {@link ../pages/admin/disability-person.page.ts} DisabilityPersonManagementPage
|
|
|
|
|
+ */
|
|
|
|
|
+test.describe('人才用户创建功能', () => {
|
|
|
|
|
+ // 测试创建的残疾人姓名,用于清理
|
|
|
|
|
+ let testPersonName: string;
|
|
|
|
|
+
|
|
|
|
|
+ test.beforeEach(async ({ adminLoginPage, disabilityPersonPage, userManagementPage }) => {
|
|
|
|
|
+ // 以管理员身份登录后台
|
|
|
|
|
+ await adminLoginPage.goto();
|
|
|
|
|
+ await adminLoginPage.login('admin', 'admin123');
|
|
|
|
|
+ await adminLoginPage.expectLoginSuccess();
|
|
|
|
|
+
|
|
|
|
|
+ // 创建测试残疾人(人才用户必须关联残疾人)
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ testPersonName = `测试残疾人_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ await disabilityPersonPage.goto();
|
|
|
|
|
+ await disabilityPersonPage.openCreateDialog();
|
|
|
|
|
+
|
|
|
|
|
+ // 填写残疾人基本信息(必填字段)
|
|
|
|
|
+ await disabilityPersonPage.fillBasicForm({
|
|
|
|
|
+ name: testPersonName,
|
|
|
|
|
+ gender: '男',
|
|
|
|
|
+ idCard: generateTestIdCard(timestamp),
|
|
|
|
|
+ disabilityId: `证${timestamp}`,
|
|
|
|
|
+ disabilityType: '视力残疾',
|
|
|
|
|
+ disabilityLevel: '一级',
|
|
|
|
|
+ phone: '13800138000',
|
|
|
|
|
+ idAddress: `测试身份证地址_${timestamp}`,
|
|
|
|
|
+ province: '广东省',
|
|
|
|
|
+ city: '广州市',
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 提交表单
|
|
|
|
|
+ await disabilityPersonPage.submitForm();
|
|
|
|
|
+ await disabilityPersonPage.waitForDialogClosed();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证残疾人创建成功
|
|
|
|
|
+ const personCreated = await disabilityPersonPage.waitForPersonExists(testPersonName, { timeout: TIMEOUTS.TABLE_LOAD });
|
|
|
|
|
+ expect(personCreated).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 导航到用户管理页面
|
|
|
|
|
+ await userManagementPage.goto();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.afterEach(async ({ disabilityPersonPage }) => {
|
|
|
|
|
+ // 清理测试数据(残疾人)
|
|
|
|
|
+ await disabilityPersonPage.goto();
|
|
|
|
|
+ await disabilityPersonPage.searchByName(testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ // 等待搜索结果
|
|
|
|
|
+ const exists = await disabilityPersonPage.personExists(testPersonName);
|
|
|
|
|
+ if (exists) {
|
|
|
|
|
+ await disabilityPersonPage.deleteDisabilityPerson(testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ // 等待删除完成
|
|
|
|
|
+ const deleted = await disabilityPersonPage.waitForPersonNotExists(testPersonName, { timeout: TIMEOUTS.TABLE_LOAD });
|
|
|
|
|
+ expect(deleted).toBe(true);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.describe('基本创建流程测试', () => {
|
|
|
|
|
+ test('应该成功创建基本人才用户', async ({ userManagementPage }) => {
|
|
|
|
|
+ // 生成唯一用户名
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `test_talent_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建人才用户(填写必填字段 + 选择残疾人)
|
|
|
|
|
+ const result = await userManagementPage.createUser({
|
|
|
|
|
+ username,
|
|
|
|
|
+ password: 'password123',
|
|
|
|
|
+ nickname: '测试人才用户',
|
|
|
|
|
+ userType: UserType.TALENT,
|
|
|
|
|
+ // personId 由 Page Object 通过残疾人名称自动处理,无需指定
|
|
|
|
|
+ }, undefined, testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证 API 响应成功
|
|
|
|
|
+ expect(result.responses).toBeDefined();
|
|
|
|
|
+ expect(result.responses?.length).toBeGreaterThan(0);
|
|
|
|
|
+ const createResponse = result.responses?.find(r => r.url.includes('/api/v1/users'));
|
|
|
|
|
+ expect(createResponse?.ok).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证创建成功提示(可选,Toast 检测可能不稳定)
|
|
|
|
|
+ if (result.hasSuccess && result.successMessage) {
|
|
|
|
|
+ expect(result.successMessage).toContain('成功');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户出现在列表中
|
|
|
|
|
+ await expect(async () => {
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(true);
|
|
|
|
|
+ }).toPass({ timeout: TIMEOUTS.DIALOG });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户类型徽章显示为人才用户
|
|
|
|
|
+ const userRow = userManagementPage.getUserByUsername(username);
|
|
|
|
|
+ const userTypeBadge = userRow.getByTestId('user-type-badge');
|
|
|
|
|
+ await expect(userTypeBadge).toContainText('人才用户');
|
|
|
|
|
+
|
|
|
|
|
+ // 清理测试数据(用户)
|
|
|
|
|
+ const deleteResult = await userManagementPage.deleteUser(username);
|
|
|
|
|
+ expect(deleteResult).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户已被删除
|
|
|
|
|
+ const existsAfterDelete = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(existsAfterDelete).toBe(false);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test('创建后人才用户应该出现在列表中', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `talent_list_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建人才用户
|
|
|
|
|
+ await userManagementPage.createUser({
|
|
|
|
|
+ username,
|
|
|
|
|
+ password: 'password123',
|
|
|
|
|
+ nickname: '列表测试用户',
|
|
|
|
|
+ userType: UserType.TALENT,
|
|
|
|
|
+ }, undefined, testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户出现在列表中
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 清理
|
|
|
|
|
+ await userManagementPage.deleteUser(username);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.describe('完整表单字段测试', () => {
|
|
|
|
|
+ test('应该成功创建完整信息人才用户', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `talent_full_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建人才用户(填写所有字段)
|
|
|
|
|
+ const result = await userManagementPage.createUser({
|
|
|
|
|
+ username,
|
|
|
|
|
+ password: 'password123',
|
|
|
|
|
+ nickname: '完整信息用户',
|
|
|
|
|
+ email: `full_${timestamp}@example.com`,
|
|
|
|
|
+ phone: '13800138001',
|
|
|
|
|
+ name: '张三',
|
|
|
|
|
+ userType: UserType.TALENT,
|
|
|
|
|
+ // personId 由 Page Object 通过残疾人名称自动处理,无需指定
|
|
|
|
|
+ }, undefined, testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证 API 响应成功
|
|
|
|
|
+ const createResponse = result.responses?.find(r => r.url.includes('/api/v1/users'));
|
|
|
|
|
+ expect(createResponse?.ok).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户出现在列表中
|
|
|
|
|
+ await expect(async () => {
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(true);
|
|
|
|
|
+ }).toPass({ timeout: TIMEOUTS.DIALOG });
|
|
|
|
|
+
|
|
|
|
|
+ // 清理
|
|
|
|
|
+ await userManagementPage.deleteUser(username);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test('应该保存所有填写的字段数据', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `talent_fields_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建人才用户(填写所有字段)
|
|
|
|
|
+ const result = await userManagementPage.createUser({
|
|
|
|
|
+ username,
|
|
|
|
|
+ password: 'password123',
|
|
|
|
|
+ nickname: `字段测试_${timestamp}`,
|
|
|
|
|
+ email: `fields_${timestamp}@test.com`,
|
|
|
|
|
+ phone: '13900139000',
|
|
|
|
|
+ name: '李四',
|
|
|
|
|
+ userType: UserType.TALENT,
|
|
|
|
|
+ // personId 由 Page Object 通过残疾人名称自动处理,无需指定
|
|
|
|
|
+ }, undefined, testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证创建成功(优先检查 API 响应)
|
|
|
|
|
+ const createResponse = result.responses?.find(r => r.url.includes('/api/v1/users'));
|
|
|
|
|
+ expect(createResponse?.ok).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证创建成功提示(可选,Toast 检测可能不稳定)
|
|
|
|
|
+ if (result.hasSuccess && result.successMessage) {
|
|
|
|
|
+ expect(result.successMessage).toContain('成功');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户出现在列表中
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 清理
|
|
|
|
|
+ await userManagementPage.deleteUser(username);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.describe('残疾人关联验证测试', () => {
|
|
|
|
|
+ // TODO: 后端当前未强制要求人才用户必须关联残疾人
|
|
|
|
|
+ // 当前行为:后端允许创建没有 personId 的 TALENT 用户
|
|
|
|
|
+ // 期望行为:后端应返回 400 错误,要求人才用户必须关联残疾人
|
|
|
|
|
+ test.skip('人才用户必须关联残疾人 [后端验证未实现]', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `talent_no_person_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 打开创建对话框
|
|
|
|
|
+ await userManagementPage.openCreateDialog();
|
|
|
|
|
+
|
|
|
|
|
+ // 填写用户名和密码
|
|
|
|
|
+ await userManagementPage.usernameInput.fill(username);
|
|
|
|
|
+ await userManagementPage.passwordInput.fill('password123');
|
|
|
|
|
+
|
|
|
|
|
+ // 选择用户类型为人才用户(但不选择残疾人)
|
|
|
|
|
+ await userManagementPage.page.waitForSelector('[data-testid="用户类型-trigger"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
|
|
|
|
|
+ await userManagementPage.userTypeSelector.click();
|
|
|
|
|
+ await userManagementPage.page.waitForSelector('[role="option"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
|
|
|
|
|
+ await userManagementPage.page.getByRole('option', { name: '人才用户' }).click();
|
|
|
|
|
+
|
|
|
|
|
+ // 尝试提交表单
|
|
|
|
|
+ const submitResult = await userManagementPage.submitForm();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证 API 响应包含错误(后端验证)
|
|
|
|
|
+ const createResponse = submitResult.responses?.find(r => r.url.includes('/api/v1/users'));
|
|
|
|
|
+ // 后端应该返回 400 错误或 Toast 错误消息
|
|
|
|
|
+ expect(createResponse?.ok || submitResult.hasError).toBe(false);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户没有被创建(列表中不存在)
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(false);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.skip('不选择残疾人时应该显示错误提示 [后端验证未实现]', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `talent_error_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 打开创建对话框
|
|
|
|
|
+ await userManagementPage.openCreateDialog();
|
|
|
|
|
+
|
|
|
|
|
+ // 填写必填字段
|
|
|
|
|
+ await userManagementPage.usernameInput.fill(username);
|
|
|
|
|
+ await userManagementPage.passwordInput.fill('password123');
|
|
|
|
|
+ await userManagementPage.nicknameInput.fill('错误测试用户');
|
|
|
|
|
+
|
|
|
|
|
+ // 选择用户类型为人才用户(但不选择残疾人)
|
|
|
|
|
+ await userManagementPage.page.waitForSelector('[data-testid="用户类型-trigger"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
|
|
|
|
|
+ await userManagementPage.userTypeSelector.click();
|
|
|
|
|
+ await userManagementPage.page.waitForSelector('[role="option"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
|
|
|
|
|
+ await userManagementPage.page.getByRole('option', { name: '人才用户' }).click();
|
|
|
|
|
+
|
|
|
|
|
+ // 尝试提交表单
|
|
|
|
|
+ const submitResult = await userManagementPage.submitForm();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证后端返回错误(残疾人必填验证)
|
|
|
|
|
+ const createResponse = submitResult.responses?.find(r => r.url.includes('/api/v1/users'));
|
|
|
|
|
+ expect(createResponse?.ok || submitResult.hasError).toBe(false);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户没有被创建
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(false);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.describe('表单验证测试', () => {
|
|
|
|
|
+ test('用户名为空时应显示验证错误', async ({ userManagementPage }) => {
|
|
|
|
|
+ // 打开创建对话框
|
|
|
|
|
+ await userManagementPage.openCreateDialog();
|
|
|
|
|
+
|
|
|
|
|
+ // 不填写用户名,直接填写密码
|
|
|
|
|
+ await userManagementPage.passwordInput.fill('password123');
|
|
|
|
|
+
|
|
|
|
|
+ // 尝试提交表单
|
|
|
|
|
+ await userManagementPage.submitForm();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证对话框仍然打开(表单验证阻止了提交)
|
|
|
|
|
+ const dialog = userManagementPage.page.locator('[role="dialog"]');
|
|
|
|
|
+ await expect(dialog).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 关闭对话框
|
|
|
|
|
+ await userManagementPage.cancelDialog();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test('密码为空时应显示验证错误', async ({ userManagementPage }) => {
|
|
|
|
|
+ // 打开创建对话框
|
|
|
|
|
+ await userManagementPage.openCreateDialog();
|
|
|
|
|
+
|
|
|
|
|
+ // 填写用户名,但不填写密码
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ await userManagementPage.usernameInput.fill(`user_no_pwd_${timestamp}`);
|
|
|
|
|
+
|
|
|
|
|
+ // 尝试提交表单
|
|
|
|
|
+ await userManagementPage.submitForm();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证对话框仍然打开(表单验证阻止了提交)
|
|
|
|
|
+ const dialog = userManagementPage.page.locator('[role="dialog"]');
|
|
|
|
|
+ await expect(dialog).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 关闭对话框
|
|
|
|
|
+ await userManagementPage.cancelDialog();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test('邮箱格式不正确时应显示验证错误', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `user_bad_email_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 打开创建对话框
|
|
|
|
|
+ await userManagementPage.openCreateDialog();
|
|
|
|
|
+
|
|
|
|
|
+ // 先填写无效格式的邮箱(在填写其他可选字段之前)
|
|
|
|
|
+ await userManagementPage.usernameInput.fill(username);
|
|
|
|
|
+ await userManagementPage.passwordInput.fill('password123');
|
|
|
|
|
+ await userManagementPage.emailInput.fill('invalid-email-format');
|
|
|
|
|
+ // 不填写昵称等其他字段,只测试邮箱格式验证
|
|
|
|
|
+
|
|
|
|
|
+ // 尝试提交表单
|
|
|
|
|
+ await userManagementPage.submitForm();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证对话框仍然打开(表单验证阻止了提交)
|
|
|
|
|
+ const dialog = userManagementPage.page.locator('[role="dialog"]');
|
|
|
|
|
+ await expect(dialog).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 关闭对话框
|
|
|
|
|
+ await userManagementPage.cancelDialog();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.describe('数据唯一性测试', () => {
|
|
|
|
|
+ test('不同测试应该使用不同的用户名', async ({ userManagementPage }) => {
|
|
|
|
|
+ // 生成两个不同的用户名
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username1 = `unique_talent_A_${timestamp}`;
|
|
|
|
|
+ const username2 = `unique_talent_B_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建第一个人才用户
|
|
|
|
|
+ await userManagementPage.createUser({
|
|
|
|
|
+ username: username1,
|
|
|
|
|
+ password: 'password123',
|
|
|
|
|
+ nickname: '唯一性测试A',
|
|
|
|
|
+ userType: UserType.TALENT,
|
|
|
|
|
+ }, undefined, testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ expect(await userManagementPage.userExists(username1)).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 创建第二个人才用户
|
|
|
|
|
+ await userManagementPage.createUser({
|
|
|
|
|
+ username: username2,
|
|
|
|
|
+ password: 'password123',
|
|
|
|
|
+ nickname: '唯一性测试B',
|
|
|
|
|
+ userType: UserType.TALENT,
|
|
|
|
|
+ }, undefined, testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ expect(await userManagementPage.userExists(username2)).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 清理两个用户
|
|
|
|
|
+ await userManagementPage.deleteUser(username1);
|
|
|
|
|
+ await userManagementPage.deleteUser(username2);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证清理成功
|
|
|
|
|
+ expect(await userManagementPage.userExists(username1)).toBe(false);
|
|
|
|
|
+ expect(await userManagementPage.userExists(username2)).toBe(false);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test('使用时间戳确保用户名唯一', async ({ userManagementPage }) => {
|
|
|
|
|
+ // 使用时间戳生成唯一用户名
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `timestamp_user_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建人才用户
|
|
|
|
|
+ await userManagementPage.createUser({
|
|
|
|
|
+ username,
|
|
|
|
|
+ password: 'password123',
|
|
|
|
|
+ nickname: '时间戳测试用户',
|
|
|
|
|
+ userType: UserType.TALENT,
|
|
|
|
|
+ }, undefined, testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户创建成功
|
|
|
|
|
+ expect(await userManagementPage.userExists(username)).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 清理
|
|
|
|
|
+ await userManagementPage.deleteUser(username);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.describe('测试后清理验证', () => {
|
|
|
|
|
+ test('应该能成功删除测试创建的人才用户', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `cleanup_talent_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建人才用户
|
|
|
|
|
+ const result = await userManagementPage.createUser({
|
|
|
|
|
+ username,
|
|
|
|
|
+ password: 'password123',
|
|
|
|
|
+ nickname: '清理测试用户',
|
|
|
|
|
+ email: `cleanup_${timestamp}@test.com`,
|
|
|
|
|
+ phone: '13800003333',
|
|
|
|
|
+ userType: UserType.TALENT,
|
|
|
|
|
+ }, undefined, testPersonName);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户存在
|
|
|
|
|
+ const createResponse = result.responses?.find(r => r.url.includes('/api/v1/users'));
|
|
|
|
|
+ expect(createResponse?.ok).toBe(true);
|
|
|
|
|
+ expect(await userManagementPage.userExists(username)).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 删除用户
|
|
|
|
|
+ const deleteResult = await userManagementPage.deleteUser(username);
|
|
|
|
|
+ expect(deleteResult).toBe(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户已被删除
|
|
|
|
|
+ await expect(async () => {
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(false);
|
|
|
|
|
+ }).toPass({ timeout: TIMEOUTS.DIALOG });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.describe('对话框元素验证', () => {
|
|
|
|
|
+ test('应该显示创建用户对话框的所有字段', async ({ userManagementPage }) => {
|
|
|
|
|
+ // 打开创建对话框
|
|
|
|
|
+ await userManagementPage.openCreateDialog();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证对话框存在
|
|
|
|
|
+ const dialog = userManagementPage.page.locator('[role="dialog"]');
|
|
|
|
|
+ await expect(dialog).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户类型选择器存在
|
|
|
|
|
+ await expect(userManagementPage.userTypeSelector).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证必填字段输入框存在
|
|
|
|
|
+ await expect(userManagementPage.usernameInput).toBeVisible();
|
|
|
|
|
+ await expect(userManagementPage.passwordInput).toBeVisible();
|
|
|
|
|
+ await expect(userManagementPage.nicknameInput).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证可选字段输入框存在
|
|
|
|
|
+ await expect(userManagementPage.emailInput).toBeVisible();
|
|
|
|
|
+ await expect(userManagementPage.phoneInput).toBeVisible();
|
|
|
|
|
+ await expect(userManagementPage.nameInput).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 残疾人选择器是条件渲染的,只有选择了 TALENT 类型才会显示
|
|
|
|
|
+ // 先选择人才用户类型
|
|
|
|
|
+ await userManagementPage.userTypeSelector.click();
|
|
|
|
|
+ await userManagementPage.page.waitForSelector('[role="option"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
|
|
|
|
|
+ await userManagementPage.page.getByRole('option', { name: '人才用户' }).click();
|
|
|
|
|
+
|
|
|
|
|
+ // 现在验证残疾人选择器存在
|
|
|
|
|
+ await expect(userManagementPage.disabledPersonSelector).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证按钮存在
|
|
|
|
|
+ await expect(userManagementPage.createSubmitButton).toBeVisible();
|
|
|
|
|
+ await expect(userManagementPage.cancelButton).toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 关闭对话框
|
|
|
|
|
+ await userManagementPage.cancelDialog();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test.describe('取消和关闭操作测试', () => {
|
|
|
|
|
+ test('应该能取消创建人才用户操作', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `cancel_talent_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 打开创建对话框并填写表单
|
|
|
|
|
+ await userManagementPage.openCreateDialog();
|
|
|
|
|
+ await userManagementPage.usernameInput.fill(username);
|
|
|
|
|
+ await userManagementPage.passwordInput.fill('password123');
|
|
|
|
|
+
|
|
|
|
|
+ // 点击取消按钮
|
|
|
|
|
+ await userManagementPage.cancelDialog();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证对话框关闭
|
|
|
|
|
+ const dialog = userManagementPage.page.locator('[role="dialog"]');
|
|
|
|
|
+ await expect(dialog).not.toBeVisible();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户没有被创建
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(false);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ test('应该能通过关闭对话框取消创建', async ({ userManagementPage }) => {
|
|
|
|
|
+ const timestamp = Date.now();
|
|
|
|
|
+ const username = `close_talent_${timestamp}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 打开创建对话框并填写表单
|
|
|
|
|
+ await userManagementPage.openCreateDialog();
|
|
|
|
|
+ await userManagementPage.usernameInput.fill(username);
|
|
|
|
|
+ await userManagementPage.passwordInput.fill('password123');
|
|
|
|
|
+
|
|
|
|
|
+ // 按 ESC 键关闭对话框
|
|
|
|
|
+ await userManagementPage.page.keyboard.press('Escape');
|
|
|
|
|
+
|
|
|
|
|
+ // 等待对话框关闭
|
|
|
|
|
+ await userManagementPage.waitForDialogClosed();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证用户没有被创建
|
|
|
|
|
+ const exists = await userManagementPage.userExists(username);
|
|
|
|
|
+ expect(exists).toBe(false);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 生成测试用身份证号
|
|
|
|
|
+ * @param timestamp 时间戳
|
|
|
|
|
+ * @returns 18位身份证号
|
|
|
|
|
+ */
|
|
|
|
|
+function generateTestIdCard(timestamp: number): string {
|
|
|
|
|
+ // 生成一个有效的18位身份证号(简化版本)
|
|
|
|
|
+ const prefix = '110101'; // 北京市东城区
|
|
|
|
|
+ const birthDate = new Date(timestamp);
|
|
|
|
|
+ const year = birthDate.getFullYear();
|
|
|
|
|
+ const month = String(birthDate.getMonth() + 1).padStart(2, '0');
|
|
|
|
|
+ const day = String(birthDate.getDate()).padStart(2, '0');
|
|
|
|
|
+ const sequence = String(timestamp % 1000).padStart(3, '0');
|
|
|
|
|
+ const base = prefix + year + month + day + sequence;
|
|
|
|
|
+
|
|
|
|
|
+ // 简单校验码计算(实际身份证校验码算法更复杂)
|
|
|
|
|
+ const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
|
|
|
|
+ const checkChars = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
|
|
|
|
|
+
|
|
|
|
|
+ let sum = 0;
|
|
|
|
|
+ for (let i = 0; i < 17; i++) {
|
|
|
|
|
+ sum += parseInt(base[i]) * weights[i];
|
|
|
|
|
+ }
|
|
|
|
|
+ const checkCode = checkChars[sum % 11];
|
|
|
|
|
+
|
|
|
|
|
+ return base + checkCode;
|
|
|
|
|
+}
|