mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(ct): multi root vue components (#16211)
This commit is contained in:
parent
2fa48483af
commit
bd5eddd62e
@ -78,7 +78,7 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||||||
await hook({ hooksConfig });
|
await hook({ hooksConfig });
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUnmount = async (element, rootElement) => {
|
window.playwrightUnmount = async rootElement => {
|
||||||
if (!ReactDOM.unmountComponentAtNode(rootElement))
|
if (!ReactDOM.unmountComponentAtNode(rootElement))
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
};
|
};
|
||||||
|
@ -68,7 +68,7 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||||||
svelteComponent.$on(key, event => listener(event.detail));
|
svelteComponent.$on(key, event => listener(event.detail));
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUnmount = async (element, rootElement) => {
|
window.playwrightUnmount = async rootElement => {
|
||||||
const svelteComponent = /** @type {SvelteComponent} */ (rootElement[svelteComponentKey]);
|
const svelteComponent = /** @type {SvelteComponent} */ (rootElement[svelteComponentKey]);
|
||||||
if (!svelteComponent)
|
if (!svelteComponent)
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
|
@ -168,21 +168,22 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||||||
for (const hook of /** @type {any} */(window).__pw_hooks_before_mount || [])
|
for (const hook of /** @type {any} */(window).__pw_hooks_before_mount || [])
|
||||||
await hook({ app, hooksConfig });
|
await hook({ app, hooksConfig });
|
||||||
const instance = app.mount(rootElement);
|
const instance = app.mount(rootElement);
|
||||||
instance.$el[appKey] = app;
|
rootElement[appKey] = app;
|
||||||
instance.$el[componentKey] = wrapper;
|
rootElement[componentKey] = wrapper;
|
||||||
|
|
||||||
for (const hook of /** @type {any} */(window).__pw_hooks_after_mount || [])
|
for (const hook of /** @type {any} */(window).__pw_hooks_after_mount || [])
|
||||||
await hook({ app, hooksConfig, instance });
|
await hook({ app, hooksConfig, instance });
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUnmount = async element => {
|
window.playwrightUnmount = async rootElement => {
|
||||||
const app = /** @type {import('vue').App} */ (element[appKey]);
|
const app = /** @type {import('vue').App} */ (rootElement[appKey]);
|
||||||
if (!app)
|
if (!app)
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
app.unmount();
|
app.unmount();
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightRerender = async (element, options) => {
|
window.playwrightRerender = async (rootElement, options) => {
|
||||||
const component = element[componentKey].component;
|
const component = rootElement[componentKey].component;
|
||||||
if (!component)
|
if (!component)
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
|
|
||||||
|
@ -134,6 +134,8 @@ function render(component, h) {
|
|||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const instanceKey = Symbol('instanceKey');
|
||||||
|
|
||||||
window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
||||||
for (const hook of /** @type {any} */(window).__pw_hooks_before_mount || [])
|
for (const hook of /** @type {any} */(window).__pw_hooks_before_mount || [])
|
||||||
await hook({ hooksConfig });
|
await hook({ hooksConfig });
|
||||||
@ -142,18 +144,16 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||||||
render: h => render(component, h),
|
render: h => render(component, h),
|
||||||
}).$mount();
|
}).$mount();
|
||||||
rootElement.appendChild(instance.$el);
|
rootElement.appendChild(instance.$el);
|
||||||
/** @type {any} */ (instance.$el)[instanceKey] = instance;
|
/** @type {any} */ (rootElement)[instanceKey] = instance;
|
||||||
|
|
||||||
for (const hook of /** @type {any} */(window).__pw_hooks_after_mount || [])
|
for (const hook of /** @type {any} */(window).__pw_hooks_after_mount || [])
|
||||||
await hook({ hooksConfig, instance });
|
await hook({ hooksConfig, instance });
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUnmount = async element => {
|
window.playwrightUnmount = async rootElement => {
|
||||||
const component = /** @type {any} */(element)[instanceKey];
|
const component = /** @type {any} */(rootElement)[instanceKey];
|
||||||
if (!component)
|
if (!component)
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
component.$destroy();
|
component.$destroy();
|
||||||
element.remove();
|
component.$el.remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
const instanceKey = Symbol('instanceKey');
|
|
||||||
|
@ -55,14 +55,15 @@ export const fixtures: Fixtures<
|
|||||||
const locator = page.locator(selector);
|
const locator = page.locator(selector);
|
||||||
return Object.assign(locator, {
|
return Object.assign(locator, {
|
||||||
unmount: async () => {
|
unmount: async () => {
|
||||||
await locator.evaluate(async element => {
|
await locator.evaluate(async () => {
|
||||||
const rootElement = document.getElementById('root')!;
|
const rootElement = document.getElementById('root')!;
|
||||||
await window.playwrightUnmount(element, rootElement);
|
await window.playwrightUnmount(rootElement);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
rerender: async (options: Omit<MountOptions, 'hooksConfig'>) => {
|
rerender: async (options: Omit<MountOptions, 'hooksConfig'>) => {
|
||||||
await locator.evaluate(async (element, options) => {
|
await locator.evaluate(async (element, options) => {
|
||||||
return await window.playwrightRerender(element, options);
|
const rootElement = document.getElementById('root')!;
|
||||||
|
return await window.playwrightRerender(rootElement, options);
|
||||||
}, options);
|
}, options);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -39,7 +39,7 @@ export type Component = JsxComponent | ObjectComponent;
|
|||||||
declare global {
|
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(rootElement: Element): Promise<void>;
|
||||||
playwrightRerender(element: Element, props: Omit<MountOptions, 'hooksConfig'>): Promise<void>;
|
playwrightRerender(rootElement: Element, options: Omit<MountOptions, 'hooksConfig'>): Promise<void>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
<template>
|
||||||
|
<div>root 1</div>
|
||||||
|
<div>root 2</div>
|
||||||
|
</template>
|
@ -3,6 +3,7 @@ import Button from './components/Button.vue'
|
|||||||
import Counter from './components/Counter.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 MultiRoot from './components/MultiRoot.vue'
|
||||||
|
|
||||||
test.use({ viewport: { width: 500, height: 500 } })
|
test.use({ viewport: { width: 500, height: 500 } })
|
||||||
|
|
||||||
@ -83,3 +84,15 @@ test('should run hooks', async ({ page, mount }) => {
|
|||||||
})
|
})
|
||||||
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'])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('unmount a multi root component should work', async ({ mount, page }) => {
|
||||||
|
const component = await mount(<MultiRoot />)
|
||||||
|
|
||||||
|
await expect(page.locator('#root')).toContainText('root 1')
|
||||||
|
await expect(page.locator('#root')).toContainText('root 2')
|
||||||
|
|
||||||
|
await component.unmount()
|
||||||
|
|
||||||
|
await expect(page.locator('#root')).not.toContainText('root 1')
|
||||||
|
await expect(page.locator('#root')).not.toContainText('root 2')
|
||||||
|
})
|
||||||
|
@ -2,6 +2,7 @@ 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 Counter from './components/Counter.vue'
|
||||||
import DefaultSlot from './components/DefaultSlot.vue'
|
import DefaultSlot from './components/DefaultSlot.vue'
|
||||||
|
import MultiRoot from './components/MultiRoot.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'
|
||||||
|
|
||||||
@ -96,3 +97,15 @@ test('should run hooks', async ({ page, mount }) => {
|
|||||||
})
|
})
|
||||||
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'])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('unmount a multi root component should work', async ({ mount, page }) => {
|
||||||
|
const component = await mount(MultiRoot)
|
||||||
|
|
||||||
|
await expect(page.locator('#root')).toContainText('root 1')
|
||||||
|
await expect(page.locator('#root')).toContainText('root 2')
|
||||||
|
|
||||||
|
await component.unmount()
|
||||||
|
|
||||||
|
await expect(page.locator('#root')).not.toContainText('root 1')
|
||||||
|
await expect(page.locator('#root')).not.toContainText('root 2')
|
||||||
|
})
|
||||||
|
@ -4,6 +4,7 @@ import Button from './components/Button.vue'
|
|||||||
import Counter from './components/Counter.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 MultiRoot from './components/MultiRoot.vue'
|
||||||
import Component from './components/Component.vue'
|
import Component from './components/Component.vue'
|
||||||
|
|
||||||
test.use({ viewport: { width: 500, height: 500 } })
|
test.use({ viewport: { width: 500, height: 500 } })
|
||||||
@ -107,3 +108,15 @@ test('should unmount', async ({ page, mount }) => {
|
|||||||
await component.unmount();
|
await component.unmount();
|
||||||
await expect(page.locator('#root')).not.toContainText('Submit');
|
await expect(page.locator('#root')).not.toContainText('Submit');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount a multi root component should work', async ({ mount, page }) => {
|
||||||
|
const component = await mount(MultiRoot)
|
||||||
|
|
||||||
|
await expect(page.locator('#root')).toContainText('root 1')
|
||||||
|
await expect(page.locator('#root')).toContainText('root 2')
|
||||||
|
|
||||||
|
await component.unmount()
|
||||||
|
|
||||||
|
await expect(page.locator('#root')).not.toContainText('root 1')
|
||||||
|
await expect(page.locator('#root')).not.toContainText('root 2')
|
||||||
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user