In Cypress we can do this way:
things.ts
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) => {
Elements.FOO().invoke('text').then(parseFloat).as('something');
cy.get<number>('@something').then((something) => {
for (let i = 100; i <= barNumber; i++) {
...
cy.wait('@bar').then(() => {
Elements.FOO().should('have.text', ...);
});
}
});
};
test.cy.ts
import * as Things from '../things';
describe('something', () => {
it('will do something', () => {
Things.Elements.FOO().should('be.checked');
Things.barSomething(10);
...
});
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?"
cy.get
is equivalent to PW locator APIsinvoke(jQuery)
is equivalent to locator.evaluate
then
is optional, I would prefer async/awaitas
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 PWThe thing you're referring to as "functional programming" principle seems more like a page "object" to me. ¯_(ツ)_/¯
Related Ask AI answer for "What are some guidelines for applying functional programming principles in Playwright without using classes?".
Sure, you can apply functional programming principles in Playwright without using classes. Here's how:
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;
}
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) {
console.log('Retrying...');
return await action(...args);
}
}
}
Combine multiple small functions together to create more complex behavior while maintaining modularity and reusability.
const navigateAndClick = compose(navigateTo, clickElement);
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.
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 [email protected].