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

/**
 * HTTP 层全站审计(node 客户端不受生产 Bot/UA 降级影响,稳定返回新版)
 * 逐页检查结构完整性,输出审计指标
 */
const PAGES: Array<[String, String]> = [
  ['首页', '/'],
  ['分类core', '/core'],
  ['分类xcode', '/xcode'],
  ['分类cube', '/cube'],
  ['分类blood', '/blood'],
  ['分类iot', '/iot'],
  ['分类tech', '/tech'],
  ['分类events', '/events'],
  ['core分页2', '/core-2'],
  ['详情nav', '/core/nav'],
  ['详情talk', '/events/night_talks_004'],
  ['产品newlife', '/blood/newlife'],
  ['产品stardust', '/blood/stardust'],
  ['搜索结果', '/search-%E5%BA%8F%E5%88%97%E5%8C%96'],
  ['搜索空态', '/search-%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%9A%84%E8%AF%8D%E6%9D%A1zz'],
  ['分类内搜索', '/core-%E5%BA%8F%E5%88%97%E5%8C%96'],
];

test.describe('生产全站 HTML 审计', () => {
  for (const [name, path] of PAGES) {
    test(`审计 ${name}`, async () => {
      const ctx = await request.newContext({ extraHTTPHeaders: { 'cache-control': 'no-cache' } });
      const resp = await ctx.get(`https://newlifex.com${path}`);
      const status = resp.status();
      const ct = resp.headers()['content-type'] || '';
      const body = ct.includes('html') ? await resp.text() : '';
      const has = (re: RegExp) => re.test(body);
      const count = (re: RegExp) => (body.match(re) || []).length;
      const title = (body.match(/<title>([^<]*)<\/title>/) || [])[1]?.trim() || '';
      const isNew = has(/f-grid/) && has(/学无先后达者为师/);
      const isLimited = has(/访问太频繁/);
      const out: String[] = [
        `status=${status}`,
        `NEW=${isNew}`,
        isLimited ? 'LIMITED' : '',
        `title=${title.slice(0, 40)}`,
      ];
      if (isNew) {
        // 新版才做结构指标
        out.push(`articleCard=${count(/class="[^"]*article-card/g)}`);
        out.push(`badgeTop=${count(/badge-top/g)}`);
        out.push(`pagination=${has(/class="[^"]*pagination/)}`);
        out.push(`mark=${count(/<mark>/g)}`);
        out.push(`toc=${has(/class="[^"]*toc/)}`);
        out.push(`projectCard=${count(/class="[^"]*project-card/g)}`);
        out.push(`bookCard=${count(/class="[^"]*book-card/g)}`);
        out.push(`latestItem=${count(/class="[^"]*latest-item/g)}`);
        out.push(`hero=${has(/class="[^"]*hero/)}`);
        out.push(`searchEmpty=${has(/search-empty/)}`);
        out.push(`crumb=${has(/class="[^"]*crumb/)}`);
      }
      // eslint-disable-next-line no-console
      console.log(`>>> ${name} ${path}\n    ${out.join(' | ')}`);
      await ctx.dispose();
      await new Promise((r) => setTimeout(r, 900));
    });
  }
});