Open ariefurtado opened 2 years ago
I have forked the project, and based on this comment from an issue of the dom-testing-library
, I have swapped the @testing-library/dom
dependency for the testing-library__dom
.
commentary about the issue: https://github.com/testing-library/dom-testing-library/issues/742#issuecomment-674987855
my library fork: https://github.com/ariefurtado/testing-library
For those that wants to try the forked version, I created a tag within the fork and its working! https://github.com/ariefurtado/testing-library/tree/v0.0.1_shadow
ps: since this is my first time forking and doing all of this, I ask you folks not to be too harsh with me ^^
ps²: this is not a production ready implementation and cannot be merged into the original project and we have to wait for a stable solution.
Hey @ariefurtado thanks a lot for the work you did there! I tested it out and it's awesome.
Although your solution does add support for web components, there is a slight problem there, given the fact that it's using a community fork of testing library from 2 years ago:
If you are very interested in making this possible in the actual @testing-library/dom
package, can you reach out to me on twitter? There is a possible long term solution but for that I need help from someone who is well versed into the web components world.
I just ran into this issue and, with interactions, this is how I'm working around it:
MyThing.play = async ({args, canvasElement}) => {
const wc = canvasElement.querySelector(
'my-thing',
) as HTMLElement;
// Wait for Shadow DOM to be mounted & `open`
const root = await waitFor(
() => (wc.shadowRoot as ShadowRoot).firstElementChild as HTMLElement,
{
timeout: 5000,
},
);
const screen = within(root);
...
};
Perhaps this could be documented away?
@ericclemmons Unfortunately this doesn't work for us:
export const WithLabel = WithLabelTemplate.bind({});
WithLabel.play = async ({ canvasElement }) => {
const wc = canvasElement.querySelector("calcite-input") as HTMLInputElement;
const root = await waitFor(() => (wc.shadowRoot as ShadowRoot).firstElementChild as HTMLElement, {
timeout: 5000
});
const screen = within(root);
const input = screen.getByTestId("input-with-label") as HTMLInputElement;
await userEvent.type(input, "foo bar baz");
};
We get this error:
What did you put in the rest of your play
function? I'm skeptical about the work around since @testing-library/dom
doesn't provide access to web component browser APIs, but I hope I'm wrong.
@yannbf I don't have twitter, but my team and I would like to connect about the long term solution. We are creating Calcite Components and may be able to help with the web component side of the equation. We want to migrate to chromatic and this is the only thing blocking us. Let me know how we can help and/or how we should connect. Thanks!
Still no support?
@yannbf I don't have twitter, but my team and I would like to connect about the long term solution. We are creating Calcite Components and may be able to help with the web component side of the equation. We want to migrate to chromatic and this is the only thing blocking us. Let me know how we can help and/or how we should connect. Thanks!
Sorry I missed this @benelan, I'll reach out on Linkedin.
@yannbf @benelan any updates 😊?
Hello again @yannbf, this has been a very long year for me, and a lot of stuff hapenned so i could not see this issue progressing.
I played with the solution presented by @ericclemmons and thought that something was off.
Then I've searched the docs for the waitFor
function and came up with a refactor that got me there.
I've created the function withinShadowRoot
to make it easy to re-use.
export async function withinShadowRoot(customElement: HTMLElement, selector: string) {
const webc = customElement.querySelector(selector);
await waitFor(
() => {
const shadowRootFirstEl = webc.shadowRoot.firstElementChild as HTMLElement;
return expect(shadowRootFirstEl).toContainElement(shadowRootFirstEl);
},
{ timeout: 1000 },
);
// force type HTMLElement to ignore the type checking of the "within" function
return within(webc.shadowRoot as any as HTMLElement);
}
With this function, all that is needed to interact with the elements in the shadowRoot is to await
for the function to return and we can use it. Example:
// CSF3 StoryObj
export const Default: StoryObj<PzlButtonStoryArgs> = {
render: Template.bind({}),
args: {
onClick: event => action('Button Clicked')(event),
children: <p>click me</p>
},
play: async ({ canvasElement }) => {
const webc = await withinShadowRoot(canvasElement, 'pzl-button');
const buttonEl = await webc.findByRole('button');
await userEvent.click(buttonEl);
}
};
I'm not sure about the efficiency and I have not tested enough, but for now, it is doing the trick.
Thanks everyone ^^
ps: please forgive my english... 😳
@ariefurtado can't wait to give this a try over the weekend! Cheers!
Hello @yannbf,
any updates on this?
Describe the bug
Currently, it is not possible to use the library with Web Components because of missing shadow dom...
Steps to reproduce the behavior
shadow: true
and a stories file for that componentExpected behavior
Should be able to find the element within the shadow dom.