refactor: make all components svelte5 compliant and update tests
This commit is contained in:
parent
3e0a19230d
commit
53d6d57854
3
packages/playwright-ct-svelte/index.d.ts
vendored
3
packages/playwright-ct-svelte/index.d.ts
vendored
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Snippet } from "svelte"
|
||||
import type {
|
||||
SvelteComponent as V4Component,
|
||||
Component as V5Component,
|
||||
|
|
@ -21,7 +22,7 @@ import type {
|
|||
} from 'svelte/types/runtime';
|
||||
import type { TestType, Locator } from '@playwright/experimental-ct-core';
|
||||
|
||||
type ComponentSlot = string | string[];
|
||||
type ComponentSlot = Snippet | string;
|
||||
type ComponentSlots = Record<string, ComponentSlot> & { default?: ComponentSlot };
|
||||
type ComponentEvents = Record<string, Function>;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@
|
|||
// This file is injected into the registry as text, no dependencies are allowed.
|
||||
|
||||
import { asClassComponent } from 'svelte/legacy';
|
||||
import { createRawSnippet } from "svelte";
|
||||
|
||||
/** @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 */
|
||||
|
||||
|
|
@ -38,6 +38,30 @@ function isObjectComponent(component) {
|
|||
);
|
||||
}
|
||||
|
||||
/** @type {( component: ObjectComponent ) => Record<string, any>} */
|
||||
function extractParams(component) {
|
||||
let {props, slots, on} = component;
|
||||
|
||||
slots = Object.fromEntries(
|
||||
Object.entries(slots ?? {}).map(([key, snippet]) => {
|
||||
if(typeof snippet === "string") {
|
||||
console.log("ugraded", key);
|
||||
return [key, createRawSnippet(() => ({render: () => snippet}))];
|
||||
}
|
||||
|
||||
return [key, snippet]
|
||||
})
|
||||
);
|
||||
|
||||
on = Object.fromEntries(
|
||||
Object.entries(on ?? {}).map(([key, fn]) => {
|
||||
return [`on${key}`, fn]
|
||||
})
|
||||
);
|
||||
|
||||
return {props, slots, on};
|
||||
}
|
||||
|
||||
const __pwSvelteComponentKey = Symbol('svelteComponent');
|
||||
|
||||
window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
||||
|
|
@ -45,17 +69,20 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||
throw new Error('JSX mount notation is not supported');
|
||||
|
||||
const objectComponent = component;
|
||||
component.type = component.type;
|
||||
|
||||
/** @type {ComponentType} */
|
||||
const componentCtor = asClassComponent(component.type);
|
||||
class App extends componentCtor {
|
||||
constructor(options = {}) {
|
||||
if (!isObjectComponent(component))
|
||||
throw new Error('JSX mount notation is not supported');
|
||||
|
||||
let {props, slots, on} = extractParams(component);
|
||||
|
||||
super({
|
||||
target: rootElement,
|
||||
props: {
|
||||
...objectComponent.props,
|
||||
$$scope: {}
|
||||
...props,
|
||||
...slots,
|
||||
...on,
|
||||
},
|
||||
...options
|
||||
});
|
||||
|
|
@ -63,9 +90,7 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||
}
|
||||
|
||||
/** @type {SvelteComponent | undefined} */
|
||||
|
||||
let svelteComponent;
|
||||
|
||||
for (const hook of window.__pw_hooks_before_mount || []) {
|
||||
svelteComponent = await hook({ hooksConfig, App });
|
||||
}
|
||||
|
|
@ -76,9 +101,6 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||
|
||||
rootElement[__pwSvelteComponentKey] = svelteComponent;
|
||||
|
||||
for (const [key, listener] of Object.entries(objectComponent.on || {}))
|
||||
svelteComponent.$on(key, event => listener(event.detail));
|
||||
|
||||
for (const hook of window.__pw_hooks_after_mount || [])
|
||||
await hook({ hooksConfig, svelteComponent });
|
||||
};
|
||||
|
|
@ -101,8 +123,11 @@ window.playwrightUpdate = async (rootElement, component) => {
|
|||
);
|
||||
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));
|
||||
let {props, slots, on} = extractParams(component);
|
||||
|
||||
if (component.props) svelteComponent.$set(component.props);
|
||||
svelteComponent.$set({
|
||||
...props,
|
||||
...slots,
|
||||
...on,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
export let title;
|
||||
const dispatch = createEventDispatcher();
|
||||
const { title, onsubmit } = $props();
|
||||
</script>
|
||||
|
||||
<button on:click={() => dispatch('submit', 'hello')}>{title}</button>
|
||||
|
||||
<button onclick={() => onsubmit('hello')}>{title}</button>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
<script>
|
||||
import { update, remountCount } from '../store'
|
||||
import { createEventDispatcher } from "svelte";
|
||||
export let count;
|
||||
const dispatch = createEventDispatcher();
|
||||
const { count, onsubmit, main, children } = $props()
|
||||
update();
|
||||
</script>
|
||||
|
||||
<button on:click={() => dispatch('submit', 'hello')}>
|
||||
<button onclick={() => onsubmit?.('hello')}>
|
||||
<span data-testid="props">{count}</span>
|
||||
<span data-testid="remount-count">{remountCount}</span>
|
||||
<slot name="main" />
|
||||
<slot />
|
||||
{@render main?.()}
|
||||
{@render children?.()}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
<script>
|
||||
const {children} = $props()
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h1>Welcome!</h1>
|
||||
<main>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</main>
|
||||
<footer>
|
||||
Thanks for visiting.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
<script>
|
||||
const {header, main, footer} = $props()
|
||||
|
||||
console.log({header, main, footer});
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<header>
|
||||
<slot name="header" />
|
||||
{@render header?.()}
|
||||
</header>
|
||||
<main>
|
||||
<slot name="main" />
|
||||
{@render main?.()}
|
||||
</main>
|
||||
<footer>
|
||||
<slot name="footer" />
|
||||
{@render footer?.()}
|
||||
</footer>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import NamedSlots from '@/components/NamedSlots.svelte';
|
|||
test('render a default slot', async ({ mount }) => {
|
||||
const component = await mount(DefaultSlot, {
|
||||
slots: {
|
||||
default: 'Main Content',
|
||||
children: 'Main Content',
|
||||
},
|
||||
});
|
||||
await expect(component).toContainText('Main Content');
|
||||
|
|
|
|||
Loading…
Reference in a new issue