From 0c9e0d22df10fd2ebd590d127a1e12ab77c94473 Mon Sep 17 00:00:00 2001 From: Ross Wollman Date: Tue, 10 May 2022 11:45:47 -0700 Subject: [PATCH] fix(ct): preserve context changes (#13986) 1. add test (and fix) using context fixture with mount 2. add test for innerText that was failing prior to https://github.com/microsoft/playwright/pull/14008 --- packages/playwright-test/src/mount.ts | 22 +++++++------- .../ct-react/src/DelayedData.spec.tsx | 7 +++++ tests/components/ct-react/src/DelayedData.tsx | 14 +++++++++ tests/components/ct-react/src/Fetch.spec.tsx | 30 +++++++++++++++++++ tests/components/ct-react/src/Fetch.tsx | 9 ++++++ 5 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 tests/components/ct-react/src/DelayedData.spec.tsx create mode 100644 tests/components/ct-react/src/DelayedData.tsx create mode 100644 tests/components/ct-react/src/Fetch.spec.tsx create mode 100644 tests/components/ct-react/src/Fetch.tsx diff --git a/packages/playwright-test/src/mount.ts b/packages/playwright-test/src/mount.ts index c3d8316837..15948df22f 100644 --- a/packages/playwright-test/src/mount.ts +++ b/packages/playwright-test/src/mount.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Fixtures, Locator, Page, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, ViewportSize } from './types'; +import type { Fixtures, Locator, Page, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs } from './types'; let boundCallbacksForMount: Function[] = []; @@ -35,14 +35,20 @@ export const fixtures: Fixtures { + page: async ({ _workerPage, viewport }, use) => { + const page = _workerPage; + await page.goto('about:blank'); + await (page as any)._resetForReuse(); + await (page.context() as any)._resetForReuse(); + await page.setViewportSize(viewport || { width: 1280, height: 800 }); + await page.goto(process.env.PLAYWRIGHT_VITE_COMPONENTS_BASE_URL!); await use(_workerPage); }, - mount: async ({ page, viewport }, use) => { + mount: async ({ page }, use) => { await use(async (component, options) => { const selector = await (page as any)._wrapApiCall(async () => { - return await innerMount(page, component, options, viewport || { width: 1280, height: 800 }); + return await innerMount(page, component, options); }, true); return page.locator(selector); }); @@ -50,13 +56,7 @@ export const fixtures: Fixtures { - await page.goto('about:blank'); - await (page as any)._resetForReuse(); - await (page.context() as any)._resetForReuse(); - await page.setViewportSize(viewport); - await page.goto(process.env.PLAYWRIGHT_VITE_COMPONENTS_BASE_URL!); - +async function innerMount(page: Page, jsxOrType: any, options: any): Promise { let component; if (typeof jsxOrType === 'string') component = { kind: 'object', type: jsxOrType, options }; diff --git a/tests/components/ct-react/src/DelayedData.spec.tsx b/tests/components/ct-react/src/DelayedData.spec.tsx new file mode 100644 index 0000000000..99e6f637ac --- /dev/null +++ b/tests/components/ct-react/src/DelayedData.spec.tsx @@ -0,0 +1,7 @@ +import { test, expect } from '@playwright/experimental-ct-vue' +import { DelayedData } from './DelayedData'; + +test('toHaveText works on delayed data', async ({ mount }) => { + const component = await mount(); + await expect(component).toHaveText('complete'); +}); diff --git a/tests/components/ct-react/src/DelayedData.tsx b/tests/components/ct-react/src/DelayedData.tsx new file mode 100644 index 0000000000..5eb7cb21f5 --- /dev/null +++ b/tests/components/ct-react/src/DelayedData.tsx @@ -0,0 +1,14 @@ +import React, { useEffect, useState } from 'react'; + +export const DelayedData: React.FC<{ data: string }> = ({ data }) => { + const [status, setStatus] = useState('loading'); + + useEffect(() => { + const timeout = setTimeout(() => setStatus(data), 500); + return () => { + clearTimeout(timeout); + } + }, [data]) + + return

{status}

+}; diff --git a/tests/components/ct-react/src/Fetch.spec.tsx b/tests/components/ct-react/src/Fetch.spec.tsx new file mode 100644 index 0000000000..66d97b7356 --- /dev/null +++ b/tests/components/ct-react/src/Fetch.spec.tsx @@ -0,0 +1,30 @@ +import { test as _test, expect } from '@playwright/experimental-ct-vue' +import { Fetch } from './Fetch'; +import { serverFixtures } from '../../../../tests/config/serverFixtures'; + +const test = _test.extend(serverFixtures); + +test('components routing should go through context', async ({ mount, context, server }) => { + server.setRoute('/hello', (req, res) => { + res.write('served via server'); + res.end(); + }); + + let markRouted: (url: string) => void; + const routedViaContext = new Promise(res => markRouted = res); + await context.route('**/hello', async (route, request) => { + markRouted(`${request.method()} ${request.url()}`); + await route.fulfill({ + body: 'intercepted', + }); + }); + + const whoServedTheRequest = Promise.race([ + server.waitForRequest('/hello').then((req) => `served via server: ${req.method} ${req.url}`), + routedViaContext.then(req => `served via context: ${req}`), + ]); + + const component = await mount(); + await expect.soft(whoServedTheRequest).resolves.toMatch(/served via context: GET.*\/hello.*/i); + await expect.soft(component).toHaveText('intercepted'); +}); diff --git a/tests/components/ct-react/src/Fetch.tsx b/tests/components/ct-react/src/Fetch.tsx new file mode 100644 index 0000000000..06cf76f20f --- /dev/null +++ b/tests/components/ct-react/src/Fetch.tsx @@ -0,0 +1,9 @@ +import React, { useEffect, useState } from 'react'; + +export const Fetch: React.FC<{ url: string }> = ({ url }) => { + const [data, setData] = useState('no response yet'); + useEffect(() => { + fetch(url).then(res => res.text()).then(setData); + }, [url]); + return

{data}

; +}