Skip to content

[Question] How to reuse locators?  #20000

Closed

Description

How can I reuse locator variables in different tests?
Something like:

// @ts-check
const { test, expect } = require('@playwright/test');

test.beforeEach( async ({ page }) => {
  await page.goto('[desired URL]');  
});

// I want to make this variable global to be able to use it within all the tests.
const signInBtn = page.getByTestId('some-button'); // how to resolve 'page' here??

test.describe('My set of tests', () => {

  test('My test 1', async ({ page }) => {
    await expect(page).toHaveTitle(/Some-Title/);
    await expect(signInBtn).toBeEnabled();     // I wanna use the variable here...
  });
  
  test('My test 2', async ({ page }) => {
    await signInBtn.click();   // ...and here, without having to define everytime inside each test.
  });
});

Activity

  1. Nav-2d commented on Jan 10, 2023

    @Nav-2d

    You can define the variable as let signInBtn at the top level and then assign and reuse it as needed.

  2. gauravgandhi1315 commented on Jan 10, 2023

    @gauravgandhi1315

    You can define all your locators in one separate file. From there, you can export and then use it in all your test scripts.

    exports.LocatorFile = class LocatorFile {
      static get LocatorFileTest() {
        return {
        locator: "locator"
    }
    
  3. aslushnikov commented on Jan 10, 2023

    @aslushnikov
    Contributor

    Gustavo Andrade (@1UpGus) there are ultimately 2 ways to do this.

    1. Have a simple helper function, e.g. helpers, and call it in every test:
    import { test, expect } from '@playwright/test';
    import type { Page } from '@playwright/test';
    
    function helpers(page: Page) {
      return {
        loginButton: page.getByRole('button', { name: 'login' }),
        logoutButton: page.getByRole('button', { name: 'logout' }),
        passwordField: page.getByRole('textbox', { name: 'password' });
        /* ... */
      }
    }
    
    test('should work', async ({ page }) => {
      const { loginButton } = helpers(page);
      await expect(loginButton).toBeVisible();
      await loginButton.click();
    });
    1. Setup a POM fixture. This will look something like this:
    import { test as base, expect } from '@playwright/test';
    import type { Page, Locator } from '@playwright/test';
    
    class POM {
      loginButton: Locator; 
      logoutButton: Locator;
      
      constructor(page: Page) {
        this.loginButton = page.getByRole('button', { name: 'login' });
        this.logoutButton = page.getByRole('button', { name: 'logout' });
      }
    }
    
    const test = base.extend<{pom: POM}, {}>({
      pom: async ({ page }, use) => {
        await use(new POM(page));
      },
    });
    
    test('should work', async ({ pom }) => {
      await expect(pom.loginButton).toBeVisible();
      await pom.loginButton.click();
    });

    This POM approach also was described in one of our release videos:

    https://www.youtube.com/watch?v=LczBDR0gOhk&list=PLQ6Buerc008fTzmUIPkPo3Eis0vjx7ykn&index=15&t=322s

    Hope this helps! Please do not hesitate to file new issues if you think we can be helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions