更新说明文档
大石头 authored at 2022-04-16 15:30:05
2.76 KiB
YuQue
import { test, expect } from '@playwright/test';
import { collectErrors, expectNoErrors } from './helpers';

/** 布局/全局走查:头部导航树/页尾/标题合理性/下拉/移动端断点 */
const isMobile = (w: number) => w <= 900;

test.describe('全局布局', () => {
  test.beforeEach(async () => { await new Promise((r) => setTimeout(r, 300)); });

  test('头部导航存在且渲染真实链接', async ({ page }) => {
    await page.goto('/');
    await expect(page.locator('.site-header')).toBeVisible();
    // 桌面导航含可点链接(去往分类或外部),排除 js:void(0) 触发层
    const realLinks = await page.locator('.main-nav a[href^="/"]').count();
    expect(realLinks, '头部导航无任何站内链接').toBeGreaterThan(0);
    expectNoErrors(collectErrors(page));
  });

  test('页尾结构:多列 + 版权/备案', async ({ page }) => {
    await page.goto('/');
    await expect(page.locator('.site-footer')).toBeVisible();
    const body = await page.locator('.site-footer').innerText();
    expect(body.length, '页尾内容为空').toBeGreaterThan(10);
    // 备案链接(若有)应指向 beian.miit.gov.cn
    const icp = page.locator('.site-footer a[href*="beian.miit.gov.cn"]');
    if ((await icp.count()) > 0) {
      await expect(icp.first()).toHaveText(/[0-9A-Z-]+号|ICP/i);
    }
  });

  test('标题合理性:非空且非默认占位', async ({ page }) => {
    for (const p of ['/', '/core', '/core/nav', '/search-%E5%BA%8F%E5%88%97%E5%8C%96']) {
      await page.goto(p);
      await page.waitForTimeout(1200); // 页面间留间隔,避免连续访问触发生产限流
      const title = await page.title();
      expect(title.trim().length, `${p} title 为空`).toBeGreaterThan(0);
      expect(title, `${p} title 异常`).not.toContain('Object reference');
    }
  });

  test('移动端:导航下拉可点击展开(若存在下拉项)', async ({ page }) => {
    if (!isMobile(page.viewportSize()!.width)) return;
    await page.goto('/');
    const toggle = page.locator('.nav-toggle');
    await toggle.click();
    const dd = page.locator('.nav-dropdown').first();
    if ((await page.locator('.nav-dropdown').count()) === 0) return;
    await expect(dd).toBeVisible();
    // 点击下拉触发层展开子菜单
    await dd.locator(':scope > a').click();
    await expect(dd).toHaveClass(/open/);
    const sub = dd.locator('.dd-menu a').first();
    if ((await sub.count()) > 0) await expect(sub).toBeVisible();
  });

  test('移动端:toc 在窄屏不遮挡正文(若详情有 toc)', async ({ page }) => {
    if (!isMobile(page.viewportSize()!.width)) return;
    await page.goto('/core/nav');
    const toc = page.locator('.toc');
    if ((await toc.count()) === 0) return;
    await expect(toc).toBeHidden();
  });
});