feat(svelte): add support for svelte5
This commit is contained in:
parent
0bb5925d0d
commit
b1659fb42c
4262
package-lock.json
generated
4262
package-lock.json
generated
File diff suppressed because it is too large
Load diff
35
packages/playwright-ct-svelte/index.d.ts
vendored
35
packages/playwright-ct-svelte/index.d.ts
vendored
|
|
@ -14,33 +14,50 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { SvelteComponent, ComponentProps } from 'svelte/types/runtime';
|
||||
import type {
|
||||
SvelteComponent as V4Component,
|
||||
Component as V5Component,
|
||||
ComponentProps
|
||||
} from 'svelte/types/runtime';
|
||||
import type { TestType, Locator } from '@playwright/experimental-ct-core';
|
||||
|
||||
type ComponentSlot = string | string[];
|
||||
type ComponentSlots = Record<string, ComponentSlot> & { default?: ComponentSlot };
|
||||
type ComponentEvents = Record<string, Function>;
|
||||
|
||||
export interface MountOptions<HooksConfig, Component extends SvelteComponent> {
|
||||
props?: ComponentProps<Component>;
|
||||
export interface MountOptions<
|
||||
HooksConfig,
|
||||
Component extends (new (...args: any[]) => V4Component) | V5Component
|
||||
> {
|
||||
props?: ComponentProps<InstanceType<Component>>;
|
||||
slots?: ComponentSlots;
|
||||
on?: ComponentEvents;
|
||||
hooksConfig?: HooksConfig;
|
||||
}
|
||||
|
||||
export interface MountResult<Component extends SvelteComponent> extends Locator {
|
||||
export interface MountResult<
|
||||
Component extends (new (...args: any[]) => V4Component) | V5Component
|
||||
> extends Locator {
|
||||
unmount(): Promise<void>;
|
||||
update(options: {
|
||||
props?: Partial<ComponentProps<Component>>;
|
||||
props?: Partial<ComponentProps<InstanceType<Component>>>;
|
||||
on?: Partial<ComponentEvents>;
|
||||
}): Promise<void>;
|
||||
}
|
||||
|
||||
export const test: TestType<{
|
||||
mount<HooksConfig, Component extends SvelteComponent = SvelteComponent>(
|
||||
component: new (...args: any[]) => Component,
|
||||
options?: MountOptions<HooksConfig, Component>
|
||||
mount<
|
||||
HooksConfig,
|
||||
Component extends (new (...args: any[]) => V4Component) | V5Component
|
||||
>(
|
||||
component: Component,
|
||||
options?: MountOptions<HooksConfig, InstanceType<Component>>
|
||||
): Promise<MountResult<Component>>;
|
||||
}>;
|
||||
|
||||
export { defineConfig, PlaywrightTestConfig, expect, devices } from '@playwright/experimental-ct-core';
|
||||
export {
|
||||
defineConfig,
|
||||
PlaywrightTestConfig,
|
||||
expect,
|
||||
devices
|
||||
} from '@playwright/experimental-ct-core';
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.51.0-next",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"svelte": "^4.2.19"
|
||||
"svelte": "^5.19.9"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
|
|||
|
|
@ -18,51 +18,24 @@
|
|||
|
||||
// This file is injected into the registry as text, no dependencies are allowed.
|
||||
|
||||
import { detach as __pwDetach, insert as __pwInsert, noop as __pwNoop } from 'svelte/internal';
|
||||
import { asClassComponent } from 'svelte/legacy';
|
||||
|
||||
/** @typedef {import('../playwright-ct-core/types/component').Component} Component */
|
||||
/** @typedef {import('../playwright-ct-core/types/component').ObjectComponent} ObjectComponent */
|
||||
/** @typedef {any} FrameworkComponent */
|
||||
/** @typedef {import('svelte').SvelteComponent} SvelteComponent */
|
||||
/** @typedef {import('svelte').ComponentType} ComponentType */
|
||||
|
||||
/**
|
||||
* @param {any} component
|
||||
* @returns {component is ObjectComponent}
|
||||
*/
|
||||
function isObjectComponent(component) {
|
||||
return typeof component === 'object' && component && component.__pw_type === 'object-component';
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: remove this function when the following issue is fixed:
|
||||
* https://github.com/sveltejs/svelte/issues/2588
|
||||
*/
|
||||
function __pwCreateSlots(slots) {
|
||||
const svelteSlots = {};
|
||||
|
||||
for (const slotName in slots) {
|
||||
const template = document
|
||||
.createRange()
|
||||
.createContextualFragment(slots[slotName]);
|
||||
svelteSlots[slotName] = [createSlotFn(template)];
|
||||
}
|
||||
|
||||
function createSlotFn(element) {
|
||||
return function() {
|
||||
return {
|
||||
c: __pwNoop,
|
||||
m: function mount(target, anchor) {
|
||||
__pwInsert(target, element, anchor);
|
||||
},
|
||||
d: function destroy(detaching) {
|
||||
if (detaching)
|
||||
__pwDetach(element);
|
||||
},
|
||||
l: __pwNoop,
|
||||
};
|
||||
};
|
||||
}
|
||||
return svelteSlots;
|
||||
return (
|
||||
typeof component === 'object' &&
|
||||
component &&
|
||||
component.__pw_type === 'object-component'
|
||||
);
|
||||
}
|
||||
|
||||
const __pwSvelteComponentKey = Symbol('svelteComponent');
|
||||
|
|
@ -72,28 +45,34 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||
throw new Error('JSX mount notation is not supported');
|
||||
|
||||
const objectComponent = component;
|
||||
const componentCtor = component.type;
|
||||
component.type = component.type;
|
||||
|
||||
/** @type {ComponentType} */
|
||||
const componentCtor = asClassComponent(component.type);
|
||||
class App extends componentCtor {
|
||||
constructor(options = {}) {
|
||||
super({
|
||||
target: rootElement,
|
||||
props: {
|
||||
...objectComponent.props,
|
||||
$$slots: __pwCreateSlots(objectComponent.slots),
|
||||
$$scope: {},
|
||||
$$scope: {}
|
||||
},
|
||||
...options
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let svelteComponent;
|
||||
for (const hook of window.__pw_hooks_before_mount || [])
|
||||
svelteComponent = await hook({ hooksConfig, App });
|
||||
/** @type {SvelteComponent | undefined} */
|
||||
|
||||
if (!svelteComponent)
|
||||
let svelteComponent;
|
||||
|
||||
for (const hook of window.__pw_hooks_before_mount || []) {
|
||||
svelteComponent = await hook({ hooksConfig, App });
|
||||
}
|
||||
|
||||
if (!svelteComponent) {
|
||||
svelteComponent = new App();
|
||||
}
|
||||
|
||||
rootElement[__pwSvelteComponentKey] = svelteComponent;
|
||||
|
||||
|
|
@ -105,9 +84,10 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||
};
|
||||
|
||||
window.playwrightUnmount = async rootElement => {
|
||||
const svelteComponent = /** @type {SvelteComponent} */ (rootElement[__pwSvelteComponentKey]);
|
||||
if (!svelteComponent)
|
||||
throw new Error('Component was not mounted');
|
||||
const svelteComponent = /** @type {SvelteComponent} */ (
|
||||
rootElement[__pwSvelteComponentKey]
|
||||
);
|
||||
if (!svelteComponent) throw new Error('Component was not mounted');
|
||||
svelteComponent.$destroy();
|
||||
delete rootElement[__pwSvelteComponentKey];
|
||||
};
|
||||
|
|
@ -116,13 +96,13 @@ window.playwrightUpdate = async (rootElement, component) => {
|
|||
if (!isObjectComponent(component))
|
||||
throw new Error('JSX mount notation is not supported');
|
||||
|
||||
const svelteComponent = /** @type {SvelteComponent} */ (rootElement[__pwSvelteComponentKey]);
|
||||
if (!svelteComponent)
|
||||
throw new Error('Component was not mounted');
|
||||
const svelteComponent = /** @type {SvelteComponent} */ (
|
||||
rootElement[__pwSvelteComponentKey]
|
||||
);
|
||||
if (!svelteComponent) throw new Error('Component was not mounted');
|
||||
|
||||
for (const [key, listener] of Object.entries(component.on || {}))
|
||||
svelteComponent.$on(key, event => listener(event.detail));
|
||||
|
||||
if (component.props)
|
||||
svelteComponent.$set(component.props);
|
||||
if (component.props) svelteComponent.$set(component.props);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue