103 lines
4.2 KiB
TypeScript
103 lines
4.2 KiB
TypeScript
import { expect, test, type Page } from "@playwright/test";
|
|
|
|
async function setEditor(page: Page, testId: string, value: string) {
|
|
await page.getByTestId(testId).locator(".cm-content").fill(value);
|
|
}
|
|
|
|
async function openMinimizer(page: Page) {
|
|
await page.getByRole("button", { name: "Minimize", exact: true }).click();
|
|
const dialog = page.getByRole("dialog", {
|
|
name: "Minimize a reproducer",
|
|
});
|
|
await expect(dialog).toBeVisible();
|
|
await expect(dialog).toBeInViewport();
|
|
return dialog;
|
|
}
|
|
|
|
test("real workers minimize exact failures and expose bounded cancellation", async ({
|
|
page,
|
|
}) => {
|
|
const pageErrors: string[] = [];
|
|
page.on("pageerror", (error) => pageErrors.push(error.message));
|
|
await page.goto("./");
|
|
await page.getByLabel("Live").uncheck();
|
|
|
|
// A deterministic failing should-not-match assertion, verified by the
|
|
// browser's actual ECMAScript worker.
|
|
await setEditor(page, "editor-regular-expression-pattern", "X");
|
|
await setEditor(page, "editor-test-text", "abXcd");
|
|
await expect(
|
|
page.getByRole("button", { name: "Run", exact: true }),
|
|
).toBeEnabled({ timeout: 15_000 });
|
|
let dialog = await openMinimizer(page);
|
|
await dialog.getByRole("button", { name: "Verify & minimize" }).click();
|
|
await expect(
|
|
dialog.getByRole("heading", {
|
|
name: "Locally minimal under the documented transforms",
|
|
}),
|
|
).toBeVisible({ timeout: 30_000 });
|
|
await expect(
|
|
dialog.getByLabel("Minimizer evaluation progress"),
|
|
).toBeVisible();
|
|
await expect(dialog.getByText("Baseline verification")).toBeVisible();
|
|
await expect(dialog.getByText("Final accepted candidate")).toBeVisible();
|
|
await expect(dialog).toContainText("Native ECMAScript RegExp");
|
|
await expect(dialog).toContainText("expected-no-match:present");
|
|
await expect(dialog.getByLabel("Minimized subject")).toHaveValue("X");
|
|
await dialog.getByRole("button", { name: "Use minimized subject" }).click();
|
|
await expect(dialog).not.toBeVisible();
|
|
await expect(
|
|
page.getByTestId("editor-test-text").locator(".cm-content"),
|
|
).toHaveText("X");
|
|
|
|
// With mandatory PCRE2 UCP, \w matches é; ECMAScript \w does not. Padding
|
|
// is removed while preserving the exact match-count mismatch category.
|
|
await setEditor(page, "editor-regular-expression-pattern", "\\w+");
|
|
await setEditor(page, "editor-test-text", "!!é??");
|
|
await expect(
|
|
page.getByRole("button", { name: "Run", exact: true }),
|
|
).toBeEnabled({ timeout: 15_000 });
|
|
dialog = await openMinimizer(page);
|
|
await dialog
|
|
.getByLabel("Minimization failure kind")
|
|
.selectOption("comparison-mismatch");
|
|
await dialog.getByRole("button", { name: "Verify & minimize" }).click();
|
|
await expect(
|
|
dialog.getByRole("heading", {
|
|
name: "Locally minimal under the documented transforms",
|
|
}),
|
|
).toBeVisible({ timeout: 30_000 });
|
|
await expect(dialog.getByLabel("Minimized subject")).toHaveValue("é");
|
|
await expect(dialog).toContainText(
|
|
"comparison:semantic-mismatch · match-count",
|
|
);
|
|
await expect(dialog).toContainText("Native ECMAScript RegExp");
|
|
await expect(dialog).toContainText("PCRE2 WebAssembly");
|
|
await expect(dialog).toContainText("10.47 2025-10-21");
|
|
await dialog.getByRole("button", { name: "Use minimized subject" }).click();
|
|
await expect(
|
|
page.getByTestId("editor-test-text").locator(".cm-content"),
|
|
).toHaveText("é");
|
|
|
|
// Cancellation stays immediately available even for a deliberately
|
|
// pathological timeout target; it terminates the active worker set.
|
|
await setEditor(page, "editor-regular-expression-pattern", "(a+)+$");
|
|
await setEditor(page, "editor-test-text", `${"a".repeat(40_000)}!`);
|
|
dialog = await openMinimizer(page);
|
|
await dialog
|
|
.getByLabel("Minimization failure kind")
|
|
.selectOption("engine-timeout");
|
|
await dialog.getByLabel("Each candidate ms").fill("10000");
|
|
await dialog.getByRole("button", { name: "Verify & minimize" }).click();
|
|
const cancel = dialog.getByRole("button", { name: "Cancel" });
|
|
await expect(cancel).toBeVisible();
|
|
await cancel.click();
|
|
await expect(dialog).toContainText(
|
|
"Cancelled; active syntax and engine workers were terminated.",
|
|
);
|
|
await expect(
|
|
dialog.getByRole("button", { name: "Verify & minimize" }),
|
|
).toBeEnabled();
|
|
expect(pageErrors).toEqual([]);
|
|
});
|