chore(ct): change setProps to rerender (#16204)

This commit is contained in:
sand4rt 2022-08-04 03:14:00 +02:00 committed by GitHub
parent e4efc300c7
commit e5cc78af67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 91 additions and 54 deletions

View File

@ -34,25 +34,22 @@ export type PlaywrightTestConfig = Omit<BasePlaywrightTestConfig, 'use'> & {
} }
}; };
interface MountResult<Props = { [key: string]: any }> extends Locator { export interface MountOptions<Props = Record<string, unknown>> {
props?: Props,
slots?: Record<string, unknown>,
on?: Record<string, Function>,
hooksConfig?: any,
}
interface MountResult<Props = Record<string, unknown>> extends Locator {
unmount(): Promise<void>; unmount(): Promise<void>;
setProps(props: Partial<Props>): Promise<void> rerender(options: { props: Props }): Promise<void>
} }
export interface ComponentFixtures { export interface ComponentFixtures {
mount(component: JSX.Element): Promise<MountResult>; mount(component: JSX.Element): Promise<MountResult>;
mount(component: any, options?: { mount(component: any, options?: MountOptions): Promise<MountResult>;
props?: { [key: string]: any }, mount<Props>(component: any, options: MountOptions<Required<Props>>): Promise<MountResult<Props>>;
slots?: { [key: string]: any },
on?: { [key: string]: Function },
hooksConfig?: any,
}): Promise<MountResult>;
mount<Props>(component: any, options: {
props: Props,
slots?: { [key: string]: any },
on?: { [key: string]: Function },
hooksConfig?: any,
}): Promise<MountResult<Props>>;
} }
export const test: TestType< export const test: TestType<

View File

@ -181,11 +181,11 @@ window.playwrightUnmount = async element => {
app.unmount(); app.unmount();
}; };
window.playwrightSetProps = async (element, props) => { window.playwrightRerender = async (element, options) => {
const component = element[componentKey].component; const component = element[componentKey].component;
if (!component) if (!component)
throw new Error('Component was not mounted'); throw new Error('Component was not mounted');
for (const [key, value] of Object.entries(props)) for (const [key, value] of Object.entries(options.props || {}))
component.props[key] = value; component.props[key] = value;
}; };

View File

@ -15,13 +15,13 @@
*/ */
import type { Fixtures, Locator, Page, BrowserContextOptions, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, BrowserContext } from './types'; import type { Fixtures, Locator, Page, BrowserContextOptions, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, BrowserContext } from './types';
import type { Component, JsxComponent, ObjectComponentOptions } from '../types/component'; import type { Component, JsxComponent, MountOptions } from '../types/component';
let boundCallbacksForMount: Function[] = []; let boundCallbacksForMount: Function[] = [];
interface MountResult extends Locator { interface MountResult extends Locator {
unmount: (locator: Locator) => Promise<void>; unmount(locator: Locator): Promise<void>;
setProps: (props: { [key: string]: any }) => Promise<void>; rerender(options: Omit<MountOptions, 'hooksConfig'>): Promise<void>;
} }
export const fixtures: Fixtures< export const fixtures: Fixtures<
@ -48,7 +48,7 @@ export const fixtures: Fixtures<
}, },
mount: async ({ page }, use) => { mount: async ({ page }, use) => {
await use(async (component: JsxComponent | string, options?: ObjectComponentOptions) => { await use(async (component: JsxComponent | string, options?: MountOptions) => {
const selector = await (page as any)._wrapApiCall(async () => { const selector = await (page as any)._wrapApiCall(async () => {
return await innerMount(page, component, options); return await innerMount(page, component, options);
}, true); }, true);
@ -60,10 +60,10 @@ export const fixtures: Fixtures<
await window.playwrightUnmount(element, rootElement); await window.playwrightUnmount(element, rootElement);
}); });
}, },
setProps: async (props: { [key: string]: any }) => { rerender: async (options: Omit<MountOptions, 'hooksConfig'>) => {
await locator.evaluate(async (element, props) => { await locator.evaluate(async (element, options) => {
return await window.playwrightSetProps(element, props); return await window.playwrightRerender(element, options);
}, props); }, options);
} }
}); });
}); });
@ -71,7 +71,7 @@ export const fixtures: Fixtures<
}, },
}; };
async function innerMount(page: Page, jsxOrType: JsxComponent | string, options: ObjectComponentOptions = {}): Promise<string> { async function innerMount(page: Page, jsxOrType: JsxComponent | string, options: MountOptions = {}): Promise<string> {
let component: Component; let component: Component;
if (typeof jsxOrType === 'string') if (typeof jsxOrType === 'string')
component = { kind: 'object', type: jsxOrType, options }; component = { kind: 'object', type: jsxOrType, options };

View File

@ -17,13 +17,13 @@
export type JsxComponent = { export type JsxComponent = {
kind: 'jsx', kind: 'jsx',
type: string, type: string,
props: {[key: string]: any}, props: Record<string, any>,
children: (Component | string)[], children: (Component | string)[],
}; };
export type ObjectComponentOptions = { export type MountOptions = {
props?: { [key: string]: any }, props?: Record<string, any>,
slots?: { [key: string]: any }, slots?: Record<string, any>,
on?: { [key: string]: Function }, on?: { [key: string]: Function },
hooksConfig?: any, hooksConfig?: any,
}; };
@ -31,7 +31,7 @@ export type ObjectComponentOptions = {
export type ObjectComponent = { export type ObjectComponent = {
kind: 'object', kind: 'object',
type: string, type: string,
options?: ObjectComponentOptions options?: MountOptions
}; };
export type Component = JsxComponent | ObjectComponent; export type Component = JsxComponent | ObjectComponent;
@ -40,6 +40,6 @@ declare global {
interface Window { interface Window {
playwrightMount(component: Component, rootElement: Element, hooksConfig: any): Promise<void>; playwrightMount(component: Component, rootElement: Element, hooksConfig: any): Promise<void>;
playwrightUnmount(element: Element, rootElement: Element): Promise<void>; playwrightUnmount(element: Element, rootElement: Element): Promise<void>;
playwrightSetProps(element: Element, props: { [key: string]: any }): Promise<void>; playwrightRerender(element: Element, props: Omit<MountOptions, 'hooksConfig'>): Promise<void>;
} }
} }

View File

@ -3,9 +3,6 @@ defineProps({
title: { title: {
type: String, type: String,
required: true required: true
},
emits: {
submit: null,
} }
}) })
</script> </script>

View File

@ -0,0 +1,21 @@
<template>
<div>
<span id="remount-count">{{ remountCount }}</span>
<span id="rerender-count">{{ count }}</span>
</div>
</template>
<script>
let remountCount = 0
</script>
<script setup>
defineProps({
count: {
type: Number,
required: true
}
})
remountCount++
</script>

View File

