From 3a9b29f46c98c1ede67ce64ee3d04a21595c76e8 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 11 Jul 2022 12:54:05 -0800 Subject: [PATCH] feat(ct-vue): allow configuring apps per test (#15538) --- .../playwright-ct-react/registerSource.mjs | 2 +- .../playwright-ct-svelte/registerSource.mjs | 2 +- packages/playwright-ct-vue/.npmignore | 2 ++ packages/playwright-ct-vue/hooks.d.ts | 19 ++++++++++++++++ packages/playwright-ct-vue/hooks.mjs | 22 +++++++++++++++++++ packages/playwright-ct-vue/index.d.ts | 1 + packages/playwright-ct-vue/package.json | 4 ++++ packages/playwright-ct-vue/registerSource.mjs | 6 ++++- .../playwright-ct-vue2/registerSource.mjs | 2 +- packages/playwright-test/src/mount.ts | 2 +- packages/playwright-test/types/component.d.ts | 2 +- .../ct-vue-vite/playwright/index.js | 5 +++++ .../ct-vue-vite/src/notation-vue.spec.ts | 14 ++++++++++++ 13 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 packages/playwright-ct-vue/hooks.d.ts create mode 100644 packages/playwright-ct-vue/hooks.mjs diff --git a/packages/playwright-ct-react/registerSource.mjs b/packages/playwright-ct-react/registerSource.mjs index 4aa0c99423..88588c60ae 100644 --- a/packages/playwright-ct-react/registerSource.mjs +++ b/packages/playwright-ct-react/registerSource.mjs @@ -68,6 +68,6 @@ function render(component) { })); } -window.playwrightMount = component => { +window.playwrightMount = async component => { ReactDOM.render(render(component), document.getElementById('root')); }; diff --git a/packages/playwright-ct-svelte/registerSource.mjs b/packages/playwright-ct-svelte/registerSource.mjs index f3635fbbf4..21305231f3 100644 --- a/packages/playwright-ct-svelte/registerSource.mjs +++ b/packages/playwright-ct-svelte/registerSource.mjs @@ -32,7 +32,7 @@ export function register(components) { registry.set(name, value); } -window.playwrightMount = (component, rootElement) => { +window.playwrightMount = async (component, rootElement) => { let componentCtor = registry.get(component.type); if (!componentCtor) { // Lookup by shorthand. diff --git a/packages/playwright-ct-vue/.npmignore b/packages/playwright-ct-vue/.npmignore index 5aac845c35..dd4553cbc5 100644 --- a/packages/playwright-ct-vue/.npmignore +++ b/packages/playwright-ct-vue/.npmignore @@ -7,3 +7,5 @@ !registerSource.mjs !index.d.ts !index.js +!hooks.d.ts +!hooks.mjs diff --git a/packages/playwright-ct-vue/hooks.d.ts b/packages/playwright-ct-vue/hooks.d.ts new file mode 100644 index 0000000000..5076dfb06f --- /dev/null +++ b/packages/playwright-ct-vue/hooks.d.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { App } from 'vue'; + +export declare function onApp(callback: (app: App, appConfig: any) => Promise): void; diff --git a/packages/playwright-ct-vue/hooks.mjs b/packages/playwright-ct-vue/hooks.mjs new file mode 100644 index 0000000000..b050f74957 --- /dev/null +++ b/packages/playwright-ct-vue/hooks.mjs @@ -0,0 +1,22 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const __pw_hooks_on_app = []; +window.__pw_hooks_on_app = __pw_hooks_on_app; + +export const onApp = callback => { + __pw_hooks_on_app.push(callback); +}; diff --git a/packages/playwright-ct-vue/index.d.ts b/packages/playwright-ct-vue/index.d.ts index 4a56ae3fea..386da99ded 100644 --- a/packages/playwright-ct-vue/index.d.ts +++ b/packages/playwright-ct-vue/index.d.ts @@ -40,6 +40,7 @@ interface ComponentFixtures { props?: Props, slots?: { [key: string]: any }, on?: { [key: string]: Function }, + appConfig?: any, }): Promise; } diff --git a/packages/playwright-ct-vue/package.json b/packages/playwright-ct-vue/package.json index 07c696625f..a7cce5d668 100644 --- a/packages/playwright-ct-vue/package.json +++ b/packages/playwright-ct-vue/package.json @@ -19,6 +19,10 @@ "./register": { "types": "./register.d.ts", "default": "./register.mjs" + }, + "./hooks": { + "types": "./hooks.d.ts", + "default": "./hooks.mjs" } }, "dependencies": { diff --git a/packages/playwright-ct-vue/registerSource.mjs b/packages/playwright-ct-vue/registerSource.mjs index bee6349cb8..6d6fe85a46 100644 --- a/packages/playwright-ct-vue/registerSource.mjs +++ b/packages/playwright-ct-vue/registerSource.mjs @@ -155,10 +155,14 @@ function createDevTools() { }; } -window.playwrightMount = (component, rootElement) => { +window.playwrightMount = async (component, rootElement) => { const app = createApp({ render: () => render(component) }); setDevtoolsHook(createDevTools(), {}); + if (component.kind === 'object') { + for (const onAppCallback of /** @type {any} */(window).__pw_hooks_on_app || []) + await onAppCallback(app, /** @type {any} */(component.options)?.appConfig) + } app.mount(rootElement); }; diff --git a/packages/playwright-ct-vue2/registerSource.mjs b/packages/playwright-ct-vue2/registerSource.mjs index 83a7313c97..052a4c1f20 100644 --- a/packages/playwright-ct-vue2/registerSource.mjs +++ b/packages/playwright-ct-vue2/registerSource.mjs @@ -134,7 +134,7 @@ function render(component, h) { return wrapper; } -window.playwrightMount = (component, rootElement) => { +window.playwrightMount = async (component, rootElement) => { const mounted = new Vue({ render: h => render(component, h), }).$mount(); diff --git a/packages/playwright-test/src/mount.ts b/packages/playwright-test/src/mount.ts index 53970a8f04..ec95796084 100644 --- a/packages/playwright-test/src/mount.ts +++ b/packages/playwright-test/src/mount.ts @@ -110,7 +110,7 @@ async function innerMount(page: Page, jsxOrType: JsxComponent | string, options: document.body.appendChild(rootElement); } - window.playwrightMount(component, rootElement); + await window.playwrightMount(component, rootElement); // When mounting fragments, return selector pointing to the root element. return rootElement.childNodes.length > 1 ? '#root' : '#root > *'; diff --git a/packages/playwright-test/types/component.d.ts b/packages/playwright-test/types/component.d.ts index fa0b0812b8..dfabc6d867 100644 --- a/packages/playwright-test/types/component.d.ts +++ b/packages/playwright-test/types/component.d.ts @@ -37,6 +37,6 @@ export type Component = JsxComponent | ObjectComponent; declare global { interface Window { - playwrightMount(component: Component, rootElement: Element): void; + playwrightMount(component: Component, rootElement: Element): Promise; } } diff --git a/tests/components/ct-vue-vite/playwright/index.js b/tests/components/ct-vue-vite/playwright/index.js index e69de29bb2..3fd36c7d6f 100644 --- a/tests/components/ct-vue-vite/playwright/index.js +++ b/tests/components/ct-vue-vite/playwright/index.js @@ -0,0 +1,5 @@ +import { onApp } from '@playwright/experimental-ct-vue/hooks'; + +onApp(async (app, addConfig) => { + console.log(`App ${!!app} configured with config: ${JSON.stringify(addConfig)}`); +}); diff --git a/tests/components/ct-vue-vite/src/notation-vue.spec.ts b/tests/components/ct-vue-vite/src/notation-vue.spec.ts index e1b706dcc9..8663b410aa 100644 --- a/tests/components/ct-vue-vite/src/notation-vue.spec.ts +++ b/tests/components/ct-vue-vite/src/notation-vue.spec.ts @@ -66,3 +66,17 @@ test('optionless should work', async ({ mount }) => { const component = await mount(Component) await expect(component).toContainText('test') }) + +test('should configure app', async ({ page, mount }) => { + const messages = [] + page.on('console', m => messages.push(m.text())) + const component = await mount(Button, { + props: { + title: 'Submit' + }, + appConfig: { + route: 'A' + } + }) + expect(messages).toEqual(['App true configured with config: {\"route\":\"A\"}']) +})