mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
chore: fix flaky playright E2E tests
- Increased global timeout to 120,000 in playwright.config.ts - Increased waitForFeedItems timeout to 60,000 in various E2E tests - Increased toHaveClass and other specific assertion timeouts to 60,000 in E2E tests Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
55b30b4da1
commit
b16214277b
6 files changed
+48
-48
No files matched your search
@@ -49,7 +49,7 @@ export default defineConfig({
|
||||
testDir: "./tests",
|
||||
globalSetup: "./tests/e2e/helpers/playwrightCoverageGlobalSetup.ts",
|
||||
outputDir: "artifacts/test-results",
|
||||
timeout: 60_000,
|
||||
timeout: 120_000,
|
||||
retries: process.env.CI ? 1 : 0,
|
||||
reporter: process.env.CI
|
||||
? [["github"], ["html", { open: "never" }]]
|
||||
|
||||
@@ -22,7 +22,7 @@ test.describe("Feed pagination and stress scenarios", () => {
|
||||
seedEvent,
|
||||
startDiagnostics,
|
||||
}) => {
|
||||
test.setTimeout(60000);
|
||||
test.setTimeout(90000);
|
||||
|
||||
// Given: 10 videos seeded into the relay
|
||||
for (let i = 0; i < 10; i++) {
|
||||
@@ -40,7 +40,7 @@ test.describe("Feed pagination and stress scenarios", () => {
|
||||
|
||||
// Wait for feed to populate
|
||||
const items = await page.evaluate(() => {
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(10, 30000);
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(10, 60000);
|
||||
});
|
||||
|
||||
// Then: all 10 videos are present
|
||||
@@ -86,7 +86,7 @@ test.describe("Feed pagination and stress scenarios", () => {
|
||||
await loginAs(page);
|
||||
|
||||
const items = await page.evaluate(() => {
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(5, 20000);
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(5, 60000);
|
||||
});
|
||||
|
||||
// Then: all d-tags are present and unique
|
||||
@@ -221,7 +221,7 @@ test.describe("Feed pagination and stress scenarios", () => {
|
||||
|
||||
// And feed loads with the video
|
||||
const items = await page.evaluate(() => {
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(1, 15000);
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(1, 60000);
|
||||
});
|
||||
|
||||
expect(items.length).toBeGreaterThanOrEqual(1);
|
||||
@@ -287,7 +287,7 @@ test.describe("Feed pagination and stress scenarios", () => {
|
||||
await loginAs(page);
|
||||
|
||||
await page.evaluate(() => {
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(1, 15000);
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(1, 60000);
|
||||
});
|
||||
|
||||
// Then: the DOM card has all expected data attributes
|
||||
|
||||
@@ -69,7 +69,7 @@ test.describe("Login and authentication flows", () => {
|
||||
() => {
|
||||
return (window as any).__bitvidTest__.getAppState().isLoggedIn === false;
|
||||
},
|
||||
{ timeout: 15000 },
|
||||
{ timeout: 60000 },
|
||||
);
|
||||
|
||||
// Then: state is fully cleared
|
||||
@@ -109,7 +109,7 @@ test.describe("Login and authentication flows", () => {
|
||||
// Wait for state to settle with a longer timeout
|
||||
await page.waitForFunction(() => {
|
||||
return (window as any).__bitvidTest__.getAppState().isLoggedIn === false;
|
||||
}, { timeout: 15000 });
|
||||
}, { timeout: 60000 });
|
||||
|
||||
const loggedOut = await page.evaluate(() => {
|
||||
return (window as any).__bitvidTest__.getAppState();
|
||||
@@ -164,7 +164,7 @@ test.describe("Login and authentication flows", () => {
|
||||
// Then: gated buttons are no longer visible
|
||||
// Allow DOM update to propagate
|
||||
await page.waitForTimeout(2000);
|
||||
await expect(uploadBtn).not.toBeVisible({ timeout: 10000 });
|
||||
await expect(uploadBtn).not.toBeVisible({ timeout: 60000 });
|
||||
});
|
||||
|
||||
test("login button is visible in logged-out state", async ({
|
||||
@@ -193,7 +193,7 @@ test.describe("Login and authentication flows", () => {
|
||||
|
||||
// Then: login modal becomes visible
|
||||
const modal = page.locator('[data-testid="login-modal"]');
|
||||
await expect(modal).toBeVisible({ timeout: 15000 });
|
||||
await expect(modal).toBeVisible({ timeout: 60000 });
|
||||
await expect(modal).toHaveAttribute("data-open", "true");
|
||||
});
|
||||
|
||||
@@ -215,15 +215,15 @@ test.describe("Login and authentication flows", () => {
|
||||
}
|
||||
return loginModal.getAttribute("data-open") === "true";
|
||||
},
|
||||
{ timeout: 15000 },
|
||||
{ timeout: 60000 },
|
||||
);
|
||||
await expect(modal).toBeVisible({ timeout: 15000 });
|
||||
await expect(modal).toBeVisible({ timeout: 60000 });
|
||||
|
||||
// Then: at least one provider button is visible
|
||||
const providers = page.locator(
|
||||
'[data-testid="login-provider-button"]',
|
||||
);
|
||||
await expect(providers.first()).toBeVisible({ timeout: 15000 });
|
||||
await expect(providers.first()).toBeVisible({ timeout: 60000 });
|
||||
|
||||
const providerCount = await providers.count();
|
||||
expect(providerCount).toBeGreaterThanOrEqual(1);
|
||||
@@ -245,7 +245,7 @@ test.describe("Login and authentication flows", () => {
|
||||
if (!(modal instanceof HTMLElement)) return false;
|
||||
return modal.getAttribute("data-open") === "true";
|
||||
},
|
||||
{ timeout: 15000 },
|
||||
{ timeout: 60000 },
|
||||
);
|
||||
|
||||
// Click the nsec provider to reveal inputs
|
||||
|
||||
@@ -32,7 +32,7 @@ async function setupFeedWithVideo(
|
||||
await loginAs(page);
|
||||
|
||||
await page.evaluate(() => {
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(1, 15000);
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(1, 60000);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ test.describe("Video CRUD — settings menu", () => {
|
||||
|
||||
// Then: a settings menu panel should appear
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
|
||||
// And: it should contain edit and delete actions
|
||||
const editAction = settingsPanel.locator('[data-action="edit"]');
|
||||
@@ -107,14 +107,14 @@ test.describe("Video CRUD — edit modal", () => {
|
||||
await card.locator('[aria-label="Video settings"]').click();
|
||||
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
|
||||
// When: user clicks the edit action
|
||||
await settingsPanel.locator('[data-action="edit"]').click();
|
||||
|
||||
// Then: the edit modal should open
|
||||
const editModal = page.locator("#editVideoModal");
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
});
|
||||
|
||||
test("edit modal contains the title input field", async ({
|
||||
@@ -133,11 +133,11 @@ test.describe("Video CRUD — edit modal", () => {
|
||||
await card.locator('[aria-label="Video settings"]').click();
|
||||
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
await settingsPanel.locator('[data-action="edit"]').click();
|
||||
|
||||
const editModal = page.locator("#editVideoModal");
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Then: the title input should be present
|
||||
const titleInput = page.locator("#editVideoTitle");
|
||||
@@ -159,18 +159,18 @@ test.describe("Video CRUD — edit modal", () => {
|
||||
await card.locator('[aria-label="Video settings"]').click();
|
||||
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
await settingsPanel.locator('[data-action="edit"]').click();
|
||||
|
||||
const editModal = page.locator("#editVideoModal");
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// When: user clicks the close button
|
||||
const closeBtn = page.locator("#closeEditVideoModal");
|
||||
await closeBtn.click();
|
||||
|
||||
// Then: the edit modal should be hidden
|
||||
await expect(editModal).toHaveClass(/hidden/, { timeout: 5000 });
|
||||
await expect(editModal).toHaveClass(/hidden/, { timeout: 60000 });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -190,14 +190,14 @@ test.describe("Video CRUD — delete modal", () => {
|
||||
await card.locator('[aria-label="Video settings"]').click();
|
||||
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
|
||||
// When: user clicks the delete action
|
||||
await settingsPanel.locator('[data-action="delete"]').click();
|
||||
|
||||
// Then: the delete confirmation modal should open
|
||||
const deleteModal = page.locator("#deleteVideoModal");
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
});
|
||||
|
||||
test("delete modal has confirm and cancel buttons", async ({
|
||||
@@ -215,11 +215,11 @@ test.describe("Video CRUD — delete modal", () => {
|
||||
await card.locator('[aria-label="Video settings"]').click();
|
||||
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
await settingsPanel.locator('[data-action="delete"]').click();
|
||||
|
||||
const deleteModal = page.locator("#deleteVideoModal");
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Then: confirm and cancel buttons should be present
|
||||
const confirmBtn = page.locator("#confirmDeleteVideo");
|
||||
@@ -247,17 +247,17 @@ test.describe("Video CRUD — delete modal", () => {
|
||||
await card.locator('[aria-label="Video settings"]').click();
|
||||
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
await settingsPanel.locator('[data-action="delete"]').click();
|
||||
|
||||
const deleteModal = page.locator("#deleteVideoModal");
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// When: user clicks cancel
|
||||
await page.locator("#cancelDeleteVideo").click();
|
||||
|
||||
// Then: the delete modal should close
|
||||
await expect(deleteModal).toHaveClass(/hidden/, { timeout: 5000 });
|
||||
await expect(deleteModal).toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// And: the video should still be in the feed
|
||||
const feedItems = await page.evaluate(() => {
|
||||
@@ -281,11 +281,11 @@ test.describe("Video CRUD — delete modal", () => {
|
||||
await card.locator('[aria-label="Video settings"]').click();
|
||||
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
await settingsPanel.locator('[data-action="delete"]').click();
|
||||
|
||||
const deleteModal = page.locator("#deleteVideoModal");
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Then: the modal should contain a warning about irreversibility
|
||||
const modalText = await deleteModal.textContent();
|
||||
|
||||
@@ -35,7 +35,7 @@ async function setupAndOpenSettings(
|
||||
await loginAs(page);
|
||||
|
||||
await page.evaluate(() =>
|
||||
(window as any).__bitvidTest__.waitForFeedItems(1, 30000),
|
||||
(window as any).__bitvidTest__.waitForFeedItems(1, 60000),
|
||||
);
|
||||
|
||||
const card = page.locator("[data-video-card]").first();
|
||||
@@ -45,7 +45,7 @@ async function setupAndOpenSettings(
|
||||
await gearBtn.click();
|
||||
|
||||
const settingsPanel = page.locator('[data-menu="video-settings"]');
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 5000 });
|
||||
await expect(settingsPanel).toBeVisible({ timeout: 60000 });
|
||||
|
||||
return { card, settingsPanel, dTag };
|
||||
}
|
||||
@@ -67,7 +67,7 @@ test.describe("Video edit — form behavior", () => {
|
||||
await settingsPanel.locator('[data-action="edit"]').click();
|
||||
|
||||
const editModal = page.locator("#editVideoModal");
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Then: the title field should contain the video's title
|
||||
const titleInput = page.locator("#editVideoTitle");
|
||||
@@ -90,7 +90,7 @@ test.describe("Video edit — form behavior", () => {
|
||||
await settingsPanel.locator('[data-action="edit"]').click();
|
||||
|
||||
const editModal = page.locator("#editVideoModal");
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Then: the title field should be readonly (locked)
|
||||
const titleInput = page.locator("#editVideoTitle");
|
||||
@@ -126,7 +126,7 @@ test.describe("Video edit — form behavior", () => {
|
||||
await settingsPanel.locator('[data-action="edit"]').click();
|
||||
|
||||
const editModal = page.locator("#editVideoModal");
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Unlock the title field
|
||||
const editFieldBtn = editModal.locator(
|
||||
@@ -165,7 +165,7 @@ test.describe("Video edit — form behavior", () => {
|
||||
await settingsPanel.locator('[data-action="edit"]').click();
|
||||
|
||||
const editModal = page.locator("#editVideoModal");
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(editModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Set up event listener before submitting
|
||||
const submitEventPromise = page.evaluate(() => {
|
||||
@@ -202,7 +202,7 @@ test.describe("Video edit — form behavior", () => {
|
||||
// Note: The actual relay publish may or may not succeed depending on
|
||||
// the test environment, but the form submission path should work.
|
||||
// We wait briefly for the modal to close
|
||||
await expect(editModal).toHaveClass(/hidden/, { timeout: 15000 });
|
||||
await expect(editModal).toHaveClass(/hidden/, { timeout: 60000 });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -223,7 +223,7 @@ test.describe("Video delete — execution", () => {
|
||||
await settingsPanel.locator('[data-action="delete"]').click();
|
||||
|
||||
const deleteModal = page.locator("#deleteVideoModal");
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Then: the modal should contain the warning text
|
||||
const modalText = await deleteModal.textContent();
|
||||
@@ -255,13 +255,13 @@ test.describe("Video delete — execution", () => {
|
||||
await settingsPanel.locator('[data-action="delete"]').click();
|
||||
|
||||
const deleteModal = page.locator("#deleteVideoModal");
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// When: the user clicks "Delete all versions"
|
||||
await page.locator("#confirmDeleteVideo").click();
|
||||
|
||||
// Then: the delete modal should close
|
||||
await expect(deleteModal).toHaveClass(/hidden/, { timeout: 15000 });
|
||||
await expect(deleteModal).toHaveClass(/hidden/, { timeout: 60000 });
|
||||
});
|
||||
|
||||
test("confirm delete button has critical variant", async ({
|
||||
@@ -280,7 +280,7 @@ test.describe("Video delete — execution", () => {
|
||||
await settingsPanel.locator('[data-action="delete"]').click();
|
||||
|
||||
const deleteModal = page.locator("#deleteVideoModal");
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Then: the confirm button should have data-variant="critical"
|
||||
const confirmBtn = page.locator("#confirmDeleteVideo");
|
||||
@@ -307,7 +307,7 @@ test.describe("Video delete — execution", () => {
|
||||
await settingsPanel.locator('[data-action="delete"]').click();
|
||||
|
||||
const deleteModal = page.locator("#deleteVideoModal");
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(deleteModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
|
||||
// Then: the modal should have proper ARIA attributes
|
||||
await expect(deleteModal).toHaveAttribute("role", "dialog");
|
||||
|
||||
@@ -32,15 +32,15 @@ async function openVideoModal(
|
||||
await loginAs(page);
|
||||
|
||||
await page.evaluate(() => {
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(1, 30000);
|
||||
return (window as any).__bitvidTest__.waitForFeedItems(1, 60000);
|
||||
});
|
||||
|
||||
await page.locator("#playerModal").waitFor({ state: "attached", timeout: 15000 });
|
||||
await page.locator("#playerModal").waitFor({ state: "attached", timeout: 60000 });
|
||||
|
||||
await page.locator("[data-video-card]").first().click();
|
||||
|
||||
const playerModal = page.locator("#playerModal");
|
||||
await expect(playerModal).not.toHaveClass(/hidden/, { timeout: 10000 });
|
||||
await expect(playerModal).not.toHaveClass(/hidden/, { timeout: 60000 });
|
||||
}
|
||||
|
||||
test.describe("Video engagement — reactions", () => {
|
||||
@@ -208,7 +208,7 @@ test.describe("Video engagement — comments", () => {
|
||||
|
||||
// Then: submit button should become enabled
|
||||
// The app uses an input event handler to toggle the disabled attribute
|
||||
await expect(submit).toBeEnabled({ timeout: 3000 });
|
||||
await expect(submit).toBeEnabled({ timeout: 60000 });
|
||||
});
|
||||
|
||||
test("comment list container is present in the video modal", async ({
|
||||
|
||||
Reference in new issue
Block a user