Files
workinf_Blender_Wasm/tools/web/check-chromium-keymap-fixture.mjs
mes123456 380cbed4ff
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Checkpoint web parity through Chromium input tasks
2026-08-19 10:39:03 -04:00

47 lines
6.2 KiB
JavaScript

import assert from "node:assert/strict";
import crypto from "node:crypto";
import fs from "node:fs";
import http from "node:http";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const distRoot = path.join(root, "web/dist");
const reportPath = path.join(root, "tests/golden/M14-04E/chromium-keymap-report.json");
const manifestPath = path.join(root, "tests/golden/M14-04E/manifest.json");
const mime = new Map([[".html", "text/html; charset=utf-8"], [".js", "text/javascript; charset=utf-8"], [".css", "text/css; charset=utf-8"], [".json", "application/json"], [".wasm", "application/wasm"]]);
const server = http.createServer((request, response) => { const pathname = decodeURIComponent(new URL(request.url ?? "/", "http://127.0.0.1").pathname); const relative = pathname === "/" ? "index.html" : pathname.replace(/^\//u, ""); const file = path.resolve(distRoot, relative); if (!file.startsWith(`${distRoot}${path.sep}`) || !fs.existsSync(file) || !fs.statSync(file).isFile()) { response.writeHead(404); response.end("not found"); return; } response.statusCode = 200; response.setHeader("Content-Type", mime.get(path.extname(file)) ?? "application/octet-stream"); response.setHeader("Cross-Origin-Opener-Policy", "same-origin"); response.setHeader("Cross-Origin-Embedder-Policy", "require-corp"); response.setHeader("Cross-Origin-Resource-Policy", "same-origin"); response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; connect-src 'self'; font-src 'self'; img-src 'self'; media-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'"); fs.createReadStream(file).pipe(response); });
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
const address = server.address();
assert.ok(address && typeof address === "object");
let browser;
try {
const playwright = await import(pathToFileURL(path.join(root, "web/node_modules/playwright/index.mjs")).href);
browser = await playwright.chromium.launch({ headless: true, args: ["--no-sandbox", "--use-gl=swiftshader", "--enable-unsafe-swiftshader"] });
const page = await (await browser.newContext({ viewport: { width: 960, height: 640 } })).newPage();
await page.goto(`http://127.0.0.1:${address.port}/`, { waitUntil: "load" });
await page.waitForFunction(() => document.querySelector("[data-testid=engine-status]")?.textContent === "Engine: ready, open a .blend file", undefined, { timeout: 20_000 });
const fixtures = [
{ key: "a", code: "KeyA", location: 0, shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
{ key: "ä", code: "Quote", location: 0, shiftKey: true, ctrlKey: false, altKey: true, metaKey: false },
{ key: "Dead", code: "Quote", location: 0, shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
{ key: "z", code: "KeyZ", location: 0, shiftKey: true, ctrlKey: true, altKey: false, metaKey: false },
];
const observations = [];
for (const fixture of fixtures) {
await page.evaluate((value) => { const target = document.querySelector("canvas.viewport-canvas") ?? document.body; target.dispatchEvent(new KeyboardEvent("keydown", { bubbles: true, key: value.key, code: value.code, location: value.location, shiftKey: value.shiftKey, ctrlKey: value.ctrlKey, altKey: value.altKey, metaKey: value.metaKey })); }, fixture);
await page.waitForTimeout(20);
observations.push(await page.locator(".blender-app").evaluate((element) => ({ key: element.getAttribute("data-key-key"), code: element.getAttribute("data-key-code"), location: Number(element.getAttribute("data-key-location")), modifiers: element.getAttribute("data-key-modifiers"), dead: element.getAttribute("data-key-dead") === "true" })));
}
assert.deepEqual(observations, [{ key: "a", code: "KeyA", location: 0, modifiers: "", dead: false }, { key: "ä", code: "Quote", location: 0, modifiers: "SA", dead: false }, { key: "Dead", code: "Quote", location: 0, modifiers: "A", dead: true }, { key: "z", code: "KeyZ", location: 0, modifiers: "SC", dead: false }]);
const report = { schemaVersion: 1, task: "M14-04E", operation: "CHROMIUM_KEYMAP_LAYOUT_MODIFIER_FIXTURE", runtime: "PLAYWRIGHT_CHROMIUM", fixtureNames: ["US", "NON_US", "DEAD_KEY", "MODIFIER"], observations, execution: "DISABLED", nextTask: "M14-04F" };
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
const relative = (file) => path.relative(root, file).replaceAll(path.sep, "/");
if (process.env.UPDATE_M14_04E_REPORT === "1") { fs.mkdirSync(path.dirname(reportPath), { recursive: true }); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); const artifactPaths = { parentManifest: path.join(root, "tests/golden/M14-04D/manifest.json"), checker: path.join(root, "tools/web/check-chromium-keymap-fixture.mjs"), protocol: path.join(root, "web/protocol/keyboard-contract.ts"), unit: path.join(root, "web/tests/unit/keyboard-contract.test.mjs"), app: path.join(root, "web/app/src/app/App.tsx"), package: path.join(root, "web/package.json"), report: reportPath }; const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: relative(file), sha256: sha256(file) }])); fs.writeFileSync(manifestPath, `${JSON.stringify({ schemaVersion: 1, task: "M14-04E", parentTask: "M14-04D", enablingTask: false, parityStateChange: false, runtime: "PLAYWRIGHT_CHROMIUM", operation: "CHROMIUM_KEYMAP_LAYOUT_MODIFIER_FIXTURE", artifacts, nextTask: "M14-04F" }, null, 2)}\n`); }
assert.deepEqual(JSON.parse(fs.readFileSync(reportPath, "utf8")), report);
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
assert.deepEqual({ task: manifest.task, parentTask: manifest.parentTask, nextTask: manifest.nextTask }, { task: "M14-04E", parentTask: "M14-04D", nextTask: "M14-04F" });
for (const artifact of Object.values(manifest.artifacts)) assert.equal(sha256(path.join(root, artifact.path)), artifact.sha256, artifact.path);
process.stdout.write(`chromium-keymap-ok fixtures=US,NON_US,DEAD_KEY,MODIFIER observations=${observations.length} execution=DISABLED next=${manifest.nextTask}\n`);
} finally { await browser?.close(); await new Promise((resolve) => server.close(resolve)); }