How can I check if an element’s class contains a specific string in Playwright?

I am trying to get the element for day 18 in a date picker and check if it has disabled in its class.

HTML snippet:

<div class="react-datepicker__day react-datepicker__day--tue" aria-label="day-16" role="option">16</div>
<div class="react-datepicker__day react-datepicker__day--wed react-datepicker__day--today" aria-label="day-17" role="option">17</div>
<div class="react-datepicker__day react-datepicker__day--thu react-datepicker__day--disabled" aria-label="day-18" role="option">18</div>

Original code:

this.xpath = 'xpath=.//*[contains(@class, "react-datepicker__day") and not (contains(@class, "outside-month")) and ./text()="18"]'

async isDateAvailable() {
    const dayElt = await this.page.$(this.xpath)
    console.log(dayElt.classList.contains('disabled')) // this should return true
}

Error:

TypeError: Cannot read property 'contains' of undefined

I can’t seem to make it work. Can someone point out what I’m doing wrong?

I ran into the same issue when trying to check classes in Playwright. The main thing is that page.$() returns an ElementHandle, so you can’t directly access classList in Node. Instead, get the class attribute:

const dayElt = await page.$(xpath);
const className = await dayElt.getAttribute('class');
console.log(className.includes('disabled')); // true if it has 'disabled'

This is the easiest way to check if a class exists. I use includes() instead of trying to access classList.

I usually prefer locator() and Playwright test assertions, it’s cleaner and async-friendly:

const day = page.locator(this.xpath);
await expect(day).toHaveClass(/disabled/);

This checks that the element has a class matching the regex /disabled/. It avoids manual getAttribute calls and works well in test scripts with expect.

Another approach I use is evaluate() if I want to run DOM code:

const dayElt = await page.$(xpath);
const hasDisabled = await dayElt.evaluate(el => el.classList.contains('react-datepicker__day--disabled'));
console.log(hasDisabled); // true

This works because evaluate runs in the browser context, so classList is accessible.