Stage workspace controls after bootstrap
This commit is contained in:
@@ -91,6 +91,89 @@ test("successful login transitions to play workspace", async ({ page, context })
|
||||
await expect(page.locator("#login-username")).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("workspace stays usable when input controls are DOM-wrapped during mount", async ({ page, context }) => {
|
||||
const username = `wrapped-${Date.now()}`;
|
||||
await registerAndLogin(context.request, username, "Wrapped Inputs");
|
||||
|
||||
const campaign = await postJson(context.request, "/api/campaigns", {
|
||||
name: "Wrapped Inputs",
|
||||
rulesetId: "d6"
|
||||
});
|
||||
const character = await postJson(context.request, "/api/characters", {
|
||||
name: "Wrapper Hero",
|
||||
campaignId: campaign.id
|
||||
});
|
||||
await postJson(context.request, `/api/characters/${character.id}/skills`, {
|
||||
name: "Stealth",
|
||||
diceRollDefinition: "2D+1",
|
||||
wildDice: 1,
|
||||
allowFumble: true
|
||||
});
|
||||
|
||||
await page.addInitScript(() => {
|
||||
const wrappedMarker = "rrWrappedByTest";
|
||||
|
||||
function wrapControl(element) {
|
||||
if (!(element instanceof HTMLElement) || !element.isConnected || element.dataset[wrappedMarker] === "1") {
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = element.parentNode;
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const wrapper = document.createElement("span");
|
||||
wrapper.dataset[wrappedMarker] = "1";
|
||||
element.dataset[wrappedMarker] = "1";
|
||||
parent.insertBefore(wrapper, element);
|
||||
wrapper.appendChild(element);
|
||||
}
|
||||
|
||||
function queueWrap(node) {
|
||||
if (!(node instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.matches("input, select")) {
|
||||
queueMicrotask(() => wrapControl(node));
|
||||
}
|
||||
|
||||
node.querySelectorAll("input, select").forEach((element) => {
|
||||
queueMicrotask(() => wrapControl(element));
|
||||
});
|
||||
}
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
mutation.addedNodes.forEach(queueWrap);
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(document.documentElement, { childList: true, subtree: true });
|
||||
document.querySelectorAll("input, select").forEach((element) => queueWrap(element));
|
||||
});
|
||||
|
||||
const blazorErrors = [];
|
||||
page.on("console", (message) => {
|
||||
if (message.type() !== "error") {
|
||||
return;
|
||||
}
|
||||
|
||||
const text = message.text();
|
||||
if (/error applying batch|unhandled exception on the current circuit/i.test(text)) {
|
||||
blazorErrors.push(text);
|
||||
}
|
||||
});
|
||||
|
||||
await page.goto("/");
|
||||
await expect(page.getByText("Campaign Log")).toBeVisible();
|
||||
await expect(page.locator("#skill-filter-input")).toBeVisible();
|
||||
await expect(page.locator("#custom-roll-expression")).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Roll Stealth" })).toBeVisible();
|
||||
expect(blazorErrors).toEqual([]);
|
||||
});
|
||||
|
||||
test("Rolemaster open-ended roll detail renders specialized dice chips", async ({ page, context }) => {
|
||||
const username = `rm-${Date.now()}`;
|
||||
const displayName = "Rolemaster Smoke";
|
||||
|
||||
Reference in New Issue
Block a user