diff --git a/src/testing/jest/jest-27-and-under/jest-environment.ts b/src/testing/jest/jest-27-and-under/jest-environment.ts index 6adbc53b3f8..9e6851d70e9 100644 --- a/src/testing/jest/jest-27-and-under/jest-environment.ts +++ b/src/testing/jest/jest-27-and-under/jest-environment.ts @@ -29,6 +29,11 @@ export function createJestPuppeteerEnvironment(): JestPuppeteerEnvironmentConstr this.browser = await connectBrowser(); } + /** + * if the user had open pages before, close them all when creating a new one + */ + await this.closeOpenPages(); + const page = await newBrowserPage(this.browser); this.pages.push(page); // during E2E tests, we can safely assume that the current environment is a `E2EProcessEnv` @@ -40,7 +45,7 @@ export function createJestPuppeteerEnvironment(): JestPuppeteerEnvironmentConstr } async closeOpenPages() { - await Promise.all(this.pages.map((page) => page.close())); + await Promise.all(this.pages.filter((page) => !page.isClosed()).map((page) => page.close())); this.pages.length = 0; } diff --git a/src/testing/jest/jest-27-and-under/jest-setup-test-framework.ts b/src/testing/jest/jest-27-and-under/jest-setup-test-framework.ts index cf76f538c6c..155068c3f0b 100644 --- a/src/testing/jest/jest-27-and-under/jest-setup-test-framework.ts +++ b/src/testing/jest/jest-27-and-under/jest-setup-test-framework.ts @@ -34,9 +34,6 @@ export function jestSetupTestFramework() { }); afterEach(async () => { - if (global.__CLOSE_OPEN_PAGES__) { - await global.__CLOSE_OPEN_PAGES__(); - } stopAutoApplyChanges(); // Remove each node from the mocked DOM @@ -61,6 +58,12 @@ export function jestSetupTestFramework() { global.resourcesUrl = '/build'; }); + afterAll(async () => { + if (global.__CLOSE_OPEN_PAGES__) { + await global.__CLOSE_OPEN_PAGES__(); + } + }); + const jasmineEnv = (jasmine as any).getEnv(); if (jasmineEnv != null) { jasmineEnv.addReporter({ diff --git a/src/testing/jest/jest-28/jest-environment.ts b/src/testing/jest/jest-28/jest-environment.ts index 3dc0daaf46c..4ac1530e380 100644 --- a/src/testing/jest/jest-28/jest-environment.ts +++ b/src/testing/jest/jest-28/jest-environment.ts @@ -70,6 +70,11 @@ export function createJestPuppeteerEnvironment(): JestPuppeteerEnvironmentConstr this.browser = await connectBrowser(); } + /** + * if the user had open pages before, close them all when creating a new one + */ + await this.closeOpenPages(); + const page = await newBrowserPage(this.browser); this.pages.push(page); // during E2E tests, we can safely assume that the current environment is a `E2EProcessEnv` @@ -81,7 +86,7 @@ export function createJestPuppeteerEnvironment(): JestPuppeteerEnvironmentConstr } async closeOpenPages() { - await Promise.all(this.pages.map((page) => page.close())); + await Promise.all(this.pages.filter((page) => !page.isClosed()).map((page) => page.close())); this.pages.length = 0; } diff --git a/src/testing/jest/jest-28/jest-setup-test-framework.ts b/src/testing/jest/jest-28/jest-setup-test-framework.ts index 55628b3b662..89030126e31 100644 --- a/src/testing/jest/jest-28/jest-setup-test-framework.ts +++ b/src/testing/jest/jest-28/jest-setup-test-framework.ts @@ -34,9 +34,6 @@ export function jestSetupTestFramework() { }); afterEach(async () => { - if (global.__CLOSE_OPEN_PAGES__) { - await global.__CLOSE_OPEN_PAGES__(); - } stopAutoApplyChanges(); // Remove each node from the mocked DOM @@ -61,6 +58,12 @@ export function jestSetupTestFramework() { global.resourcesUrl = '/build'; }); + afterAll(async () => { + if (global.__CLOSE_OPEN_PAGES__) { + await global.__CLOSE_OPEN_PAGES__(); + } + }); + global.screenshotDescriptions = new Set(); // during E2E tests, we can safely assume that the current environment is a `E2EProcessEnv` diff --git a/src/testing/jest/jest-29/jest-environment.ts b/src/testing/jest/jest-29/jest-environment.ts index 3dc0daaf46c..4ac1530e380 100644 --- a/src/testing/jest/jest-29/jest-environment.ts +++ b/src/testing/jest/jest-29/jest-environment.ts @@ -70,6 +70,11 @@ export function createJestPuppeteerEnvironment(): JestPuppeteerEnvironmentConstr this.browser = await connectBrowser(); } + /** + * if the user had open pages before, close them all when creating a new one + */ + await this.closeOpenPages(); + const page = await newBrowserPage(this.browser); this.pages.push(page); // during E2E tests, we can safely assume that the current environment is a `E2EProcessEnv` @@ -81,7 +86,7 @@ export function createJestPuppeteerEnvironment(): JestPuppeteerEnvironmentConstr } async closeOpenPages() { - await Promise.all(this.pages.map((page) => page.close())); + await Promise.all(this.pages.filter((page) => !page.isClosed()).map((page) => page.close())); this.pages.length = 0; } diff --git a/src/testing/jest/jest-29/jest-setup-test-framework.ts b/src/testing/jest/jest-29/jest-setup-test-framework.ts index 55628b3b662..89030126e31 100644 --- a/src/testing/jest/jest-29/jest-setup-test-framework.ts +++ b/src/testing/jest/jest-29/jest-setup-test-framework.ts @@ -34,9 +34,6 @@ export function jestSetupTestFramework() { }); afterEach(async () => { - if (global.__CLOSE_OPEN_PAGES__) { - await global.__CLOSE_OPEN_PAGES__(); - } stopAutoApplyChanges(); // Remove each node from the mocked DOM @@ -61,6 +58,12 @@ export function jestSetupTestFramework() { global.resourcesUrl = '/build'; }); + afterAll(async () => { + if (global.__CLOSE_OPEN_PAGES__) { + await global.__CLOSE_OPEN_PAGES__(); + } + }); + global.screenshotDescriptions = new Set(); // during E2E tests, we can safely assume that the current environment is a `E2EProcessEnv` diff --git a/src/testing/puppeteer/puppeteer-element.ts b/src/testing/puppeteer/puppeteer-element.ts index b7fb74a31cc..3e767715621 100644 --- a/src/testing/puppeteer/puppeteer-element.ts +++ b/src/testing/puppeteer/puppeteer-element.ts @@ -527,6 +527,14 @@ export class E2EElement extends MockHTMLElement implements pd.E2EElementInternal const rootElm = frag.firstElementChild; + /** + * in case the user called `newE2EPage` without any content `rootElm` will be undefined + * and further operations will fail. We need to check for this case and return early. + */ + if (!rootElm) { + return; + } + this.nodeName = rootElm.nodeName; this.attributes = cloneAttributes(rootElm.attributes); diff --git a/test/end-to-end/src/miscellaneous/test.e2e.ts b/test/end-to-end/src/miscellaneous/test.e2e.ts new file mode 100644 index 00000000000..73508a7e42e --- /dev/null +++ b/test/end-to-end/src/miscellaneous/test.e2e.ts @@ -0,0 +1,19 @@ +import { type E2EPage, newE2EPage } from '@stencil/core/testing'; + +describe('do not throw page already closed if page was defined in before(All) hook', () => { + let page: E2EPage; + + beforeAll(async () => { + page = await newE2EPage(); + }); + + it('first test', async () => { + const p = await page.find('html'); + expect(p).not.toBeNull(); + }); + + it('second test', async () => { + const p = await page.find('html'); + expect(p).not.toBeNull(); + }); +});