Implementation of one test

This commit is contained in:
Mark Tolmacs
2025-08-20 17:53:20 +02:00
parent 023895b49b
commit 4c9ad1a22f
4 changed files with 2745 additions and 14770 deletions

View File

@@ -170,6 +170,15 @@ export class Record {
}
private static onMouseMove(event: MouseEvent) {
if (
event.clientX < 0 ||
event.clientX > window.innerWidth ||
event.clientY < 0 ||
event.clientY > window.innerHeight
) {
return;
}
const now = event.timeStamp || performance.now();
const delay = now - Record.timestamp;
Record.timestamp = now;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,77 @@
import { expect, type Page } from "@playwright/test";
import type { PlaybackEvent } from "../../record";
export async function playbackEvents(page: Page, events: PlaybackEvent[]) {
const mask = [
page.getByRole("button", { name: "Share" }),
page.getByTitle("Library").locator("div"),
];
let width = 0;
let height = 0;
page.setDefaultTimeout(100000);
for (const event of events) {
// Handle header event specially: set viewport and localStorage before playback
if (event.type === "header") {
// set viewport to recorded size
await page.setViewportSize({ width: event.width, height: event.height });
width = event.width;
height = event.height;
// apply localStorage snapshot in page context
if (event.localStorage) {
await page.evaluate((ls: Record<string, string>) => {
try {
for (const k in ls) {
if (Object.prototype.hasOwnProperty.call(ls, k)) {
localStorage.setItem(k, ls[k]);
}
}
} catch {}
}, event.localStorage as Record<string, string>);
}
await page.reload();
await page.waitForLoadState("load");
// header has no further action
continue;
}
// wait the recorded delay before dispatching the event
const ms = Math.max(0, Math.round((event as any).delay ?? 0));
if (ms > 0) {
await page.waitForTimeout(ms);
}
switch (event.type) {
case "mouse.move":
// Simulate mouse movement
if (event.x < 0 || event.x > width || event.y < 0 || event.y > height) {
break;
}
await page.mouse.move(event.x, event.y);
break;
case "mouse.down":
// Simulate mouse button down
await page.mouse.down({ button: event.button });
break;
case "mouse.up":
// Simulate mouse button up
await page.mouse.up({ button: event.button });
await expect(page).toHaveScreenshot({ maxDiffPixels: 100, mask });
break;
case "keyboard.down":
// Simulate key down
await page.keyboard.down(event.key);
break;
case "keyboard.up":
// Simulate key up
await page.keyboard.up(event.key);
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask,
});
break;
}
}
}

View File

@@ -12,25 +12,28 @@ import { defineConfig, devices } from "@playwright/test";
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./excalidraw-app/tests",
testDir: "./excalidraw-app/tests/regression",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
retries: process.env.CI ? 2 : 1,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
actionTimeout: 0,
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://localhost:3000',
baseURL: "http://localhost:3000",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
headless: true,
},
timeout: 1200000,
/* Configure projects for major browsers */
projects: [