From 10801b6334e2f9f6a8f2d12d6a6056a5a5cb3acd Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:57:53 +0200 Subject: [PATCH] E2E test fixes (#2901) --- .github/workflows/e2e-tests.yml | 7 ++ .../components/Bracket/Match.tsx | 2 +- e2e/analyzer.spec.ts | 5 ++ e2e/navigation.spec.ts | 43 +++++++--- e2e/tournament-bracket.spec.ts | 79 ++++++++++++++++--- 5 files changed, 112 insertions(+), 24 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 8e7304398..142fe40d3 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -62,3 +62,10 @@ jobs: name: playwright-report path: playwright-report/ retention-days: 30 + + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: playwright-traces + path: test-results/ + retention-days: 30 diff --git a/app/features/tournament-bracket/components/Bracket/Match.tsx b/app/features/tournament-bracket/components/Bracket/Match.tsx index 652bbef38..d0d3eca43 100644 --- a/app/features/tournament-bracket/components/Bracket/Match.tsx +++ b/app/features/tournament-bracket/components/Bracket/Match.tsx @@ -371,7 +371,7 @@ function MatchTimer({ match, bracket }: Pick) { : "var(--color-text)"; return ( -
+
{displayText}
diff --git a/e2e/analyzer.spec.ts b/e2e/analyzer.spec.ts index 75201ac5c..f11744779 100644 --- a/e2e/analyzer.spec.ts +++ b/e2e/analyzer.spec.ts @@ -71,6 +71,11 @@ test.describe("Build Analyzer", () => { await swimSpeedAbilityButtonLocator.click(); await expect(swimSpeedAbilityLocator).toBeVisible(); await swimSpeedAbilityButtonLocator.click(); + await expect( + page.locator( + "[data-testid='ability-selector'] [data-testid='SSU-ability']", + ), + ).toHaveCount(2); await page.getByTestId("ap-tab").click(); await expect(page.getByTestId("ap-compare-1").first()).toContainText( diff --git a/e2e/navigation.spec.ts b/e2e/navigation.spec.ts index f2643e76b..7ce30e66d 100644 --- a/e2e/navigation.spec.ts +++ b/e2e/navigation.spec.ts @@ -27,21 +27,30 @@ test.describe("Navigation", () => { // TopNavMenus — Play await page.getByRole("button", { name: "Play" }).click(); - await expect(page.getByRole("link", { name: "SendouQ" })).toBeVisible(); - await expect(page.getByRole("link", { name: "Scrims" })).toBeVisible(); - await page.getByRole("link", { name: "SendouQ" }).click(); - await expect(page.getByRole("link", { name: "SendouQ" })).not.toBeVisible(); + const playMenu = page.locator("[class*='menuContent']"); + await expect(playMenu.getByRole("link", { name: "SendouQ" })).toBeVisible(); + await expect(playMenu.getByRole("link", { name: "Scrims" })).toBeVisible(); + await playMenu.getByRole("link", { name: "SendouQ" }).click(); + await expect( + playMenu.getByRole("link", { name: "SendouQ" }), + ).not.toBeVisible(); await navigate({ page, url: "/" }); // TopNavMenus — Tools await page.getByRole("button", { name: "Tools" }).click(); - await expect(page.getByRole("link", { name: "Analyzer" })).toBeVisible(); + const toolsMenu = page.locator("[class*='menuContent']"); + await expect( + toolsMenu.getByRole("link", { name: "Analyzer" }), + ).toBeVisible(); await page.keyboard.press("Escape"); // TopNavMenus — Community await page.getByRole("button", { name: "Community" }).click(); - await expect(page.getByRole("link", { name: "Builds" })).toBeVisible(); + const communityMenu = page.locator("[class*='menuContent']"); + await expect( + communityMenu.getByRole("link", { name: "Builds" }), + ).toBeVisible(); await page.keyboard.press("Escape"); // SideNav footer — user info @@ -69,9 +78,16 @@ test.describe("Navigation", () => { // Menu panel — open and verify contents await menuTab.click(); - await expect(page.getByRole("link", { name: "SendouQ" })).toBeVisible(); - await expect(page.getByRole("link", { name: "Analyzer" })).toBeVisible(); - await expect(page.getByRole("link", { name: "Builds" })).toBeVisible(); + const mobileMenu = page.getByLabel("Menu", { exact: true }); + await expect( + mobileMenu.getByRole("link", { name: "SendouQ" }), + ).toBeVisible(); + await expect( + mobileMenu.getByRole("link", { name: "Analyzer" }), + ).toBeVisible(); + await expect( + mobileMenu.getByRole("link", { name: "Builds" }), + ).toBeVisible(); await expect( page.locator("h3").filter({ hasText: "Streams" }), ).toBeVisible(); @@ -83,7 +99,9 @@ test.describe("Navigation", () => { .locator("[class*='ghostTab']:not([class*='ghostTabBar'])") .nth(1) .dispatchEvent("click"); - await expect(page.getByRole("link", { name: "SendouQ" })).not.toBeVisible(); + await expect( + mobileMenu.getByRole("link", { name: "SendouQ" }), + ).not.toBeVisible(); const friendsViewAll = page.getByRole("link", { name: /View all/ }); await expect(friendsViewAll).toBeVisible(); @@ -141,7 +159,10 @@ test.describe("Navigation", () => { // TopNavMenus still work await page.getByRole("button", { name: "Play" }).click(); - await expect(page.getByRole("link", { name: "SendouQ" })).toBeVisible(); + const tabletPlayMenu = page.locator("[class*='menuContent']"); + await expect( + tabletPlayMenu.getByRole("link", { name: "SendouQ" }), + ).toBeVisible(); await page.keyboard.press("Escape"); // MobileNav hidden diff --git a/e2e/tournament-bracket.spec.ts b/e2e/tournament-bracket.spec.ts index eeda557a5..332f9b7de 100644 --- a/e2e/tournament-bracket.spec.ts +++ b/e2e/tournament-bracket.spec.ts @@ -135,8 +135,10 @@ const reportResult = async ({ }; const backToBracket = async (page: Page) => { - await page.getByTestId("back-to-bracket-button").click(); - await expect(page.getByTestId("brackets-viewer")).toBeVisible(); + await expect(async () => { + await page.getByTestId("back-to-bracket-button").click(); + await expect(page.getByTestId("brackets-viewer")).toBeVisible(); + }).toPass(); }; const expectScore = (page: Page, score: [number, number]) => @@ -197,6 +199,7 @@ test.describe("Tournament bracket", () => { // 6) Try to reopen N-ZAP's first match and succeed // 7) As N-ZAP, undo all scores and switch to different team sweeping test("reports score and sees bracket update", async ({ page }) => { + test.slow(); const tournamentId = 2; await startBracket(page); @@ -371,7 +374,7 @@ test.describe("Tournament bracket", () => { test("completes and finalizes a small tournament (RR->SE w/ underground bracket)", async ({ page, }) => { - test.slow(); + test.setTimeout(150_000); const tournamentId = 3; @@ -471,8 +474,60 @@ test.describe("Tournament bracket", () => { await navigateToMatch(page, 14); await isNotVisible(page.getByTestId("reopen-match-button")); await backToBracket(page); + }); + + test("shows tournament results on user profile after finalized tournament", async ({ + page, + }) => { + const tournamentId = 4; + + await seed(page, "SMALL_SOS"); + await impersonate(page); + + await navigate({ + page, + url: tournamentAdminPage(tournamentId), + }); + + await page.getByLabel("Action").selectOption("CHECK_OUT"); + for (const teamId of ["303", "304"]) { + await page.getByLabel("Team", { exact: true }).selectOption(teamId); + await submit(page); + } + + await page.getByTestId("edit-event-info-button").click(); + for (let i = 0; i < 3; i++) { + await page.getByTestId("delete-bracket-button").last().click(); + } + await page.getByTestId("placements-input").last().fill("1,2"); + await submit(page); + + await page.getByTestId("brackets-tab").click(); + await page.getByTestId("finalize-bracket-button").click(); + await submit(page, "confirm-finalize-bracket-button"); + + await page.locator('[data-match-id="1"]').click(); + await reportResult({ + page, + amountOfMapsToReport: 2, + points: [100, 0], + }); + await backToBracket(page); + + await page.getByRole("tab", { name: "Great White" }).click(); + await page.getByTestId("finalize-bracket-button").click(); + await submit(page, "confirm-finalize-bracket-button"); + + await page.locator('[data-match-id="2"]').click(); + await reportResult({ + page, + amountOfMapsToReport: 3, + }); + await backToBracket(page); + + await page.getByTestId("finalize-tournament-button").click(); + await page.getByRole("button", { name: "Finalize" }).click(); - // added result to user profile await page.getByTestId("results-tab").click(); await page.getByTestId("result-team-name").first().click(); await page.getByTestId("team-member-name").first().click(); @@ -483,19 +538,18 @@ test.describe("Tournament bracket", () => { await page.getByTestId("user-results-tab").click(); await expect( page.getByTestId("tournament-name-cell").first(), - ).toContainText("Paddling Pool 253"); + ).toContainText("Swim or Sink 101"); await page.getByTestId("mates-button").first().click(); await expect( page.locator('[data-testid="mates-cell-placement-0"] li'), ).toHaveCount(3); - - // if more assertions added below we need to close the popover first (data-testid="underlay") }); test("changes SOS format and progresses with it & adds a member to another team", async ({ page, }) => { + test.slow(); const tournamentId = 4; await seed(page, "SMALL_SOS"); @@ -689,6 +743,7 @@ test.describe("Tournament bracket", () => { }); test("reopens round robin match and changes score", async ({ page }) => { + test.slow(); const tournamentId = 3; await seed(page); @@ -1188,15 +1243,15 @@ test.describe("Tournament bracket", () => { await backToBracket(page); - // Fast forward a bit to ensure timer shows on bracket - await page.clock.fastForward("00:10"); // 10 seconds - await page.waitForTimeout(1000); - const bracketMatch = page.locator('[data-match-id="5"]'); await expect(bracketMatch).toBeVisible(); + // Verify timer shows on bracket page (timer is a sibling of the match link) + const matchWrapper = bracketMatch.locator(".."); + await expect(matchWrapper.getByTestId("bracket-match-timer")).toBeVisible(); + // Fast forward time past limit (30 minutes for Bo3 = 26min limit) - await page.clock.fastForward("29:50"); // Total 30 minutes + await page.clock.fastForward("30:00"); await page.reload(); await navigateToMatch(page, matchId);