← Back to Discord Forum

[QUESTION] How to use the same approach on PW without the need of class

In Cypress we can do this way:


export const Elements = {
  FOO: () => cy.get('[data-cy="foo-box"]'),
  FOO_BUTTON: () => cy.get('[data-cy="foo-button"]'),
  FOO_LIST: (number: number) => cy.get(`[data-cy="list-${number}"]`),

export const barSomething = (barNumber: number) => {

  cy.get<number>('@something').then((something) => {
    for (let i = 100; i <= barNumber; i++) {
      cy.wait('@bar').then(() => {
        Elements.FOO().should('have.text', ...);


import * as Things from '../things';

describe('something', () => {
  it('will do something', () => {

How can I use the same principle as "functional programming" in PW?

So far what I noticed I can not do because of the fixture and checking the documentation it only shows using class https://playwright.dev/docs/test-fixtures#without-fixtures

Anyone can enlighten me?

This thread is trying to answer question "How can I use the same principle as 'functional programming' in PW?"

3 replies
  • cy.get is equivalent to PW locator APIs
  • invoke(jQuery) is equivalent to locator.evaluate
  • then is optional, I would prefer async/await
  • as is not needed in PW since locators inherently work as as.
  • wait is also not needed in PW because locators inherently wait for the element before performing action, assertions, etc.
  • should needs to be converted to expect if you want web-first assertion support from PW

The thing you're referring to as "functional programming" principle seems more like a page "object" to me. ¯_(ツ)_/¯

It is more in the sense of not be obliged to have class and only use the functions. I dont know if I am explaining myself in a good way, sorry 😛

I was just commenting on the "functional programming" aspect in your example, but that's not your question is about, so let's leave that topic for another day. As for PW equivalents of Cy, I think I answered your question. Ask me if you have any problem with that. Happy to help 🙂


Sure, you can apply functional programming principles in Playwright without using classes. Here's how:

Pure Functions

Write pure functions that take inputs and return outputs based on those inputs. For example, instead of a class method to interact with an element, create a function that takes the element as an argument and performs the action.

function clickElement(element: ElementHandle) {
  return element.click();


Avoid modifying existing data structures or objects directly. Instead, create new ones with the desired changes. This prevents unexpected side effects and makes your code more predictable.

function updatePage(newPage: Page) {
  return newPage;

Higher-Order Functions

Use higher-order functions to encapsulate common actions or behaviors into reusable function components.

function withRetry(action: Function) {
  return async function(...args: any[]) {
    try {
      return await action(...args);
    } catch (error) {
      return await action(...args);

Function Composition

Combine multiple small functions together to create more complex behavior while maintaining modularity and reusability.

const navigateAndClick = compose(navigateTo, clickElement);

Functional Libraries

Use libraries like lodash/fp or Ramda.js that provide utility functions for functional programming paradigms.

By following these guidelines, your code will be easier to understand, test, and maintain, while also promoting reusability and modularity. For more tips on writing efficient Playwright test scripts, check out this blog post.

Related Discord Threads

AboutQuestionsDiscord ForumBrowser ExtensionTagsQA Jobs

Rayrun is a community for QA engineers. I am constantly looking for new ways to add value to people learning Playwright and other browser automation frameworks. If you have feedback, email luc@ray.run.