Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Component as slot #15900

Open
1 of 3 tasks
sand4rt opened this issue Jul 24, 2022 · 7 comments
Open
1 of 3 tasks

[Feature] Component as slot #15900

sand4rt opened this issue Jul 24, 2022 · 7 comments
Assignees

Comments

@sand4rt
Copy link
Collaborator

sand4rt commented Jul 24, 2022

I cannot specify a component as a slot:

import { test, expect } from '@playwright/experimental-ct-vue';
import Form from './Form.vue';

test('renders a component as slot', async ({ mount }) => {
    const component = await mount(Form, {
        slots: {
            // Input is registered in playwright/index.ts. 
            default: `<Input />`
        }
    });

    await expect(component.getByRole('textbox')).toBeVisible(); // input cannot be found
});

TODO

@pavelfeldman
Copy link
Member

Yes, I'm not sure I understand the text vs markup ambiguity in VTU, so we interpret slots as text there. Any reason you don't like JSX for composition? Looks way easier to read, is more in line with the way you compose in the actual .vue files. Would be interested in what you think.

@sand4rt
Copy link
Collaborator Author

sand4rt commented Jul 26, 2022

I agree with your statements. However, my thought process is that it's another technology that adds to an already large stack of technologies that people are being pushed towards when using frontend frameworks.

In my opinion there aren't many use cases where you want to add complex slots to your component (inside tests). I only do this when the parent component and child components are talking directly to each other which is rare. So the need for JSX is less.

In addition, the API of JSX and the Vue template engine are not quite the same. In my opinion, those minor differences are confusing to people unfamiliar with JSX and most people using Vue don't use JSX. You probably know the differences but those are some of them:


Vue
<button @click="onButtonClick />
JSX
<button onClick={onButtonClick} />


Vue
<Counter :count="count" />
JSX
<Counter count={count} />


Vue
<div>{{ text }}</div>
JSX
<div>{ text }</div>


Vue
<input v-model="inputValue" />
JSX
Not sure if using v-model is possible with JSX? Will probably look like this?:
<input onChange={handleChange} value={inputValue} />


With that being said the mount options API isn't perfect either. As you said, the code does not look like how you would compose them in .vue files. Also no type checking and syntax highlighting when using HTML in slots. So at this time for me it's a matter of "pick your poison". Would love to see the full Vue template syntax working in JSX but don't think this is possible?

@pavelfeldman
Copy link
Member

Would love to see the full Vue template syntax working in JSX but don't think this is possible?

All the Vue examples you provide above are actually a subset of JSX, at least syntactically. {{ text }} is basically an object shorthand notation { text } that you can use inside the code block { }. But the tooling / type checking will get confused for sure, so I would keep it JSX for the VS Code smarts.

The missing bits for the complete template support in slots would be:

  • The mapping from the component name in the markup to the actual component definition. Probably discoverable from the registry of components.
  • Actual rendering call - we don't want to interpret this string, need some Vue internals to do that for us.

@dgozman dgozman removed the v1.25 label Aug 4, 2022
@sand4rt sand4rt changed the title [BUG] Component testing Vue slots [BUG] Component as slot Oct 11, 2022
@sand4rt sand4rt changed the title [BUG] Component as slot [Feature] Component as slot Mar 8, 2023
@pbrzosko
Copy link

I see that Vue 3 as a slot is done, but I can not make it to work. I see @sand4rt in your change, that you register the component globally in the app. But what If I don't want to register it globally, but just want to use it in one test as a slot? It doesn't render anything in that scenario. Something like that:

const component = await mount(WizardTestWrapper, {
      props: {
        model: {}
      },
      components: {
        WizardFirstPage,
      },
      slots: {
        default: "<WizardFirstPage/>",
      },
    });

@sand4rt
Copy link
Collaborator Author

sand4rt commented Mar 13, 2024

Hi @pbrzosko, i usually just register it globally for all tests, but if you want to register the component for one single test you could use:

// playwright/index.ts
export type HooksConfig = {
  registerButton: boolean;
}

beforeMount<HooksConfig>(async ({ app, hooksConfig }) => {
  for (hooksConfig.registerButton)
    app.component('button', Button);
});
// slots.test.ts
test('render a component as slot', async ({ mount }) => {
  const component = await mount<HooksConfig>(DefaultSlot, {
    slots: {
      default: '<Button title="Submit" />',
    },
    hooksConfig: {
      registerButton: true
    }
  });
  await expect(component).toContainText('Submit');
});

This is would be nice to have I think, but is not suported ATM:

// playwright/index.ts
export type HooksConfig = {
  components: Record<any, any>;
}

beforeMount<HooksConfig>(async ({ app, hooksConfig }) => {
  for (const [name, component] of Object.entries(hooksConfig.components))
    app.component(name, component);
});
// slots.test.ts
test('render a component as slot', async ({ mount }) => {
  const component = await mount<HooksConfig>(DefaultSlot, {
    slots: {
      default: '<Button title="Submit" />',
    },
    hooksConfig: {
      components: { Button }
    }
  });
  await expect(component).toContainText('Submit');
});

@pbrzosko
Copy link

But I believe there is a components object in mount options. Why it is not enough to specify a component there?

@sand4rt
Copy link
Collaborator Author

sand4rt commented Apr 27, 2024

@pbrzosko there is no components property on the mount options atm.

Related to #30453

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants