|
|
@@ -1,4 +1,7 @@
|
|
|
import { test, expect } from '../../utils/test-setup';
|
|
|
+import { AdminLoginPage } from '../../pages/admin/login.page';
|
|
|
+import { UserManagementPage } from '../../pages/admin/user-management.page';
|
|
|
+import { UserType } from '@d8d/shared-types';
|
|
|
|
|
|
/**
|
|
|
* 企业小程序登录 E2E 测试
|
|
|
@@ -6,14 +9,70 @@ import { test, expect } from '../../utils/test-setup';
|
|
|
* 测试企业用户通过小程序登录的功能,验证:
|
|
|
* - 登录失败场景
|
|
|
* - 表单验证
|
|
|
- *
|
|
|
- * 注意:
|
|
|
- * - 登录成功、Token 持久性、退出登录等测试需要预创建测试用户
|
|
|
- * - 这些测试需要在独立测试套件中运行,使用专用的 page context
|
|
|
- * - 当前测试文件专注于不需要用户创建的测试场景
|
|
|
+ * - 登录成功场景(使用独立 context 创建测试用户)
|
|
|
+ * - Token 持久性
|
|
|
+ * - 退出登录
|
|
|
*
|
|
|
* @see {@link ../pages/mini/enterprise-mini.page.ts} EnterpriseMiniPage
|
|
|
*/
|
|
|
+
|
|
|
+/**
|
|
|
+ * 创建测试用户的辅助函数
|
|
|
+ *
|
|
|
+ * 在独立的 browser context 中通过管理后台创建测试用户,
|
|
|
+ * 避免与小程序登录测试共享 page 实例导致的冲突。
|
|
|
+ *
|
|
|
+ * @param browser Playwright browser 实例
|
|
|
+ * @param userData 用户数据
|
|
|
+ * @returns 创建的用户名和密码
|
|
|
+ */
|
|
|
+async function createTestUser(browser: typeof test['fixtures']['browser'], userData: {
|
|
|
+ username: string;
|
|
|
+ password: string;
|
|
|
+ nickname?: string;
|
|
|
+ phone?: string;
|
|
|
+ email?: string;
|
|
|
+ userType?: UserType;
|
|
|
+ companyName?: string;
|
|
|
+}): Promise<{ username: string; password: string }> {
|
|
|
+ // 创建独立的 browser context
|
|
|
+ const adminContext = await browser.newContext();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 在独立 context 中创建 page
|
|
|
+ const adminPage = await adminContext.newPage();
|
|
|
+
|
|
|
+ // 创建管理后台 Page Objects
|
|
|
+ const adminLoginPage = new AdminLoginPage(adminPage);
|
|
|
+ const userManagementPage = new UserManagementPage(adminPage);
|
|
|
+
|
|
|
+ // 登录管理后台
|
|
|
+ await adminLoginPage.goto();
|
|
|
+ await adminLoginPage.login('admin', 'admin123');
|
|
|
+
|
|
|
+ // 导航到用户管理页面
|
|
|
+ await userManagementPage.goto();
|
|
|
+
|
|
|
+ // 创建测试用户(使用 EMPLOYER 类型,企业用户)
|
|
|
+ const result = await userManagementPage.createUser({
|
|
|
+ username: userData.username,
|
|
|
+ password: userData.password,
|
|
|
+ nickname: userData.nickname || '测试企业用户',
|
|
|
+ phone: userData.phone,
|
|
|
+ email: userData.email,
|
|
|
+ userType: userData.userType || UserType.EMPLOYER,
|
|
|
+ }, userData.companyName || '默认公司');
|
|
|
+
|
|
|
+ // 验证创建成功
|
|
|
+ expect(result.success).toBe(true);
|
|
|
+
|
|
|
+ return { username: userData.username, password: userData.password };
|
|
|
+ } finally {
|
|
|
+ // 清理:关闭独立 context
|
|
|
+ await adminContext.close();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
test.describe('企业小程序登录功能', () => {
|
|
|
test.describe('表单验证测试 (AC3)', () => {
|
|
|
test('手机号为空时应该显示错误提示', async ({ enterpriseMiniPage }) => {
|
|
|
@@ -108,48 +167,252 @@ test.describe('企业小程序登录功能', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- test.describe.skip('基本登录成功测试 (AC1) - 需要预创建测试用户', () => {
|
|
|
- // 这些测试需要预创建的测试用户
|
|
|
- // 应该在独立的测试套件中运行,使用专用的 page context
|
|
|
- test('应该成功登录企业小程序', async ({ enterpriseMiniPage: _enterpriseMiniPage }) => {
|
|
|
- // TODO: 需要预创建测试用户
|
|
|
- // 1. 在独立测试套件中创建测试用户
|
|
|
+ test.describe.serial('基本登录成功测试 (AC1)', () => {
|
|
|
+ test('应该成功登录企业小程序', async ({ enterpriseMiniPage, browser }) => {
|
|
|
+ // 1. 创建测试用户(使用独立 context)
|
|
|
+ const testUsername = `mini_test_${Date.now()}`;
|
|
|
+ const testPassword = 'Test123!@#';
|
|
|
+ const testPhone = `138${Date.now().toString().slice(-8)}`;
|
|
|
+
|
|
|
+ await createTestUser(browser, {
|
|
|
+ username: testUsername,
|
|
|
+ password: testPassword,
|
|
|
+ phone: testPhone,
|
|
|
+ nickname: '小程序测试用户',
|
|
|
+ userType: UserType.EMPLOYER,
|
|
|
+ });
|
|
|
+
|
|
|
// 2. 使用该用户登录小程序
|
|
|
- // 3. 验证登录成功
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+ await enterpriseMiniPage.login(testPhone, testPassword);
|
|
|
+
|
|
|
+ // 3. 验证登录成功(URL 跳转到 dashboard 或显示用户信息)
|
|
|
+ await enterpriseMiniPage.expectLoginSuccess();
|
|
|
});
|
|
|
|
|
|
- test('登录成功后应该显示用户信息', async ({ enterpriseMiniPage: _enterpriseMiniPage }) => {
|
|
|
- // TODO: 需要预创建测试用户
|
|
|
+ test('登录成功后应该显示用户信息', async ({ enterpriseMiniPage, browser }) => {
|
|
|
+ // 1. 创建测试用户
|
|
|
+ const testUsername = `mini_info_${Date.now()}`;
|
|
|
+ const testPassword = 'Test123!@#';
|
|
|
+ const testPhone = `139${Date.now().toString().slice(-8)}`;
|
|
|
+
|
|
|
+ await createTestUser(browser, {
|
|
|
+ username: testUsername,
|
|
|
+ password: testPassword,
|
|
|
+ phone: testPhone,
|
|
|
+ nickname: '小程序信息测试',
|
|
|
+ userType: UserType.EMPLOYER,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 2. 登录小程序
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+ await enterpriseMiniPage.login(testPhone, testPassword);
|
|
|
+
|
|
|
+ // 3. 验证登录成功
|
|
|
+ await enterpriseMiniPage.expectLoginSuccess();
|
|
|
+
|
|
|
+ // 4. 验证用户信息显示(检查 userInfo 元素或 dashboard 可见)
|
|
|
+ const currentUrl = enterpriseMiniPage.page.url();
|
|
|
+ expect(currentUrl).toMatch(/dashboard|pages/);
|
|
|
});
|
|
|
|
|
|
- test('登录成功后 token 应该正确存储', async ({ enterpriseMiniPage: _enterpriseMiniPage }) => {
|
|
|
- // TODO: 需要预创建测试用户
|
|
|
+ test('登录成功后 token 应该正确存储', async ({ enterpriseMiniPage, browser }) => {
|
|
|
+ // 1. 创建测试用户
|
|
|
+ const testUsername = `mini_token_${Date.now()}`;
|
|
|
+ const testPassword = 'Test123!@#';
|
|
|
+ const testPhone = `137${Date.now().toString().slice(-8)}`;
|
|
|
+
|
|
|
+ await createTestUser(browser, {
|
|
|
+ username: testUsername,
|
|
|
+ password: testPassword,
|
|
|
+ phone: testPhone,
|
|
|
+ nickname: '小程序 Token 测试',
|
|
|
+ userType: UserType.EMPLOYER,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 2. 登录小程序
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+ await enterpriseMiniPage.login(testPhone, testPassword);
|
|
|
+
|
|
|
+ // 3. 验证登录成功
|
|
|
+ await enterpriseMiniPage.expectLoginSuccess();
|
|
|
+
|
|
|
+ // 4. 验证 token 被正确存储
|
|
|
+ const token = await enterpriseMiniPage.getToken();
|
|
|
+ expect(token).not.toBeNull();
|
|
|
+ expect(token?.length).toBeGreaterThan(0);
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- test.describe.skip('Token 持久性测试 (AC4) - 需要预创建测试用户', () => {
|
|
|
- // 这些测试需要预创建的测试用户
|
|
|
- test('页面刷新后 token 仍然有效', async ({ enterpriseMiniPage: _enterpriseMiniPage }) => {
|
|
|
- // TODO: 需要预创建测试用户
|
|
|
+ test.describe.serial('Token 持久性测试 (AC4)', () => {
|
|
|
+ test('页面刷新后 token 仍然有效', async ({ enterpriseMiniPage, browser }) => {
|
|
|
+ // 1. 创建测试用户
|
|
|
+ const testUsername = `mini_refresh_${Date.now()}`;
|
|
|
+ const testPassword = 'Test123!@#';
|
|
|
+ const testPhone = `136${Date.now().toString().slice(-8)}`;
|
|
|
+
|
|
|
+ await createTestUser(browser, {
|
|
|
+ username: testUsername,
|
|
|
+ password: testPassword,
|
|
|
+ phone: testPhone,
|
|
|
+ nickname: '小程序刷新测试',
|
|
|
+ userType: UserType.EMPLOYER,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 2. 登录小程序
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+ await enterpriseMiniPage.login(testPhone, testPassword);
|
|
|
+ await enterpriseMiniPage.expectLoginSuccess();
|
|
|
+
|
|
|
+ // 3. 获取登录后的 token
|
|
|
+ const tokenBeforeRefresh = await enterpriseMiniPage.getToken();
|
|
|
+ expect(tokenBeforeRefresh).not.toBeNull();
|
|
|
+
|
|
|
+ // 4. 刷新页面
|
|
|
+ await enterpriseMiniPage.page.reload();
|
|
|
+
|
|
|
+ // 5. 等待页面加载完成
|
|
|
+ await enterpriseMiniPage.page.waitForLoadState('domcontentloaded');
|
|
|
+
|
|
|
+ // 6. 验证 token 仍然存在
|
|
|
+ const tokenAfterRefresh = await enterpriseMiniPage.getToken();
|
|
|
+ expect(tokenAfterRefresh).toBe(tokenBeforeRefresh);
|
|
|
});
|
|
|
|
|
|
- test('使用已存储 token 可以继续访问', async ({ enterpriseMiniPage: _enterpriseMiniPage }) => {
|
|
|
- // TODO: 需要预创建测试用户
|
|
|
+ test('使用已存储 token 可以继续访问', async ({ enterpriseMiniPage, browser }) => {
|
|
|
+ // 1. 创建测试用户
|
|
|
+ const testUsername = `mini_persist_${Date.now()}`;
|
|
|
+ const testPassword = 'Test123!@#';
|
|
|
+ const testPhone = `135${Date.now().toString().slice(-8)}`;
|
|
|
+
|
|
|
+ await createTestUser(browser, {
|
|
|
+ username: testUsername,
|
|
|
+ password: testPassword,
|
|
|
+ phone: testPhone,
|
|
|
+ nickname: '小程序持久化测试',
|
|
|
+ userType: UserType.EMPLOYER,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 2. 登录小程序
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+ await enterpriseMiniPage.login(testPhone, testPassword);
|
|
|
+ await enterpriseMiniPage.expectLoginSuccess();
|
|
|
+
|
|
|
+ // 3. 获取 token
|
|
|
+ const token = await enterpriseMiniPage.getToken();
|
|
|
+ expect(token).not.toBeNull();
|
|
|
+
|
|
|
+ // 4. 重新导航到登录页面(模拟关闭后重新打开)
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+
|
|
|
+ // 5. 验证由于 token 存在,页面自动跳转到 dashboard
|
|
|
+ await enterpriseMiniPage.page.waitForURL(
|
|
|
+ url => url.pathname.includes('/dashboard') || url.pathname.includes('/pages'),
|
|
|
+ { timeout: 10000 }
|
|
|
+ ).catch(() => {
|
|
|
+ // 如果没有自动跳转,检查当前 URL
|
|
|
+ const currentUrl = enterpriseMiniPage.page.url();
|
|
|
+ expect(currentUrl).toMatch(/dashboard|pages/);
|
|
|
+ });
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- test.describe.skip('退出登录测试 (AC5) - 需要预创建测试用户', () => {
|
|
|
- // 这些测试需要预创建的测试用户
|
|
|
- test('应该成功退出登录', async ({ enterpriseMiniPage: _enterpriseMiniPage }) => {
|
|
|
- // TODO: 需要预创建测试用户
|
|
|
+ test.describe.serial('退出登录测试 (AC5)', () => {
|
|
|
+ test('应该成功退出登录', async ({ enterpriseMiniPage, browser }) => {
|
|
|
+ // 1. 创建测试用户
|
|
|
+ const testUsername = `mini_logout_${Date.now()}`;
|
|
|
+ const testPassword = 'Test123!@#';
|
|
|
+ const testPhone = `134${Date.now().toString().slice(-8)}`;
|
|
|
+
|
|
|
+ await createTestUser(browser, {
|
|
|
+ username: testUsername,
|
|
|
+ password: testPassword,
|
|
|
+ phone: testPhone,
|
|
|
+ nickname: '小程序退出测试',
|
|
|
+ userType: UserType.EMPLOYER,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 2. 登录小程序
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+ await enterpriseMiniPage.login(testPhone, testPassword);
|
|
|
+ await enterpriseMiniPage.expectLoginSuccess();
|
|
|
+
|
|
|
+ // 3. 退出登录
|
|
|
+ await enterpriseMiniPage.logout();
|
|
|
+
|
|
|
+ // 4. 验证返回到登录页面
|
|
|
+ await enterpriseMiniPage.expectLoggedOut();
|
|
|
+
|
|
|
+ // 5. 验证 URL 返回到登录页面
|
|
|
+ const currentUrl = enterpriseMiniPage.page.url();
|
|
|
+ expect(currentUrl).toContain('/mini');
|
|
|
});
|
|
|
|
|
|
- test('退出后 token 应该被清除', async ({ enterpriseMiniPage: _enterpriseMiniPage }) => {
|
|
|
- // TODO: 需要预创建测试用户
|
|
|
+ test('退出后 token 应该被清除', async ({ enterpriseMiniPage, browser }) => {
|
|
|
+ // 1. 创建测试用户
|
|
|
+ const testUsername = `mini_token_clear_${Date.now()}`;
|
|
|
+ const testPassword = 'Test123!@#';
|
|
|
+ const testPhone = `133${Date.now().toString().slice(-8)}`;
|
|
|
+
|
|
|
+ await createTestUser(browser, {
|
|
|
+ username: testUsername,
|
|
|
+ password: testPassword,
|
|
|
+ phone: testPhone,
|
|
|
+ nickname: '小程序 Token 清除测试',
|
|
|
+ userType: UserType.EMPLOYER,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 2. 登录小程序
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+ await enterpriseMiniPage.login(testPhone, testPassword);
|
|
|
+ await enterpriseMiniPage.expectLoginSuccess();
|
|
|
+
|
|
|
+ // 3. 验证 token 存在
|
|
|
+ const tokenBeforeLogout = await enterpriseMiniPage.getToken();
|
|
|
+ expect(tokenBeforeLogout).not.toBeNull();
|
|
|
+
|
|
|
+ // 4. 退出登录
|
|
|
+ await enterpriseMiniPage.logout();
|
|
|
+ await enterpriseMiniPage.expectLoggedOut();
|
|
|
+
|
|
|
+ // 5. 验证 token 已被清除
|
|
|
+ const tokenAfterLogout = await enterpriseMiniPage.getToken();
|
|
|
+ expect(tokenAfterLogout).toBeNull();
|
|
|
});
|
|
|
|
|
|
- test('退出后无法访问需要认证的页面', async ({ enterpriseMiniPage: _enterpriseMiniPage }) => {
|
|
|
- // TODO: 需要预创建测试用户
|
|
|
+ test('退出后无法访问需要认证的页面', async ({ enterpriseMiniPage, browser }) => {
|
|
|
+ // 1. 创建测试用户
|
|
|
+ const testUsername = `mini_auth_${Date.now()}`;
|
|
|
+ const testPassword = 'Test123!@#';
|
|
|
+ const testPhone = `132${Date.now().toString().slice(-8)}`;
|
|
|
+
|
|
|
+ await createTestUser(browser, {
|
|
|
+ username: testUsername,
|
|
|
+ password: testPassword,
|
|
|
+ phone: testPhone,
|
|
|
+ nickname: '小程序认证测试',
|
|
|
+ userType: UserType.EMPLOYER,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 2. 登录小程序
|
|
|
+ await enterpriseMiniPage.goto();
|
|
|
+ await enterpriseMiniPage.login(testPhone, testPassword);
|
|
|
+ await enterpriseMiniPage.expectLoginSuccess();
|
|
|
+
|
|
|
+ // 3. 退出登录
|
|
|
+ await enterpriseMiniPage.logout();
|
|
|
+ await enterpriseMiniPage.expectLoggedOut();
|
|
|
+
|
|
|
+ // 4. 尝试直接访问需要认证的页面(dashboard)
|
|
|
+ await enterpriseMiniPage.page.goto('/mini/dashboard');
|
|
|
+
|
|
|
+ // 5. 验证被重定向回登录页面
|
|
|
+ await enterpriseMiniPage.page.waitForLoadState('domcontentloaded');
|
|
|
+ const currentUrl = enterpriseMiniPage.page.url();
|
|
|
+ expect(currentUrl).toContain('/mini');
|
|
|
+
|
|
|
+ // 6. 验证登录页面可见
|
|
|
+ await expect(enterpriseMiniPage.loginPage).toBeVisible();
|
|
|
});
|
|
|
});
|
|
|
});
|