What is the most effective way to get an array of all class names for an element in Playwright using TypeScript?
I cannot seem to find any API for this very typical task and had to write the following:
export const getClassNames = async (locator: Locator): Promise<string[]> => {
// Make sure that we exctly one element
await expect(locator).toHaveCount(1);
// Get the element
const element = locator.first();
// Use evaluateHandle to get an array of class names for the element
const classListHandle = await element.evaluateHandle((el: Element) => Array.from(el.classList));
// Get the result from the classListHandle
const classNames = await classListHandle.jsonValue() as string[];
return classNames;
};
There doesn't appear to be such a function at the time of writing, but you can shorten your code considerably:
export const getClassNames = (locator: Locator): Promise<string[]> =>
locator.evaluate(el => [...el.classList]);
If you're running in strict mode, .evaluate
already asserts that there's a single element, and there's no need for intermediate ElementHandles which Playwright generally advises against using.
Here's a runnable proof of concept:
const playwright = require("playwright"); // 1.30.0
const classList = loc => loc.evaluate(el => [...el.classList]);
let browser;
(async () => {
browser = await playwright.chromium.launch();
const page = await browser.newPage();
await page.setContent(`<p class="a b c"></p>`);
console.log(await classList(page.locator("p"))); // => [ 'a', 'b', 'c' ]
await page.setContent(`<p></p><p></p>`);
console.log(await classList(page.locator("p")));
// => strict mode violation: locator('p') resolved to 2 elements
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
But if you're doing this for the purposes of a testing assertion, use
await expect(locator).toHaveClass(["some", "classes"]);
as described in this answer instead.