From b7d2c7450cd65d8555c1c04dd703d6aeb3f4f9cf Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 21 Nov 2025 17:50:30 +0100 Subject: [PATCH 1/4] Enhance component testing: Add error handling for modal interactions and improve visibility checks for UI elements in e2e tests. --- .../e2e-tests/component-testing.spec.ts | 117 ++++++++++------- .../react/e2e-tests/component-testing.spec.ts | 123 +++++++++++------- 2 files changed, 146 insertions(+), 94 deletions(-) diff --git a/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts b/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts index f965d0747499..d72f421a4b05 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts +++ b/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts @@ -82,6 +82,18 @@ test.describe("component testing", () => { }); test.afterEach(async ({ page }) => { + await page.click("body"); + try { + const descriptionButton = page.locator("#testing-module-description a"); + if ( + await descriptionButton.isVisible({ timeout: 4000 }).catch(() => false) + ) { + await descriptionButton.click({ timeout: 4000, force: true }); + } + } catch { + // Ignore any errors when trying to open the modal + } + await restoreAllFiles(); const expandTestingModule = page.getByLabel("Expand testing module"); @@ -95,14 +107,17 @@ test.describe("component testing", () => { await clearStatusesButton.click(); } -const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); - if (await watchModeToggle.isVisible() && await watchModeToggle.getAttribute("aria-checked") === "true") { + const watchModeToggle = page.getByRole("switch", { name: "Watch mode" }); + if ( + (await watchModeToggle.isVisible()) && + (await watchModeToggle.getAttribute("aria-checked")) === "true" + ) { await watchModeToggle.click(); } const configs = [ - page.getByRole('checkbox', { name: 'Coverage' }), - page.getByRole('checkbox', { name: 'Accessibility' }), + page.getByRole("checkbox", { name: "Coverage" }), + page.getByRole("checkbox", { name: "Accessibility" }), ]; for (const config of configs) { if (await config.isChecked()) { @@ -154,7 +169,9 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); timeout: 60000, }); - const errorFilter = page.getByLabel(/Filter main navigation to show \d+ tests with errors/); + const errorFilter = page.getByLabel( + /Filter main navigation to show \d+ tests with errors/ + ); await expect(errorFilter).toBeVisible(); // Assert discrepancy: CLI pass + Browser fail @@ -206,7 +223,9 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); ); const runTestsButton = await page.getByLabel("Start test run"); - const watchModeButton = await page.getByRole('switch', { name: 'Watch mode' }); + const watchModeButton = await page.getByRole("switch", { + name: "Watch mode", + }); await expect(runTestsButton).toBeEnabled(); await expect(watchModeButton).toBeEnabled(); @@ -216,7 +235,6 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); await Promise.all([ expect(watchModeButton).toBeDisabled(), expect(page.locator("#testing-module-description")).toHaveText(/Testing/), - ]); // Wait for test results to appear @@ -228,12 +246,14 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); await expect(runTestsButton).toBeEnabled(); await expect(watchModeButton).toBeEnabled(); - const errorFilter = page.getByLabel(/Filter main navigation to show \d+ tests with errors/); + const errorFilter = page.getByLabel( + /Filter main navigation to show \d+ tests with errors/ + ); await expect(errorFilter).toBeVisible(); // Assert for expected success const successfulStoryElement = page.locator( - '[data-item-id="addons-group-test--expected-success"] [data-testid="tree-status-button"]' + '[data-item-id="addons-group-test--expected-success"] [data-testid="tree-status-button"]' ); await expect(successfulStoryElement).toHaveAttribute( "aria-label", @@ -276,7 +296,7 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); .getByRole("button", { name: "test" }); await expect(storyElement).toBeVisible({ timeout: 30000 }); - await page.getByRole('switch', { name: 'Watch mode' }).click(); + await page.getByRole("switch", { name: "Watch mode" }).click(); // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(8000); @@ -285,7 +305,9 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); ); // Wait for test results to appear - const errorFilter = page.getByLabel(/Filter main navigation to show \d+ tests with errors/); + const errorFilter = page.getByLabel( + /Filter main navigation to show \d+ tests with errors/ + ); await expect(errorFilter).toBeVisible({ timeout: 30000 }); // Assert for expected success @@ -330,7 +352,7 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); .getByRole("button", { name: "test" }); await expect(storyElement).toBeVisible({ timeout: 30000 }); - await page.getByRole('switch', { name: 'Watch mode' }).click(); + await page.getByRole("switch", { name: "Watch mode" }).click(); // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(3000); @@ -369,7 +391,7 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); .getByRole("button", { name: "test" }); await expect(storyElement).toBeVisible({ timeout: 30000 }); - await page.getByRole('switch', { name: 'Watch mode' }).click(); + await page.getByRole("switch", { name: "Watch mode" }).click(); // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(3000); @@ -409,7 +431,7 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); .getByRole("button", { name: "test" }); await expect(storyElement).toBeVisible({ timeout: 30000 }); - await page.getByRole('switch', { name: 'Watch mode' }).click(); + await page.getByRole("switch", { name: "Watch mode" }).click(); // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(3000); @@ -513,7 +535,7 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); '[data-item-id="addons-group-test--expected-failure"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); // Assert - Only one test is running and reported @@ -525,8 +547,9 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); ).toHaveCount(1); await page.click("body"); await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: success\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: success"]' + ) ).toHaveCount(1); }); @@ -550,18 +573,18 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); await page.locator('[data-item-id="example-unhandlederrors"]').hover(); await page .locator( - '[data-item-id="example-unhandlederrors"] button[data-testid="context-menu"]' + '[data-item-id="example-unhandlederrors"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); // HACK: the testing module popover has poor tracking of focus due to how many disabled // buttons it has and how deeply it changes its UI on events. This would be solved once // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab // around to reset focus. - await page.keyboard.press('Tab'); - await page.keyboard.press('Escape'); + await page.keyboard.press("Tab"); + await page.keyboard.press("Escape"); await page.click("body"); await expect(sidebarContextMenu).not.toBeVisible(); @@ -609,7 +632,7 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); '[data-item-id="addons-group-test"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); // Assert - Tests are running and reported @@ -628,19 +651,21 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); // buttons it has and how deeply it changes its UI on events. This would be solved once // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab // around to reset focus. - await page.keyboard.press('Tab'); - await page.keyboard.press('Escape'); + await page.keyboard.press("Tab"); + await page.keyboard.press("Escape"); await page.click("body"); await expect(sidebarContextMenu).not.toBeVisible(); await page.click("body"); await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: success\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: success"]' + ) ).toHaveCount(8); await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: error\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: error"]' + ) ).toHaveCount(3); }); @@ -666,7 +691,7 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); '[data-item-id="addons-group"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); // Assert - 1 failing test shows as a failed status @@ -677,25 +702,25 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); sidebarContextMenu.getByLabel("Component tests failed") ).toHaveCount(1); -// HACK: the testing module popover has poor tracking of focus due to how many disabled + // HACK: the testing module popover has poor tracking of focus due to how many disabled // buttons it has and how deeply it changes its UI on events. This would be solved once // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab // around to reset focus. - await page.keyboard.press('Tab'); - await page.keyboard.press('Escape'); + await page.keyboard.press("Tab"); + await page.keyboard.press("Escape"); await page.click("body"); await expect(sidebarContextMenu).not.toBeVisible(); // Assert - Tests are running and reported + await expect(page.locator("#testing-module-description")).toContainText( + "Ran 11 tests", + { timeout: 30000 } + ); await expect( - page.locator("#testing-module-description") - ).toContainText("Ran 11 tests", { timeout: 30000 }); - await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: error\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: error"]' + ) ).toHaveCount(4); // 1 visible/expanded story, 1 expanded component, 1 collapsed component, 1 group - - }); test("should run focused tests without coverage, even when enabled", async ({ @@ -730,23 +755,23 @@ const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); '[data-item-id="example-button--csf-3-primary"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); - // HACK: the testing module popover has poor tracking of focus due to how many disabled // buttons it has and how deeply it changes its UI on events. This would be solved once // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab // around to reset focus. - await page.keyboard.press('Tab'); - await page.keyboard.press('Escape'); + await page.keyboard.press("Tab"); + await page.keyboard.press("Escape"); await page.click("body"); await expect(sidebarContextMenu).not.toBeVisible(); // Arrange - Wait for test to finish and unfocus sidebar context menu - await expect( - page.locator("#testing-module-description") - ).toContainText("Ran 1 test", { timeout: 30000 }); + await expect(page.locator("#testing-module-description")).toContainText( + "Ran 1 test", + { timeout: 30000 } + ); await page.click("body"); // Assert - Coverage is not shown because Focused Tests shouldn't collect coverage diff --git a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts index 8d95b2decf4e..8b46353a443a 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts +++ b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts @@ -82,6 +82,18 @@ test.describe("component testing", () => { }); test.afterEach(async ({ page }) => { + await page.click("body"); + try { + const descriptionButton = page.locator("#testing-module-description a"); + if ( + await descriptionButton.isVisible({ timeout: 4000 }).catch(() => false) + ) { + await descriptionButton.click({ timeout: 4000, force: true }); + } + } catch { + // Ignore any errors when trying to open the modal + } + await restoreAllFiles(); const expandTestingModule = page.getByLabel("Expand testing module"); @@ -95,14 +107,17 @@ test.describe("component testing", () => { await clearStatusesButton.click(); } - const watchModeToggle = page.getByRole('switch', { name: 'Watch mode' }); - if (await watchModeToggle.isVisible() && await watchModeToggle.getAttribute("aria-checked") === "true") { + const watchModeToggle = page.getByRole("switch", { name: "Watch mode" }); + if ( + (await watchModeToggle.isVisible()) && + (await watchModeToggle.getAttribute("aria-checked")) === "true" + ) { await watchModeToggle.click(); } const configs = [ - page.getByRole('checkbox', { name: 'Coverage' }), - page.getByRole('checkbox', { name: 'Accessibility' }), + page.getByRole("checkbox", { name: "Coverage" }), + page.getByRole("checkbox", { name: "Accessibility" }), ]; for (const config of configs) { if (await config.isChecked()) { @@ -154,7 +169,9 @@ test.describe("component testing", () => { timeout: 60000, }); - const errorFilter = page.getByLabel(/Filter main navigation to show \d+ tests with errors/); + const errorFilter = page.getByLabel( + /Filter main navigation to show \d+ tests with errors/ + ); await expect(errorFilter).toBeVisible(); // Assert discrepancy: CLI pass + Browser fail @@ -206,7 +223,9 @@ test.describe("component testing", () => { ); const runTestsButton = await page.getByLabel("Start test run"); - const watchModeButton = await page.getByRole('switch', { name: 'Watch mode' }); + const watchModeButton = await page.getByRole("switch", { + name: "Watch mode", + }); await expect(runTestsButton).toBeEnabled(); await expect(watchModeButton).toBeEnabled(); @@ -216,7 +235,6 @@ test.describe("component testing", () => { await Promise.all([ expect(watchModeButton).toBeDisabled(), expect(page.locator("#testing-module-description")).toHaveText(/Testing/), - ]); // Wait for test results to appear @@ -228,7 +246,9 @@ test.describe("component testing", () => { await expect(runTestsButton).toBeEnabled(); await expect(watchModeButton).toBeEnabled(); - const errorFilter = page.getByLabel(/Filter main navigation to show \d+ tests with errors/); + const errorFilter = page.getByLabel( + /Filter main navigation to show \d+ tests with errors/ + ); await expect(errorFilter).toBeVisible(); // Assert for expected success @@ -276,7 +296,7 @@ test.describe("component testing", () => { .getByRole("button", { name: "test" }); await expect(storyElement).toBeVisible({ timeout: 30000 }); - await page.getByRole('switch', { name: 'Watch mode' }).click(); + await page.getByRole("switch", { name: "Watch mode" }).click(); // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(8000); @@ -285,7 +305,9 @@ test.describe("component testing", () => { ); // Wait for test results to appear - const errorFilter = page.getByLabel(/Filter main navigation to show \d+ tests with errors/); + const errorFilter = page.getByLabel( + /Filter main navigation to show \d+ tests with errors/ + ); await expect(errorFilter).toBeVisible({ timeout: 30000 }); // Assert for expected success @@ -330,7 +352,7 @@ test.describe("component testing", () => { .getByRole("button", { name: "test" }); await expect(storyElement).toBeVisible({ timeout: 30000 }); - await page.getByRole('switch', { name: 'Watch mode' }).click(); + await page.getByRole("switch", { name: "Watch mode" }).click(); // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(3000); @@ -369,7 +391,7 @@ test.describe("component testing", () => { .getByRole("button", { name: "test" }); await expect(storyElement).toBeVisible({ timeout: 30000 }); - await page.getByRole('switch', { name: 'Watch mode' }).click(); + await page.getByRole("switch", { name: "Watch mode" }).click(); // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(3000); @@ -409,7 +431,7 @@ test.describe("component testing", () => { .getByRole("button", { name: "test" }); await expect(storyElement).toBeVisible({ timeout: 30000 }); - await page.getByRole('switch', { name: 'Watch mode' }).click(); + await page.getByRole("switch", { name: "Watch mode" }).click(); // We shouldn't have to do an arbitrary wait, but because there is no UI for loading state yet, we have to await page.waitForTimeout(3000); @@ -513,7 +535,7 @@ test.describe("component testing", () => { '[data-item-id="addons-group-test--expected-failure"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); // Assert - Only one test is running and reported @@ -525,8 +547,9 @@ test.describe("component testing", () => { ).toHaveCount(1); await page.click("body"); await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: success\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: success"]' + ) ).toHaveCount(1); }); @@ -553,21 +576,20 @@ test.describe("component testing", () => { '[data-item-id="example-unhandlederrors"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); // HACK: the testing module popover has poor tracking of focus due to how many disabled // buttons it has and how deeply it changes its UI on events. This would be solved once // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab // around to reset focus. - await page.keyboard.press('Tab'); - await page.keyboard.press('Escape'); + await page.keyboard.press("Tab"); + await page.keyboard.press("Escape"); await page.click("body"); await expect(sidebarContextMenu).not.toBeVisible(); // Assert - Tests are running and errors are reported - const errorLink = page.locator("#testing-module-description a" - ); + const errorLink = page.locator("#testing-module-description a"); await expect(errorLink).toContainText("View full error", { timeout: 30000, }); @@ -608,7 +630,7 @@ test.describe("component testing", () => { '[data-item-id="addons-group-test"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); // Assert - Tests are running and reported @@ -627,19 +649,21 @@ test.describe("component testing", () => { // buttons it has and how deeply it changes its UI on events. This would be solved once // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab // around to reset focus. - await page.keyboard.press('Tab'); - await page.keyboard.press('Escape'); + await page.keyboard.press("Tab"); + await page.keyboard.press("Escape"); await page.click("body"); await expect(sidebarContextMenu).not.toBeVisible(); await page.click("body"); await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: success\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: success"]' + ) ).toHaveCount(8); await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: error\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: error"]' + ) ).toHaveCount(3); // 1 story, 1 component, 1 group }); @@ -665,9 +689,8 @@ test.describe("component testing", () => { '[data-item-id="addons-group"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); - // Assert - 1 failing test shows as a failed status await expect( @@ -681,29 +704,32 @@ test.describe("component testing", () => { // buttons it has and how deeply it changes its UI on events. This would be solved once // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab // around to reset focus. - await page.keyboard.press('Tab'); - await page.keyboard.press('Escape'); + await page.keyboard.press("Tab"); + await page.keyboard.press("Escape"); await page.click("body"); await expect(sidebarContextMenu).not.toBeVisible(); // Assert - Tests are running and reported + await expect(page.locator("#testing-module-description")).toContainText( + "Ran 11 tests", + { timeout: 30000 } + ); await expect( - page.locator("#testing-module-description") - ).toContainText("Ran 11 tests", { timeout: 30000 }); - await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: error\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: error"]' + ) ).toHaveCount(4); // 1 visible/expanded story, 1 expanded component, 1 collapsed component, 1 group - await page.click("body"); await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: success\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: success"]' + ) ).toHaveCount(8); await expect( - page - .locator("#storybook-explorer-menu [data-testid=\"tree-status-button\"][aria-label=\"Test status: error\"]") + page.locator( + '#storybook-explorer-menu [data-testid="tree-status-button"][aria-label="Test status: error"]' + ) ).toHaveCount(4); }); @@ -739,22 +765,23 @@ test.describe("component testing", () => { '[data-item-id="example-button--csf-3-primary"] button[data-testid="context-menu"]' ) .click(); - const sidebarContextMenu = page.getByRole('dialog'); + const sidebarContextMenu = page.getByRole("dialog"); await sidebarContextMenu.getByLabel("Start test run").click(); // HACK: the testing module popover has poor tracking of focus due to how many disabled // buttons it has and how deeply it changes its UI on events. This would be solved once // we move to a declarative menu, and there's an ongoing PR for that. Until then, we tab // around to reset focus. - await page.keyboard.press('Tab'); - await page.keyboard.press('Escape'); + await page.keyboard.press("Tab"); + await page.keyboard.press("Escape"); await page.click("body"); await expect(sidebarContextMenu).not.toBeVisible(); // Arrange - Wait for test to finish and unfocus sidebar context menu - await expect( - page.locator("#testing-module-description") - ).toContainText("Ran 1 test", { timeout: 30000 }); + await expect(page.locator("#testing-module-description")).toContainText( + "Ran 1 test", + { timeout: 30000 } + ); await page.click("body"); // Assert - Coverage is not shown because Focused Tests shouldn't collect coverage From 024565e6d345e09da5eae5b1ab8bf7f19bcfa6b8 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Tue, 25 Nov 2025 11:35:51 +0100 Subject: [PATCH 2/4] Improve e2e component testing: Add handling for modal interactions to enhance error visibility during tests. --- .../react-vitest-3/e2e-tests/component-testing.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts b/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts index d72f421a4b05..836fd4dd8fce 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts +++ b/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts @@ -84,12 +84,18 @@ test.describe("component testing", () => { test.afterEach(async ({ page }) => { await page.click("body"); try { + /** Sometimes the vitest instance fails, but the error-content is only shown in a modal. + * We click the link so the modal opens and we can close it. + * Having it open shortly is enough to have it be in the playwright trace, for debugging purposes. + */ const descriptionButton = page.locator("#testing-module-description a"); if ( await descriptionButton.isVisible({ timeout: 4000 }).catch(() => false) ) { await descriptionButton.click({ timeout: 4000, force: true }); } + + await page.getByLabel("Close modal").click(); } catch { // Ignore any errors when trying to open the modal } From 7c93a23aac50fe03cb625771fa92580d60278aa5 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 27 Nov 2025 13:10:08 +0100 Subject: [PATCH 3/4] expire early, and only try close when modal was opened --- .../react-vitest-3/e2e-tests/component-testing.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts b/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts index 78a469087d44..59918515927c 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts +++ b/test-storybooks/portable-stories-kitchen-sink/react-vitest-3/e2e-tests/component-testing.spec.ts @@ -93,9 +93,11 @@ test.describe("component testing", () => { await descriptionButton.isVisible({ timeout: 4000 }).catch(() => false) ) { await descriptionButton.click({ timeout: 4000, force: true }); - } - await page.getByLabel("Close modal").click(); + await page + .getByLabel("Close modal") + .click({ timeout: 4000, force: true }); + } } catch { // Ignore any errors when trying to open the modal } From d82560cf754fdb543ca443677a6e4fed03ea6550 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 28 Nov 2025 09:34:36 +0100 Subject: [PATCH 4/4] Add click action to close modal in component testing spec --- .../react/e2e-tests/component-testing.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts index e239e853422a..2c9f06c4f4c6 100644 --- a/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts +++ b/test-storybooks/portable-stories-kitchen-sink/react/e2e-tests/component-testing.spec.ts @@ -89,6 +89,10 @@ test.describe("component testing", () => { await descriptionButton.isVisible({ timeout: 4000 }).catch(() => false) ) { await descriptionButton.click({ timeout: 4000, force: true }); + + await page + .getByLabel("Close modal") + .click({ timeout: 4000, force: true }); } } catch { // Ignore any errors when trying to open the modal