Animus
Animus

Reputation: 843

How to get classList on a selector in playwright?

This is my start with playwright and I try to test my React app with it.

It might be that there is a similar question somewhere here, however I've tried all the possible non-specific answers from StackOverflow and Github issues.

This is my test:

import {expect, test} from "@playwright/test";

test.describe('App general functionality', () => {
    test('Theme switches normally', async ({page}) => {
        const app = await page.getByTestId('app');
        const themeSwitch = await page.getByTestId('themeSwitch');

        const classList = await app.evaluate(node => {
            console.log(node);
        });
        // const classList = await app.getAttribute('class');
    });
});

I've tried installing extended expect types for toHaveClass and checked if app is present. In console it returns locator and elements inside the app. App is a test id on the root div of the application.

However the error is constant:

locator.evaluate: Target closed
=========================== logs ===========================
waiting for getByTestId('app')
============================================================

And it is one this line:

const classList = await app.evaluate // or app.getAttribute('class')

The app div:

<div data-test-id={'app'} className={`app ${appStore.isDarkTheme ? 'dark' : 'light'}`}>

Git url

Upvotes: 3

Views: 3330

Answers (1)

ggorlen
ggorlen

Reputation: 57135

I don't think the test id is set properly. It should be data-testid based on the following experiment:

import {expect, test} from "@playwright/test"; // ^1.30.0

const html = `<!DOCTYPE html>
<html><body><div data-testid="app" class="foo bar baz">hi</div></body></html>`;

test.describe("App general functionality", () => {
  test("Theme switches normally", async ({page}) => {
    await page.setContent(html); // for easy reproducibility
    const el = await page.getByTestId("app");
    const classList = await el.evaluate(el => [...el.classList]);
    expect(classList).toEqual(["foo", "bar", "baz"]);
  });
});

If you can't change the element's property, maybe try

const el = await page.$('[data-test-id="app"]');

Pehaps a bit more idiomatic (assuming you've fixed testid):

const app = page.getByTestId("app");
await expect(app).toHaveClass(/\bfoo\b/);
await expect(app).toHaveClass(/\bbar\b/);
await expect(app).toHaveClass(/\bbaz\b/);

This handles extra classes and different ordering of the classes. See also Check if element class contains string using playwright for deeper discussion of this pattern.

Upvotes: 2

Related Questions