156 lines
5.5 KiB
JavaScript
156 lines
5.5 KiB
JavaScript
import { chromium } from "@playwright/test";
|
||
import assert from "node:assert/strict";
|
||
import { mkdir, writeFile } from "node:fs/promises";
|
||
|
||
const browser = await chromium.launch({
|
||
executablePath:
|
||
process.env.BROWSER_PATH ||
|
||
"C:/Users/ikun/AppData/Local/ms-playwright/chromium_headless_shell-1234/chrome-headless-shell-win64/chrome-headless-shell.exe",
|
||
headless: true,
|
||
args: [
|
||
"--enable-webgl",
|
||
"--use-angle=swiftshader",
|
||
"--enable-unsafe-swiftshader",
|
||
],
|
||
});
|
||
const context = await browser.newContext({
|
||
viewport: { width: 1440, height: 900 },
|
||
deviceScaleFactor: 1,
|
||
});
|
||
const page = await context.newPage();
|
||
const errors = [];
|
||
const reports = [];
|
||
page.on("pageerror", (error) => errors.push(error.message));
|
||
await mkdir("artifacts", { recursive: true });
|
||
try {
|
||
const session = await context.newCDPSession(page);
|
||
await session.send("Network.enable");
|
||
await session.send("Network.setCacheDisabled", { cacheDisabled: true });
|
||
await page.goto("http://127.0.0.1:4178", { waitUntil: "networkidle" });
|
||
await page.waitForFunction(() =>
|
||
document.querySelector("#total-distance").textContent.includes("158.6"),
|
||
);
|
||
await page.locator("#play").click();
|
||
await page.locator("#timeline").fill("650");
|
||
await page.waitForTimeout(300);
|
||
await page.screenshot({
|
||
path: "artifacts/desktop-original.png",
|
||
fullPage: true,
|
||
});
|
||
const sampleCanvas = () => {
|
||
const canvas = document.querySelector("#scene canvas");
|
||
const copy = document.createElement("canvas");
|
||
copy.width = 80;
|
||
copy.height = 60;
|
||
const context = copy.getContext("2d");
|
||
context.drawImage(canvas, 0, 0, 80, 60);
|
||
const pixels = context.getImageData(0, 0, 80, 60).data;
|
||
const colors = new Set();
|
||
let sum = 0;
|
||
for (let i = 0; i < pixels.length; i += 4) {
|
||
colors.add(`${pixels[i]},${pixels[i + 1]},${pixels[i + 2]}`);
|
||
sum += pixels[i] + pixels[i + 1] + pixels[i + 2];
|
||
}
|
||
return {
|
||
colors: colors.size,
|
||
sum,
|
||
width: canvas.width,
|
||
height: canvas.height,
|
||
};
|
||
};
|
||
const originalCanvas = await page.evaluate(sampleCanvas);
|
||
assert.ok(originalCanvas.colors > 40, "三维画面不是空白");
|
||
const pausedValue = await page.locator("#timeline").inputValue();
|
||
await page.waitForTimeout(500);
|
||
assert.equal(await page.locator("#timeline").inputValue(), pausedValue);
|
||
await page.locator("#play").click();
|
||
await page.waitForTimeout(250);
|
||
assert.notEqual(await page.locator("#timeline").inputValue(), pausedValue);
|
||
await page.locator("#play").click();
|
||
await page.locator("#demo-mode").click();
|
||
await page.locator("#layer").fill("65");
|
||
await page.waitForTimeout(300);
|
||
assert.equal(await page.locator("#layer-value").textContent(), "65 / 100 层");
|
||
await page.screenshot({ path: "artifacts/desktop-demo.png", fullPage: true });
|
||
const demoCanvas = await page.evaluate(sampleCanvas);
|
||
assert.ok(demoCanvas.colors > 40);
|
||
assert.notEqual(demoCanvas.sum, originalCanvas.sum);
|
||
await page.locator("#view-top").click();
|
||
await page.waitForTimeout(300);
|
||
assert.notEqual((await page.evaluate(sampleCanvas)).sum, demoCanvas.sum);
|
||
await page.locator("#view-perspective").click();
|
||
await page.locator("#nozzle").uncheck();
|
||
await page.waitForTimeout(200);
|
||
assert.notEqual((await page.evaluate(sampleCanvas)).sum, demoCanvas.sum);
|
||
await page.locator("#nozzle").check();
|
||
await page.locator('[data-tech="nozzle"]').click();
|
||
assert.equal(
|
||
await page.locator("#tech-dialog").evaluate((element) => element.open),
|
||
true,
|
||
);
|
||
await page.locator("#dialog-action").click();
|
||
assert.equal(
|
||
await page.locator("#tech-dialog").evaluate((element) => element.open),
|
||
false,
|
||
);
|
||
for (const [width, height] of [
|
||
[1920, 1080],
|
||
[1440, 900],
|
||
[1366, 768],
|
||
[1280, 720],
|
||
[390, 844],
|
||
]) {
|
||
await page.setViewportSize({ width, height });
|
||
await page.waitForTimeout(300);
|
||
const layout = await page.evaluate(() => {
|
||
const footer = document.querySelector("footer").getBoundingClientRect();
|
||
return {
|
||
scrollWidth: document.documentElement.scrollWidth,
|
||
scrollHeight: document.documentElement.scrollHeight,
|
||
width: innerWidth,
|
||
height: innerHeight,
|
||
footerBottom: footer.bottom,
|
||
scene: document
|
||
.querySelector("#scene")
|
||
.getBoundingClientRect()
|
||
.toJSON(),
|
||
fileBottom: document
|
||
.querySelector(".file-section")
|
||
.getBoundingClientRect().bottom,
|
||
playerBottom: document.querySelector(".player").getBoundingClientRect()
|
||
.bottom,
|
||
technologyTop: document
|
||
.querySelector(".technology-strip")
|
||
.getBoundingClientRect().top,
|
||
};
|
||
});
|
||
reports.push(layout);
|
||
assert.ok(layout.scrollWidth <= width + 1, `宽度溢出 ${width}`);
|
||
if (width >= 1100)
|
||
assert.ok(
|
||
layout.scrollHeight <= height + 1,
|
||
`桌面单屏溢出 ${width}×${height}: ${layout.scrollHeight}`,
|
||
);
|
||
if (width >= 1100)
|
||
assert.ok(
|
||
Math.max(layout.fileBottom, layout.playerBottom) < layout.technologyTop,
|
||
`内容重叠 ${width}×${height}`,
|
||
);
|
||
await page.screenshot({
|
||
path: `artifacts/viewport-${width}.png`,
|
||
fullPage: true,
|
||
});
|
||
assert.ok((await page.evaluate(sampleCanvas)).colors > 40);
|
||
}
|
||
assert.deepEqual(errors, []);
|
||
console.log(
|
||
JSON.stringify({ originalCanvas, demoCanvas, reports, errors }, null, 2),
|
||
);
|
||
await writeFile(
|
||
"artifacts/browser-report.json",
|
||
JSON.stringify({ originalCanvas, demoCanvas, reports, errors }, null, 2),
|
||
);
|
||
} finally {
|
||
await browser.close();
|
||
}
|