verify-switch-both-ways.mjs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/usr/bin/env node
  2. /**
  3. * 端切换双向验证(2026-11-10)
  4. *
  5. * 复现用户实测的完整流程:
  6. * ① 桌面端宽屏 → 缩窄 → 提示切移动端 ✅
  7. * ② 点「切换」→ 进入移动端
  8. * ③ **把窗口放大回桌面尺寸 → 必须提示切回桌面端**(用户反馈这里失效)
  9. * ④ 点「切换」→ 回到桌面端
  10. */
  11. import { chromium } from 'playwright';
  12. import { mkdir } from 'node:fs/promises';
  13. import { dirname, resolve } from 'node:path';
  14. import { fileURLToPath } from 'node:url';
  15. const here = dirname(fileURLToPath(import.meta.url));
  16. const outDir = resolve(here, '..', 'test-results', 'switch-both-ways');
  17. const BASE = process.env.BASE_URL || 'http://127.0.0.1:4300';
  18. await mkdir(outDir, { recursive: true });
  19. const browser = await chromium.launch({ channel: 'chrome' });
  20. const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
  21. const errors = [];
  22. page.on('pageerror', (e) => errors.push(String(e)));
  23. const results = [];
  24. await page.goto(`${BASE}/desktop/chat`, { waitUntil: 'domcontentloaded' });
  25. await page.waitForTimeout(8000);
  26. // ① 缩窄 → 桌面端提示
  27. await page.setViewportSize({ width: 600, height: 900 });
  28. await page.waitForTimeout(900);
  29. const hint1 = await page.locator('.narrow-desktop').count();
  30. results.push(['① 桌面缩窄 → 提示切移动端', hint1 === 1, `hint=${hint1}`]);
  31. // ② 点切换 → 进入移动端
  32. const goMobile = page.locator('.narrow-btn', { hasText: '切换到手机端' });
  33. if (await goMobile.count()) {
  34. await goMobile.first().click();
  35. await page.waitForTimeout(2500);
  36. }
  37. const onMobile = page.url().includes('/mobile');
  38. results.push(['② 点切换 → 进入移动端', onMobile, page.url()]);
  39. // ③ 🔴 放大回桌面尺寸 → 移动端应提示切回桌面
  40. await page.setViewportSize({ width: 1440, height: 900 });
  41. await page.waitForTimeout(1200);
  42. const hint2 = await page.locator('.wide-mobile').count();
  43. await page.screenshot({ path: `${outDir}/1-mobile-wide-hint.png` });
  44. results.push(['③ 🔴 放大 → 提示切回桌面端', hint2 === 1, `hint=${hint2}`]);
  45. // ④ 点切换 → 回到桌面端
  46. const goDesktop = page.locator('.wide-btn', { hasText: '切换到桌面端' });
  47. if (await goDesktop.count()) {
  48. await goDesktop.first().click();
  49. await page.waitForTimeout(2500);
  50. }
  51. const backDesktop = page.url().includes('/desktop');
  52. await page.screenshot({ path: `${outDir}/2-back-desktop.png` });
  53. results.push(['④ 点切换 → 回到桌面端', backDesktop, page.url()]);
  54. // ⑤ 回到桌面后不应再提示
  55. await page.waitForTimeout(1000);
  56. const hint3 = await page.locator('.narrow-desktop').count();
  57. results.push(['⑤ 已切回桌面 → 不再提示', hint3 === 0, `hint=${hint3}`]);
  58. let pass = true;
  59. console.log('\n=== 结果 ===');
  60. for (const [name, ok, detail] of results) {
  61. if (!ok) pass = false;
  62. console.log(`${ok ? '✓' : '✗'} ${name} (${detail})`);
  63. }
  64. if (errors.length) {
  65. pass = false;
  66. console.log('页面错误:', errors.slice(0, 2).join(' | '));
  67. }
  68. console.log(`\n${pass ? '✓ 全部通过' : '✗ 存在失败项'}`);
  69. await browser.close();
  70. process.exit(pass ? 0 : 1);