modernweb-dev / web

Guides, tools and libraries for modern web development.
https://modern-web.dev
MIT License
2.15k stars 271 forks source link

Web Test Runner with Playwright-like selectors? #2714

Closed enkelmedia closed 2 months ago

enkelmedia commented 2 months ago

Hi!

I've just started to use Web Test Runner to test Web Components using PlayWright and Mocha/Chai (since this is what was recommended).

I tend to find my self needing to write quite verbose code to perform test for components that have other components nested. For example, let's say I want to test a Button Group that contains other Button. In my test I have three buttons in the group and I would like to click on button nr 2 and then ensure it has been highlighted.

By the research I've done so far I would have to do something like this:

describe('Button group highlight', () => {
    let elmButtonGroup : MyButtonGroupElement;
    let elmButtn1 : MyButtonElement;
    let elmButtn2 : MyButtonElement;
    let elmButtn3 : MyButtonElement;

    beforeEach(async () => {
        elmButtonGroup = await fixture(html`
            <my-button-group>
                <my-button>Btn 1</my-button>
                <my-button>Btn 2</my-button>
                <my-button>Btn 3</my-button>
            </my-button-group>
            `);

        elmButtn1 = elmButtonGroup.shadowRoot?.querySelector('my-button') as MyButtonElement;
        elmButtn2 = elmButtonGroup.shadowRoot?.querySelector('my-button') as MyButtonElement;
        elmButtn3 = elmButtonGroup.shadowRoot?.querySelector('my-button') as MyButtonElement;

    });

    it('Validate content after click', async () => {

        const listener = oneEvent(elmButtonGroup, 'click', false);

        elmButtn2.click();

        const event = await listener;

        // do stuff
    });

});

I was wondering what it would take to be able to have a more flexible way of selecting elements? Similar to how Playwright allows to select elements using theire selectors https://playwright.dev/docs/api/class-selectors. For example:

await page.locator('tag=div').getByText('Click me').click();

This would have been very useful.

bashmish commented 2 months ago

Maybe you need smth like a Shadow DOM selector library?

If I search on NPM, I find a few. Does any of them solve it for you? https://www.npmjs.com/search?q=shadow%20dom%20selector

enkelmedia commented 2 months ago

@bashmish, thanks a lot!

Sometimes you just need someone to help you mind think in the right direction, today you were that person to me 😀

I tried both the packages below and they work in similar ways, making it possible to query for a nested element inside the shadowDom like so:

elmButtn1 = querySelectorDeep('my-button') as MyButtonElement;

query-selector-shadow-dom https://www.npmjs.com/package/query-selector-shadow-dom

kagekiri https://www.npmjs.com/package/kagekiri

As for the other thing that I was looking for, basically to be able to ask "is this text on the screen", it seems to be possible with this API: https://developer.mozilla.org/en-US/docs/Web/API/Window/find

window.find('ashowdialog',false,false,true,false,true,true)

Feels like I just need to add some wrappers to make the tests more readable.

Thanks for helping out!