@ -1,20 +1,27 @@
import { test, expect } from '@playwright/experimental-ct-vue' import { test, expect } from '@playwright/experimental-ct-vue'
import Button from './components/Button.vue' import Button from './components/Button.vue'
import Counter from './components/Counter.vue'
import DefaultSlot from './components/DefaultSlot.vue' import DefaultSlot from './components/DefaultSlot.vue'
import NamedSlots from './components/NamedSlots.vue' import NamedSlots from './components/NamedSlots.vue'
test.use({ viewport: { width: 500, height: 500 } }) test.use({ viewport: { width: 500, height: 500 } })
test('props should work', async ({ mount }) => { test('props should work', async ({ mount }) => {
const component = await mount(<Button title='Submit'></Button>) const component = await mount(<Button title="Submit" />)
await expect(component).toContainText('Submit') await expect(component).toContainText('Submit')
}) })
test('update props should work', async ({ mount }) => { test('renderer and keep the component instance intact', async ({ mount }) => {
const component = await mount(<Button title='Submit'></Button>); const component = await mount(<Counter count={9001} />);
await expect(component).toContainText('Submit'); await expect(component.locator('#rerender-count')).toContainText('9001')
await component.setProps({ title: 'Loading' });
await expect(component).toContainText('Loading'); await component.rerender({ props: { count: 1337 } })
await expect(component.locator('#rerender-count')).toContainText('1337')
await component.rerender({ props: { count: 42 } })
await expect(component.locator('#rerender-count')).toContainText('42')
await expect(component.locator('#remount-count')).toContainText('1')
}) })
test('event should work', async ({ mount }) => { test('event should work', async ({ mount }) => {
@ -71,7 +78,7 @@ test('slot should emit events', async ({ mount }) => {
test('should run hooks', async ({ page, mount }) => { test('should run hooks', async ({ page, mount }) => {
const messages = [] const messages = []
page.on('console', m => messages.push(m.text())) page.on('console', m => messages.push(m.text()))
await mount(<Button title='Submit'></Button>, { await mount(<Button title="Submit" />, {
hooksConfig: { route: 'A' } hooksConfig: { route: 'A' }
}) })
expect(messages).toEqual(['Before mount: {\"route\":\"A\"}, app: true', 'After mount el: HTMLButtonElement']) expect(messages).toEqual(['Before mount: {\"route\":\"A\"}, app: true', 'After mount el: HTMLButtonElement'])

View File

@ -1,5 +1,6 @@
import { test, expect } from '@playwright/experimental-ct-vue' import { test, expect } from '@playwright/experimental-ct-vue'
import Button from './components/Button.vue' import Button from './components/Button.vue'
import Counter from './components/Counter.vue'
import DefaultSlot from './components/DefaultSlot.vue' import DefaultSlot from './components/DefaultSlot.vue'
import NamedSlots from './components/NamedSlots.vue' import NamedSlots from './components/NamedSlots.vue'
import Component from './components/Component.vue' import Component from './components/Component.vue'
@ -15,17 +16,24 @@ test('props should work', async ({ mount }) => {
await expect(component).toContainText('Submit') await expect(component).toContainText('Submit')
}) })
test('update props should work', async ({ mount }) => { test('renderer and keep the component instance intact', async ({ mount }) => {
const component = await mount(Button, { const component = await mount(Counter, {
props: { props: {
title: 'Submit' count: 9001
} }
}); });
await expect(component).toContainText('Submit'); await expect(component.locator('#rerender-count')).toContainText('9001')
await component.setProps({ title: 'Loading' });
await expect(component).toContainText('Loading'); await component.rerender({ props: { count: 1337 } })
await expect(component.locator('#rerender-count')).toContainText('1337')
await component.rerender({ props: { count: 42 } })
await expect(component.locator('#rerender-count')).toContainText('42')
await expect(component.locator('#remount-count')).toContainText('1')
}) })
test('event should work', async ({ mount }) => { test('event should work', async ({ mount }) => {
const messages = [] const messages = []
const component = await mount(Button, { const component = await mount(Button, {

View File

@ -1,6 +1,7 @@
import { test, expect } from '@playwright/experimental-ct-vue' import { test, expect } from '@playwright/experimental-ct-vue'
import Button from './components/Button.vue' import Button from './components/Button.vue'
import Counter from './components/Counter.vue'
import DefaultSlot from './components/DefaultSlot.vue' import DefaultSlot from './components/DefaultSlot.vue'
import NamedSlots from './components/NamedSlots.vue' import NamedSlots from './components/NamedSlots.vue'
import Component from './components/Component.vue' import Component from './components/Component.vue'
@ -16,15 +17,21 @@ test('props should work', async ({ mount }) => {
await expect(component).toContainText('Submit') await expect(component).toContainText('Submit')
}) })
test('update props should work', async ({ mount }) => { test('renderer and keep the component instance intact', async ({ mount }) => {
const component = await mount(Button, { const component = await mount<{ count: number }>(Counter, {
props: { props: {
title: 'Submit' count: 9001
} }
}); });
await expect(component).toContainText('Submit') await expect(component.locator('#rerender-count')).toContainText('9001')
await component.setProps({ title: 'Loading' })
await expect(component).toContainText('Loading') await component.rerender({ props: { count: 1337 } })
await expect(component.locator('#rerender-count')).toContainText('1337')
await component.rerender({ props: { count: 42 } })
await expect(component.locator('#rerender-count')).toContainText('42')
await expect(component.locator('#remount-count')).toContainText('1')
}) })
test('event should work', async ({ mount }) => { test('event should work', async ({ mount }) => {