playwright
playwright copied to clipboard
[Feature]: ability to pass components to `HooksConfig`
🚀 Feature Request
The ability to pass components to HooksConfig, probably by using the resolveImportRef to resolve the hooksConfig;
Example
beforeMount(async ({ app, hooksConfig }) => {
for (const [name, component] of Object.entries(hooksConfig?.components || {}))
app.component(name, component);
});
import { test, expect } from '@playwright/experimental-ct-vue';
import DefaultSlot from '@/components/DefaultSlot.vue';
import Button from '@/components/Button.vue';
test('render a component as slot', async ({ mount }) => {
const component = await mount(DefaultSlot, {
slots: {
default: '<Button title="Submit" />',
},
hooksConfig: {
components: { Button }
}
});
await expect(component).toContainText('Submit');
});
Motivation
It simplifies testing slots and other use cases such as providing plugins
Could you help me understand why we need to register component in beforeMount for this use case to work? I was hoping it would work out of the box.
Vue is unable to locate the <Button /> component when it's passed to the slot as a string.
So this test will fail because there's no reference from the <Button /> string to the actual component:
-- DefaultSlot.vue <-- NOTE: Button component not registered here
<template>
<main>
<slot />
</main>
</template>
test('render a component as slot', async ({ mount }) => {
const component = await mount(DefaultSlot, {
slots: {
default: '<Button title="Submit" />', <-- NOTE: There is no reference
},
});
await expect(component).toContainText('Submit');
})
Vue test utils follows a similar approach: https://test-utils.vuejs.org/api/#global-components. Their mount.global is kind of similar to Playwright's mount.hooksConfig: https://test-utils.vuejs.org/api/#global
Ah, I missed the string quotes around <Button>, it makes sense to me now. In terms of the proposed shape of the API, I see hooksConfig as a user object w/o schema. In this case it seems like Vue would benefit from framework-specific components property that would point to the component registry. Does it make sense?
I see hooksConfig as a user object w/o schema
I actually use hooksConfig specifically for registering global things like mixins, components, plugins and directives. It's been a while, but hooksConfig was introduced two years ago for this reason right?: https://github.com/microsoft/playwright/issues/14416
In this case it seems like Vue would benefit from framework-specific components property that would point to the component registry. Does it make sense?
It is a common scenario, but i don't think it needs a specific API as it saves just a few lines of code. This would also be the first API that's different from the rest and i kind of like the flexibility of the hooksConfig.
It's a trade-off between a generic hooksConfig API or framework-specific APIs IMO. I recently sent something about this on Discord. With the Angular adapter we are also confronted with the question: 'domain specific or generic'
Another option is to put the boilerplate code in playwright-create:
// /playwright/index.ts
beforeMount(async ({ app, hooksConfig }) => {
for (const [name, component] of Object.entries(hooksConfig?.components || {}))
app.component(name, component);
});
Ah, so you want the user to control both sides of the story, so hooksConfig's schema is left to the user to define? That's fine with me.