106 lines
5.9 KiB
JavaScript
106 lines
5.9 KiB
JavaScript
import fs from "node:fs";
|
||
import path from "node:path";
|
||
import assert from "node:assert/strict";
|
||
import { createRequire } from "node:module";
|
||
|
||
const require = createRequire(new URL("../frontend/package.json", import.meta.url));
|
||
const { chromium } = require("playwright");
|
||
const baseUrl = process.env.PROTOTYPE_URL || "http://127.0.0.1:4178";
|
||
const output = path.resolve(process.env.PLAYER_AUDIT_DIR || ".artifacts/player-round-1");
|
||
const cases = [
|
||
{ name: "mobile-390", width: 390, height: 844 },
|
||
{ name: "desktop-1440", width: 1440, height: 900 }
|
||
];
|
||
|
||
fs.mkdirSync(output, { recursive: true });
|
||
const browser = await chromium.launch({ headless: true });
|
||
const report = [];
|
||
|
||
for (const profile of cases) {
|
||
const context = await browser.newContext({ viewport: profile, locale: "zh-CN" });
|
||
const page = await context.newPage();
|
||
const errors = [];
|
||
page.on("pageerror", error => errors.push(`pageerror: ${error.message}`));
|
||
page.on("console", message => message.type() === "error" && errors.push(`console: ${message.text()}`));
|
||
|
||
await page.goto(`${baseUrl}/#/player/v1`, { waitUntil: "networkidle" });
|
||
const geometry = await page.evaluate(() => {
|
||
const stage = document.querySelector(".player-stage-v2").getBoundingClientRect();
|
||
const back = document.querySelector('.player-topbar button[aria-label="返回"]').getBoundingClientRect();
|
||
const fullscreen = document.querySelector('.player-controls-row button[aria-label="全屏"]').getBoundingClientRect();
|
||
const visibleControls = [...document.querySelectorAll(".player-stage-v2 button")].filter(button => {
|
||
const box = button.getBoundingClientRect();
|
||
const style = getComputedStyle(button);
|
||
return style.display !== "none" && style.visibility !== "hidden" && box.width > 0 && box.height > 0;
|
||
});
|
||
return {
|
||
viewportWidth: innerWidth,
|
||
documentWidth: document.documentElement.scrollWidth,
|
||
stage: { x: stage.x, width: stage.width, height: stage.height, right: stage.right },
|
||
ratio: stage.width / stage.height,
|
||
backVisible: back.left >= 0 && back.right <= innerWidth,
|
||
fullscreenVisible: fullscreen.left >= 0 && fullscreen.right <= innerWidth,
|
||
tapHighlight: getComputedStyle(document.querySelector(".main-play")).webkitTapHighlightColor,
|
||
controlsBelow44: visibleControls.filter(button => {
|
||
const box = button.getBoundingClientRect();
|
||
return box.width < 44 || box.height < 44;
|
||
}).length
|
||
};
|
||
});
|
||
|
||
assert.equal(geometry.documentWidth, geometry.viewportWidth, `${profile.name} 存在横向溢出`);
|
||
assert.ok(Math.abs(geometry.ratio - 16 / 9) < 0.02, `${profile.name} 播放舞台不是 16:9`);
|
||
assert.equal(geometry.backVisible, true, `${profile.name} 返回按钮被裁切`);
|
||
assert.equal(geometry.fullscreenVisible, true, `${profile.name} 全屏按钮被裁切`);
|
||
if (profile.width <= 720) assert.equal(geometry.controlsBelow44, 0, `${profile.name} 存在小于 44px 的播放器按钮`);
|
||
if (profile.width <= 720) assert.ok(geometry.tapHighlight === "rgba(0, 0, 0, 0)" || geometry.tapHighlight === "transparent", `${profile.name} 仍存在系统蓝色点击高亮`);
|
||
assert.equal(await page.locator(".rate-control").textContent(), "1×");
|
||
await page.screenshot({ path: path.join(output, `${profile.name}-player.png`), fullPage: true });
|
||
|
||
await page.locator(".player-tap-surface").click({ position: { x: 10, y: 100 } });
|
||
await page.locator(".player-stage-v2.controls-hidden").waitFor({ state: "visible" });
|
||
await page.waitForTimeout(150);
|
||
await page.getByRole("button", { name: "显示播放控件" }).click({ position: { x: 10, y: 100 } });
|
||
await page.locator(".player-stage-v2.controls-visible").waitFor({ state: "visible" });
|
||
|
||
const beforeSkip = Number(await page.locator('.timeline input[type="range"]').inputValue());
|
||
await page.getByRole("button", { name: "快进 10 秒" }).click();
|
||
const afterSkip = Number(await page.locator('.timeline input[type="range"]').inputValue());
|
||
assert.ok(afterSkip > beforeSkip, `${profile.name} 快进没有更新进度`);
|
||
|
||
await page.locator(".rate-control").click();
|
||
assert.equal(await page.locator(".rate-control").textContent(), "1.25×");
|
||
await page.getByRole("button", { name: "时间点", exact: true }).click();
|
||
await page.locator('.player-drawer[aria-label="视频时间点"]').waitFor({ state: "visible" });
|
||
await page.waitForTimeout(250);
|
||
await page.screenshot({ path: path.join(output, `${profile.name}-markers.png`), fullPage: true });
|
||
await page.keyboard.press("Escape");
|
||
await page.locator(".player-drawer").waitFor({ state: "detached" });
|
||
|
||
await page.getByRole("button", { name: "合集目录" }).click();
|
||
await page.locator('.player-drawer[aria-label="合集目录"]').waitFor({ state: "visible" });
|
||
await page.locator(".player-panel-scrim").click({ position: { x: 4, y: 4 } });
|
||
await page.locator(".player-drawer").waitFor({ state: "detached" });
|
||
|
||
await page.locator(".player-title-row").getByRole("button", { name: "喜欢" }).click();
|
||
assert.equal(await page.locator(".player-title-row").getByRole("button", { name: "喜欢" }).getAttribute("aria-pressed"), "true");
|
||
|
||
if (profile.width <= 720) {
|
||
await page.locator(".main-play").click();
|
||
await page.waitForTimeout(3750);
|
||
await page.locator(".player-stage-v2.controls-hidden").waitFor({ state: "visible" });
|
||
await page.locator(".player-tap-surface").click({ position: { x: 10, y: 100 } });
|
||
await page.locator(".main-play").click();
|
||
await page.waitForTimeout(3750);
|
||
assert.equal(await page.locator(".player-stage-v2").getAttribute("class").then(value => value.includes("controls-visible")), true, "暂停后控件不应自动隐藏");
|
||
}
|
||
|
||
report.push({ ...profile, geometry, errors: [...new Set(errors)] });
|
||
await context.close();
|
||
}
|
||
|
||
await browser.close();
|
||
fs.writeFileSync(path.join(output, "report.json"), JSON.stringify(report, null, 2));
|
||
console.log(JSON.stringify(report, null, 2));
|
||
assert.equal(report.flatMap(item => item.errors).length, 0, "播放器运行时出现控制台错误");
|