mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Add minimal reproducers for known bugs
- Added reproducer for mobile sidebar margin mismatch (tests/visual/overlay-layers.spec.ts). - Added reproducer for Moderation UI "Show anyway" button visibility (tests/visual/moderation.spec.ts). - Added reproducer for NIP-07 login unit test ReferenceError (tests/nostr-login-permissions.test.mjs). - Added examples/reproducers/playwright.config.ts to support running these tests. - Updated examples/reproducers/README.md with instructions. Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
b48320fc9a
commit
1b7575eaab
5 files changed
+561
-16
No files matched your search
@@ -0,0 +1,240 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
__testToast?: {
|
||||
show(message: string, options?: Record<string, unknown>): unknown;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
test.describe("overlay layering tokens", () => {
|
||||
async function dismissDisclaimerModal(page: Page) {
|
||||
const modal = page.locator("#disclaimerModal");
|
||||
if ((await modal.count()) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
await page.evaluate(() => {
|
||||
try {
|
||||
window.localStorage?.setItem("hasSeenDisclaimer", "true");
|
||||
} catch (error) {
|
||||
console.warn("Failed to persist disclaimer state", error);
|
||||
}
|
||||
document
|
||||
.querySelectorAll<HTMLElement>("#disclaimerModal")
|
||||
.forEach((node) => {
|
||||
node.classList.add("hidden");
|
||||
node.setAttribute("data-open", "false");
|
||||
});
|
||||
document.documentElement?.classList.remove("modal-open");
|
||||
document.body?.classList.remove("modal-open");
|
||||
});
|
||||
|
||||
await page.waitForFunction(() =>
|
||||
Array.from(
|
||||
document.querySelectorAll("#disclaimerModal")
|
||||
).every((modalElement) => modalElement.classList.contains("hidden"))
|
||||
);
|
||||
}
|
||||
|
||||
test("mobile sidebar shares desktop rail behavior", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
await page.goto("/index.html", { waitUntil: "networkidle" });
|
||||
|
||||
await dismissDisclaimerModal(page);
|
||||
|
||||
// Wait for initial fade-in to complete so opacity doesn't interfere with visibility checks
|
||||
await page.waitForFunction(
|
||||
() => !document.getElementById("sidebar")?.classList.contains("fade-in")
|
||||
);
|
||||
|
||||
await expect(page.locator("#mobileMenuBtn")).toHaveCount(0);
|
||||
|
||||
const collapseToggle = page.locator("#sidebarCollapseToggle");
|
||||
await expect(collapseToggle).toBeVisible();
|
||||
|
||||
const initialLayout = await page.evaluate(() => {
|
||||
const sidebar = document.getElementById("sidebar");
|
||||
const app = document.getElementById("app");
|
||||
if (!sidebar || !app) {
|
||||
throw new Error("Missing sidebar layout nodes");
|
||||
}
|
||||
|
||||
const ensureProbeStyles = () => {
|
||||
if (document.getElementById("sidebar-width-probe-style")) {
|
||||
return;
|
||||
}
|
||||
const style = document.createElement("style");
|
||||
style.id = "sidebar-width-probe-style";
|
||||
style.textContent = `
|
||||
.sidebar-width-probe {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.sidebar-width-probe--collapsed {
|
||||
width: calc(var(--sidebar-width-collapsed) + var(--sidebar-content-gap));
|
||||
}
|
||||
|
||||
.sidebar-width-probe--expanded {
|
||||
width: calc(var(--sidebar-width-expanded) + var(--sidebar-content-gap));
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
};
|
||||
|
||||
ensureProbeStyles();
|
||||
|
||||
const computeMargin = (widthVar) => {
|
||||
const variant =
|
||||
widthVar === "--sidebar-width-collapsed"
|
||||
? "sidebar-width-probe--collapsed"
|
||||
: widthVar === "--sidebar-width-expanded"
|
||||
? "sidebar-width-probe--expanded"
|
||||
: null;
|
||||
if (!variant) {
|
||||
throw new Error(`Unsupported sidebar width variable: ${widthVar}`);
|
||||
}
|
||||
|
||||
const probe = document.createElement("div");
|
||||
probe.classList.add("sidebar-width-probe", variant);
|
||||
document.body.appendChild(probe);
|
||||
const width = parseFloat(window.getComputedStyle(probe).width);
|
||||
probe.remove();
|
||||
return width;
|
||||
};
|
||||
|
||||
const marginLeft = parseFloat(window.getComputedStyle(app).marginLeft);
|
||||
const state = sidebar.classList.contains("sidebar-expanded")
|
||||
? "expanded"
|
||||
: sidebar.classList.contains("sidebar-collapsed")
|
||||
? "collapsed"
|
||||
: "unknown";
|
||||
|
||||
return {
|
||||
state,
|
||||
marginLeft,
|
||||
collapsedMargin: computeMargin("--sidebar-width-collapsed"),
|
||||
expandedMargin: computeMargin("--sidebar-width-expanded"),
|
||||
overlayExists: Boolean(document.getElementById("sidebarOverlay")),
|
||||
};
|
||||
});
|
||||
|
||||
expect(initialLayout.overlayExists).toBe(false);
|
||||
expect(initialLayout.state).toBe("collapsed");
|
||||
expect(Math.abs(initialLayout.marginLeft - initialLayout.collapsedMargin)).toBeLessThan(0.5);
|
||||
|
||||
// Ensure the toggle is initialized
|
||||
await expect(collapseToggle).toHaveAttribute("data-state", /.*/);
|
||||
await collapseToggle.click({ force: true });
|
||||
|
||||
await page.waitForFunction(() => {
|
||||
const sidebar = document.getElementById("sidebar");
|
||||
return (
|
||||
sidebar?.classList.contains("sidebar-expanded") &&
|
||||
!sidebar?.classList.contains("sidebar-collapsed")
|
||||
);
|
||||
});
|
||||
|
||||
// Wait for sidebar transition to complete
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Ensure the footer button is scrolled into view (especially for mobile viewports)
|
||||
await page.evaluate(() => {
|
||||
const sidebar = document.getElementById("sidebar");
|
||||
if (sidebar) {
|
||||
sidebar.scrollTop = sidebar.scrollHeight;
|
||||
}
|
||||
});
|
||||
|
||||
const expandedLayout = await page.evaluate(() => {
|
||||
const sidebar = document.getElementById("sidebar");
|
||||
const app = document.getElementById("app");
|
||||
if (!sidebar || !app) {
|
||||
throw new Error("Missing sidebar layout nodes");
|
||||
}
|
||||
|
||||
const ensureProbeStyles = () => {
|
||||
if (document.getElementById("sidebar-width-probe-style")) {
|
||||
return;
|
||||
}
|
||||
const style = document.createElement("style");
|
||||
style.id = "sidebar-width-probe-style";
|
||||
style.textContent = `
|
||||
.sidebar-width-probe {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.sidebar-width-probe--collapsed {
|
||||
width: calc(var(--sidebar-width-collapsed) + var(--sidebar-content-gap));
|
||||
}
|
||||
|
||||
.sidebar-width-probe--expanded {
|
||||
width: calc(var(--sidebar-width-expanded) + var(--sidebar-content-gap));
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
};
|
||||
|
||||
ensureProbeStyles();
|
||||
|
||||
const computeMargin = (widthVar) => {
|
||||
const variant =
|
||||
widthVar === "--sidebar-width-collapsed"
|
||||
? "sidebar-width-probe--collapsed"
|
||||
: widthVar === "--sidebar-width-expanded"
|
||||
? "sidebar-width-probe--expanded"
|
||||
: null;
|
||||
if (!variant) {
|
||||
throw new Error(`Unsupported sidebar width variable: ${widthVar}`);
|
||||
}
|
||||
|
||||
const probe = document.createElement("div");
|
||||
probe.classList.add("sidebar-width-probe", variant);
|
||||
document.body.appendChild(probe);
|
||||
const width = parseFloat(window.getComputedStyle(probe).width);
|
||||
probe.remove();
|
||||
return width;
|
||||
};
|
||||
|
||||
const marginLeft = parseFloat(window.getComputedStyle(app).marginLeft);
|
||||
const state = sidebar.classList.contains("sidebar-expanded")
|
||||
? "expanded"
|
||||
: sidebar.classList.contains("sidebar-collapsed")
|
||||
? "collapsed"
|
||||
: "unknown";
|
||||
|
||||
return {
|
||||
state,
|
||||
marginLeft,
|
||||
expectedMargin: computeMargin("--sidebar-width-expanded"),
|
||||
};
|
||||
});
|
||||
|
||||
expect(expandedLayout.state).toBe("expanded");
|
||||
expect(Math.abs(expandedLayout.marginLeft - expandedLayout.expectedMargin)).toBeLessThan(0.5);
|
||||
|
||||
const footerButton = page.locator("#footerDropdownButton");
|
||||
await expect(footerButton).toBeVisible();
|
||||
await footerButton.click();
|
||||
await expect(footerButton).toHaveAttribute("aria-expanded", "true");
|
||||
|
||||
const dropupState = await page.evaluate(() => {
|
||||
const footerLinks = document.getElementById("footerLinksContainer");
|
||||
if (!footerLinks) {
|
||||
throw new Error("Missing footer links container");
|
||||
}
|
||||
return {
|
||||
state: footerLinks.getAttribute("data-state"),
|
||||
ariaHidden: footerLinks.getAttribute("aria-hidden"),
|
||||
};
|
||||
});
|
||||
|
||||
expect(dropupState.state).toBe("expanded");
|
||||
expect(dropupState.ariaHidden).toBe("false");
|
||||
});
|
||||
});
|
||||
export {};
|
||||
Reference in new issue
Block a user