Retrieve a list of class names associated with a Playwright element

Can anyone suggest the best method to retrieve an array of all class names for an element in Playwright using TypeScript?

I've searched for an API but couldn't find one, so I ended up creating the following solution:

export const getClassNames = async (locator: Locator): Promise<string[]> => {
    // Ensure we have exactly one element
    await expect(locator).toHaveCount(1);

    // Get the element
    const element = locator.first();

    // Use evaluateHandle to obtain an array of class names for the element
    const classListHandle = await element.evaluateHandle((el: Element) => Array.from(el.classList));

    // Extract the class names from the classListHandle
    const classNames = await classListHandle.jsonValue() as string[];

    return classNames;
};

Answer №1

At this moment, there doesn't seem to be a function available for this specific task. However, you can significantly reduce the length of your code:

export const getClassNames = (locator: Locator): Promise<string[]> =>
  locator.evaluate(el => [...el.classList]);

If you are operating in strict mode, the .evaluate method already confirms that there is only one element present, eliminating the need for ElementHandles which Playwright generally advises against using.

Here is a sample demonstration that can be executed:

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());

However, if your intent is to use this for a testing assertion, consider using

await expect(locator).toHaveClass(["some", "classes"]);

as specified in this answer instead.

Answer №2

When verifying an element's classes, a tidy approach is to use the following code:

const locator = page.locator('list > .component');
await expect(locator).toHaveClass(['component', 'component selected', 'component']);

You can also utilize regular expressions like this:

await expect(locator).toHaveClass(/selected/);

For more information, check out:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to integrate TypeScript with styled components to display suggested properties on the component?

Hey there fellow developers! I'm currently diving into the world of TypeScript and trying to get the hang of it. One thing that's bothering me is not being able to see recommended props on a styled component while using TypeScript. For instance ...

What causes the difference in behavior between using setInterval() with a named function as an argument versus using an anonymous function?

I can't seem to figure out why using the function name in setInterval is causing issues, while passing an anonymous function works perfectly fine. In the example that's not working (it's logging NaN to the console and before the first call, ...

Converting an array of objects into a unified object and restructuring data types in TypeScript

A few days back, I posted a question regarding the transformation of an array of objects into a single object while preserving their types. Unfortunately, the simplified scenario I provided did not resolve my issue. In my situation, there are two classes: ...

What is the best way to customize a MaterialUI outlined input using a global theme overrides file?

I've been working on customizing my theme file with overrides, and I've encountered a strange bug while trying to style the outlined input. It seems like there are two borders appearing when these styles are implemented. https://i.stack.imgur.co ...

Event callback type narrowing based on the specific event key

While exploring different approaches to create a type-safe event emitter, I came across a pattern where you start by defining your event names and their corresponding types in an interface, as shown below: interface UserEvents { nameChanged: string; ...

"Sequencing http.get requests in Angular 2 using

In my service, I have a series of http.get requests structured as follows: constructor(private http:Http) {} getDetails(sysID:string){ var details; this.http.get('https://blahURL').map(res => res.json().filter(f => f.id == another.id)[0] ...

Changing an Angular template.html into a PDF document within an Angular 2 application can be achieved by utilizing

Exploring Angular 2 and looking for a way to export my HTML component in Angular 2 to PDF using jspdf. I want to convert dynamically generated tabular HTML into a PDF using jspdf. Below is a snippet of sample code along with a Plunker link: import {Comp ...

Is it possible to create a combined header/declaration file in Golang within a single file?

My goal is to automatically generate Golang declaration files based on .json data. While with TypeScript I can consolidate types/declarations in one file using namespaces, it seems more complex to achieve the same with Golang packages and namespacing. In ...

Struggling with getting Typescript async/await to function properly

I'm experiencing an issue with async/await in TypeScript targeting es2017. Here is the code snippet that's causing trouble: My route.ts : method: 'POST', config: { auth: { strategy: &apo ...

Custom React components are not designed to handle multiple onClick events simultaneously

One of my custom button components looks like this: export const Button = ({ children, onClick, className, ...props }: IButton) { const [selected, setSelected] = React.useState('primary') const handleSelected = () => { setSele ...

"What is the best way to specify a type for the src attribute in a tsx file within a

<Image src= { sessionData?.user.image} alt="user" width={100} height={100} />` An issue has been encountered: There is a type error stating that 'string | null | undefined' cannot be assigned to type 'stri ...

What is the most effective approach for annotating TypeScript abstract classes that are dynamically loaded?

I am in the process of developing a library that allows for the integration of external implementations, and I am exploring the optimal approach to defining types for these implementations. Illustration abstract class Creature { public abstract makeN ...

Testing NextJS App Router API routes with Jest: A comprehensive guide

Looking to test a basic API route: File ./src/app/api/name import { NextResponse } from 'next/server'; export async function GET() { const name = process.env.NAME; return NextResponse.json({ name, }); } Attempting to test ...

The error message states that the property 'registerUser' is not found on the class 'UserController'

In the controller file, I exported two functions (registerUser and loginUser) as default. No errors were thrown at that stage, but when attempting to access the routes, an error occurred stating - Property 'registerUser' does not exist on type &a ...

Issue with Jest: receiving error message "Module cannot be found" despite having the package installed

Recently, I went through a cleanup and update process for a private package to make it compatible with Vite. Initially, the package.json file had the following structure: { "name": "@myRegistry/my-package", "version": &qu ...

Successive type label

Looking to create an object that can have either primitives or objects as properties? Avoid pitfalls like the following: const obj: DesiredType = { correctProp1: 'string', correctProp2: 123, correctProp3: true, wrongProp4: [1, 2, 3], pr ...

NextJS introduces a unique functionality to Typescript's non-null assertion behavior

As per the typescript definition, the use of the non-null assertion operator is not supposed to impact execution. However, I have encountered a scenario where it does. I have been struggling to replicate this issue in a simpler project. In my current proj ...

I am facing conflicts between vue-tsc and volar due to version discrepancies. How can I resolve this problem?

My vsCode is alerting me about an issue: ❗ The Vue Language Features (Volar) plugin is using version 1.0.9, while the workspace has vue-tsc version 0.39.5. This discrepancy may result in different type checking behavior. vue-tsc: /home/tomas/Desktop/tes ...

What could be triggering the "slice is not defined" error in this TypeScript and Vue 3 application?

I have been developing a Single Page Application using Vue 3, TypeScript, and the The Movie Database (TMDB) API. In my src\components\MovieDetails.vue file, I have implemented the following: <template> <div class="row"> ...

Ways to avoid route change triggered by an asynchronous function

Within my Next.js application, I have a function for uploading files that includes the then and catch functions. export const uploadDocument = async (url: UploadURLs, file: File) => { const formData = new FormData(); formData.append("file" ...