| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- #!/usr/bin/env node
- /**
- * 缩放跨端提示 + 管理员用户管理 端到端验证(2026-11-10)
- *
- * 验证点:
- * ① 桌面端把窗口拖窄到 768 以下 → 弹「切换到手机端」提示(不静默跳转)
- * ② 连续改宽度只弹一次(防抖)
- * ③ 管理员账号能看到「成员管理」入口与页面
- */
- import { chromium } from 'playwright';
- import { mkdir } from 'node:fs/promises';
- import { dirname, resolve } from 'node:path';
- import { fileURLToPath } from 'node:url';
- const here = dirname(fileURLToPath(import.meta.url));
- const outDir = resolve(here, '..', 'test-results', 'resize-org');
- const BASE = process.env.BASE_URL || 'http://127.0.0.1:4300';
- await mkdir(outDir, { recursive: true });
- const browser = await chromium.launch({ channel: 'chrome' });
- const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
- const page = await ctx.newPage();
- const errors = [];
- page.on('pageerror', (e) => errors.push(String(e)));
- const results = [];
- // ---------- ① 缩放提示 ----------
- await page.goto(`${BASE}/desktop/chat`, { waitUntil: 'domcontentloaded' });
- await page.waitForTimeout(8000);
- const hintBefore = await page.locator('.narrow-desktop').count();
- results.push(['桌面宽屏:不提示', hintBefore === 0, `hint=${hintBefore}`]);
- // 连续改宽度(模拟拖拽)→ 防抖后只应出现一个提示
- for (const w of [1100, 1000, 900, 850, 820, 790, 760, 700, 640, 600]) {
- await page.setViewportSize({ width: w, height: 900 });
- await page.waitForTimeout(40);
- }
- await page.waitForTimeout(800);
- const hintAfter = await page.locator('.narrow-desktop').count();
- await page.screenshot({ path: `${outDir}/1-narrow-hint.png` });
- results.push(['拖窄到 768 以下 → 弹提示', hintAfter === 1, `hint=${hintAfter}`]);
- const jumped = page.url().includes('/mobile');
- results.push(['提示时**不**静默跳端', !jumped, page.url()]);
- // 点「我会切」→ 真的跳移动端
- const goBtn = page.locator('.narrow-btn', { hasText: '切换到手机端' });
- if (await goBtn.count()) {
- await goBtn.first().click();
- await page.waitForTimeout(2500);
- results.push(['点切换 → 进入移动端', page.url().includes('/mobile'), page.url()]);
- } else {
- results.push(['点切换 → 进入移动端', false, '按钮不存在']);
- }
- // ---------- ② 管理员用户管理 ----------
- await page.setViewportSize({ width: 1440, height: 900 });
- await page.goto(`${BASE}/desktop/admin/users`, { waitUntil: 'domcontentloaded' });
- await page.waitForTimeout(6000);
- await page.screenshot({ path: `${outDir}/2-admin-users.png` });
- const url = page.url();
- const reached = url.includes('/admin/users');
- const blocked = url.includes('/desktop/chat') && !reached;
- results.push(['管理员可进入成员管理', reached, url]);
- if (blocked) results.push(['非管理员被挡回首页', true, url]);
- const hasTable = await page.locator('.table, .rows, ui-empty, .empty').count();
- results.push(['页面有内容/三态(不是白屏)', hasTable > 0, `nodes=${hasTable}`]);
- // 导航入口:一级菜单只显示 4 项,成员管理在「更多」里
- await page.goto(`${BASE}/desktop/chat`, { waitUntil: 'domcontentloaded' });
- await page.waitForTimeout(5000);
- let navAdmin = await page.locator('.route', { hasText: '成员管理' }).count();
- if (navAdmin === 0) {
- const more = page.locator('.route-more');
- if (await more.count()) {
- await more.click();
- await page.waitForTimeout(600);
- navAdmin = await page.locator('.more-item', { hasText: '成员管理' }).count();
- }
- }
- results.push(['侧边导航有「成员管理」入口', navAdmin > 0, `matches=${navAdmin}`]);
- // ---------- 汇总 ----------
- let pass = true;
- console.log('\n=== 结果 ===');
- for (const [name, ok, detail] of results) {
- if (!ok) pass = false;
- console.log(`${ok ? '✓' : '✗'} ${name} (${detail})`);
- }
- if (errors.length) {
- pass = false;
- console.log('页面错误:', errors.slice(0, 3).join(' | '));
- }
- console.log(`\n${pass ? '✓ 全部通过' : '✗ 存在失败项'}`);
- await browser.close();
- process.exit(pass ? 0 : 1);
|