| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- import { TIMEOUTS } from '../../utils/timeouts';
- import { test, expect } from '../../utils/test-setup';
- import { AdminLoginPage } from '../../pages/admin/login.page';
- import { EnterpriseMiniPage } from '../../pages/mini/enterprise-mini.page';
- /**
- * 跨端数据同步 E2E 测试 - 编辑订单
- *
- * 测试目标:验证后台编辑订单后,企业小程序能否正确显示更新后的订单信息
- *
- * 测试流程:
- * 1. 后台操作:登录 → 导航到订单管理 → 编辑已有订单 → 验证编辑成功
- * 2. 小程序验证:登录 → 导航到订单列表 → 点击订单详情 → 验证订单信息已更新
- *
- * 重要发现(来自 Playwright MCP 探索):
- * - 小程序列表页显示缓存数据(编辑后不自动刷新)
- * - 小程序详情页显示最新数据(API 返回最新数据)
- * - 因此 E2E 测试需要通过详情页验证数据同步
- */
- // 测试常量
- const TEST_COMPANY_NAME = '测试公司_1768346782396'; // 测试公司名称
- const MINI_LOGIN_PHONE = '13800001111'; // 小程序登录手机号
- const MINI_LOGIN_PASSWORD = 'password123'; // 小程序登录密码
- /**
- * 后台登录辅助函数
- */
- async function loginAdmin(page: any, testUsers: any) {
- const adminLoginPage = new AdminLoginPage(page);
- await adminLoginPage.goto();
- await adminLoginPage.page.getByPlaceholder('请输入用户名').fill(testUsers.admin.username);
- await adminLoginPage.page.getByPlaceholder('请输入密码').fill(testUsers.admin.password);
- await adminLoginPage.page.getByRole('button', { name: '登录' }).click();
- await adminLoginPage.page.waitForURL('**/admin/dashboard', { timeout: TIMEOUTS.PAGE_LOAD });
- console.debug('[后台] 登录成功');
- }
- /**
- * 企业小程序登录辅助函数
- */
- async function loginMini(page: any) {
- const miniPage = new EnterpriseMiniPage(page);
- await miniPage.goto();
- await miniPage.login(MINI_LOGIN_PHONE, MINI_LOGIN_PASSWORD);
- await miniPage.expectLoginSuccess();
- console.debug('[小程序] 登录成功');
- }
- test.describe('跨端数据同步测试 - 后台编辑订单到企业小程序', () => {
- test.describe.configure({ mode: 'serial' });
- test('完整的跨端编辑同步测试:后台编辑订单 → 小程序详情验证', async ({ page: adminPage, page: miniPage, testUsers }) => {
- // ==================== 后台编辑订单 ====================
- console.debug('=== 阶段 1: 后台编辑订单 ===');
- // 1. 后台登录
- await loginAdmin(adminPage, testUsers);
- // 2. 导航到订单管理页面
- await adminPage.goto('/admin/orders');
- await adminPage.waitForSelector('table tbody tr', { state: 'visible', timeout: TIMEOUTS.PAGE_LOAD });
- console.debug('[后台] 导航到订单管理页面');
- // 3. 查找属于测试公司的未编辑订单(用于编辑)
- const testCompanyOrders = adminPage.locator('table tbody tr').filter({
- hasText: TEST_COMPANY_NAME
- });
- // 获取订单总数并遍历查找未编辑的订单
- const orderCount = await testCompanyOrders.count();
- let originalOrderName: string | null = null;
- for (let i = 0; i < orderCount; i++) {
- const nameCell = await testCompanyOrders.nth(i).locator('td').first();
- const name = (await nameCell.textContent())?.trim() || '';
- // 跳过已被编辑的订单(名称包含 "已编辑" 或 "_edit")
- if (!name.includes('已编辑') && !name.includes('_edit')) {
- originalOrderName = name;
- break;
- }
- }
- if (!originalOrderName) {
- test.skip();
- console.debug('[测试] 所有测试订单都已被编辑过,跳过此测试');
- return;
- }
- console.debug(`[后台] 找到测试订单: ${originalOrderName}`);
- // 4. 打开编辑对话框
- const orderRow = adminPage.locator('table tbody tr').filter({ hasText: originalOrderName });
- const menuButton = orderRow.getByRole('button', { name: '打开菜单' });
- await menuButton.click();
- console.debug('[后台] 点击订单菜单按钮');
- // 等待菜单出现并点击"编辑"选项
- const editOption = adminPage.getByRole('menuitem', { name: '编辑' });
- await editOption.waitFor({ state: 'visible', timeout: TIMEOUTS.ELEMENT_VISIBLE_SHORT });
- await editOption.click();
- console.debug('[后台] 点击编辑菜单项');
- // 等待编辑对话框出现
- await adminPage.waitForSelector('[role="dialog"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
- console.debug('[后台] 编辑对话框已打开');
- // 5. 修改订单名称(使用较短的后缀以避免 UI 截断)
- const editedOrderName = `${originalOrderName}_编辑`;
- await adminPage.getByRole('textbox', { name: '订单名称' }).fill(editedOrderName);
- console.debug(`[后台] 修改订单名称为: ${editedOrderName}`);
- // 6. 提交编辑表单
- await adminPage.getByTestId('order-update-submit-button').click();
- await adminPage.waitForLoadState('domcontentloaded');
- await adminPage.waitForTimeout(TIMEOUTS.LONG);
- console.debug('[后台] 提交编辑表单');
- // 7. 验证编辑成功的 Toast(确认编辑操作成功)
- const successToast = adminPage.locator('[data-sonner-toast][data-type="success"]');
- const toastCount = await successToast.count();
- expect(toastCount).toBeGreaterThan(0);
- console.debug('[后台] 订单编辑成功(Toast 已显示)');
- // 8. 可选:验证列表中更新(通过搜索,但可能有分页或延迟问题)
- // 由于核心测试目标是小程序数据同步,列表验证跳过
- // Toast 已经确认编辑成功,继续进行小程序验证
- // ==================== 小程序验证编辑后的订单 ====================
- console.debug('=== 阶段 2: 小程序验证编辑后的订单 ===');
- // 1. 小程序登录
- await loginMini(miniPage);
- // 2. 导航到订单列表页面
- await miniPage.getByText('订单', { exact: true }).click();
- await miniPage.waitForLoadState('domcontentloaded');
- console.debug('[小程序] 导航到订单列表页面');
- // 3. 等待订单列表加载
- await miniPage.waitForTimeout(TIMEOUTS.LONG);
- // 4. 查找编辑后的订单(通过原订单名称,因为列表可能有缓存)
- const orderExistsByOriginal = await miniPage.locator('text=' + originalOrderName).count() > 0;
- const orderExistsByEdited = await miniPage.locator('text=' + editedOrderName).count() > 0;
- console.debug(`[小程序] 列表中 - 原名称存在: ${orderExistsByOriginal}, 编辑后名称存在: ${orderExistsByEdited}`);
- // 5. 点击查看详情(详情页会获取最新数据)
- // 查找包含原订单名称的行,然后点击其"查看详情"按钮
- const orderRowInMini = miniPage.getByText(originalOrderName);
- const detailButton = orderRowInMini.locator('..').getByText('查看详情');
- // 记录详情导航开始时间
- const detailStartTime = Date.now();
- await detailButton.click();
- await miniPage.waitForURL(/\/detail/, { timeout: TIMEOUTS.PAGE_LOAD });
- console.debug('[小程序] 打开订单详情');
- // 6. 验证订单详情页显示编辑后的订单名称
- // 详情页会从 API 获取最新数据,所以应该显示编辑后的名称
- const editedOrderNameElement = miniPage.getByText(editedOrderName);
- await expect(editedOrderNameElement).toBeVisible();
- console.debug(`[小程序] 订单详情显示编辑后的名称: ${editedOrderName}`);
- // 7. 记录数据同步完成时间
- const detailEndTime = Date.now();
- const detailSyncTime = detailEndTime - detailStartTime;
- console.debug(`[小程序] 详情页加载并验证完成,耗时: ${detailSyncTime}ms`);
- // 8. 验证数据同步时效性(应 ≤ 10 秒)
- expect(detailSyncTime).toBeLessThanOrEqual(10000);
- console.debug(`[小程序] 数据同步时效性验证通过: ${detailSyncTime}ms ≤ 10000ms`);
- });
- test('后台编辑订单基本信息(名称和日期)', async ({ page: adminPage, testUsers }) => {
- // 这个测试验证编辑订单基本信息的功能
- await loginAdmin(adminPage, testUsers);
- await adminPage.goto('/admin/orders');
- // 查找测试公司的订单
- const testCompanyOrders = adminPage.locator('table tbody tr').filter({
- hasText: TEST_COMPANY_NAME
- });
- // 跳过已被编辑的订单(名称包含 "_编辑")
- const validOrders = testCompanyOrders.filter(async (_, index) => {
- const nameCell = await testCompanyOrders.nth(index).locator('td').first();
- const name = (await nameCell.textContent())?.trim() || '';
- return !name.includes('_编辑') && !name.includes('_edit');
- });
- const firstValidOrder = await validOrders.first();
- const orderName = (await firstValidOrder.locator('td').first().textContent())?.trim();
- if (!orderName || orderName.includes('_编辑')) {
- test.skip();
- console.debug('[测试] 所有测试订单都已被编辑过,跳过此测试');
- return;
- }
- console.debug(`[测试] 编辑订单: ${orderName}`);
- // 打开编辑对话框
- const orderRow = adminPage.locator('table tbody tr').filter({ hasText: orderName });
- await orderRow.getByRole('button', { name: '打开菜单' }).click();
- const editOption = adminPage.getByRole('menuitem', { name: '编辑' });
- await editOption.waitFor({ state: 'visible', timeout: TIMEOUTS.ELEMENT_VISIBLE_SHORT });
- await editOption.click();
- await adminPage.waitForSelector('[role="dialog"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
- // 修改订单名称
- const newOrderName = `${orderName}_info_edit`;
- await adminPage.getByRole('textbox', { name: '订单名称' }).fill(newOrderName);
- // 修改预计开始日期
- const newStartDate = '2026-02-01';
- await adminPage.getByRole('textbox', { name: '预计开始日期' }).fill(newStartDate);
- // 提交编辑
- await adminPage.getByTestId('order-update-submit-button').click();
- await adminPage.waitForLoadState('domcontentloaded');
- await adminPage.waitForTimeout(TIMEOUTS.LONG);
- // 验证成功
- const successToast = adminPage.locator('[data-sonner-toast][data-type="success"]');
- expect(await successToast.count()).toBeGreaterThan(0);
- console.debug('[测试] 订单编辑成功(Toast 已显示)');
- // 验证列表显示更新(使用搜索)
- await adminPage.getByTestId('search-order-name-input').fill(newOrderName);
- await adminPage.getByRole('button', { name: '搜索' }).click();
- await adminPage.waitForTimeout(TIMEOUTS.LONG);
- const updatedOrderExists = adminPage.locator('table tbody tr').filter({ hasText: newOrderName }).count() > 0;
- expect(updatedOrderExists).toBe(true);
- console.debug(`[测试] 编辑订单基本信息成功: ${orderName} -> ${newOrderName}`);
- });
- });
|