javascripte2e-testingplaywrightangularjs-e2ee2e

How to locate a div with specific text and test id with Playwright?


I have a HTML like this:

<div>
  <div>Internal Description</div>
  <app-rich-text-editor>
    <div data-testid="rich-text-editor">
    </div>
  </app-rich-text-editor>
</div>

<div>
  <div>External Description</div>
  <app-rich-text-editor>
    <div data-testid="rich-text-editor">
    </div>
  </app-rich-text-editor>
</div>

If I locate the div with await page.getByTestId('rich-text-editor') I get both divs. The difference between them are the text 'Internal Description' and 'External Description'. How to locate the first div with data-testid="rich-text-editor" and parent-parallel <div>Internal Description</div>?


Solution

  • You can work top-down:

    1. Select the <div> by text
    2. Use the + CSS selector to grab the next <app-rich-text-editor> sibling
    3. Use the getByTestId function to select by [data-testid="rich-text-editor"].
    import {expect, test} from "@playwright/test"; // ^1.39.0
    
    
    const html = `<!DOCTYPE html><html><body>
    <div>
      <div>Internal Description</div>
      <app-rich-text-editor>
        <div data-testid="rich-text-editor"></div>
      </app-rich-text-editor>
    </div>
    <div>
      <div>External Description</div>
      <app-rich-text-editor>
        <div data-testid="rich-text-editor"></div>
      </app-rich-text-editor>
    </div>
    </body></html>`;
    
    test("'Internal Description' div with rich-text-editor is visible", async ({page}) => {
      await page.setContent(html);
      const loc = page.getByText("Internal Description")
        .locator("+ app-rich-text-editor")
        .getByTestId("rich-text-editor");
      await expect(loc).toBeVisible();
    });
    

    It's also possible to use the attribute child selector since you're in CSS selector context anyway:

    const loc = page.getByText("Internal Description")
      .locator('+ app-rich-text-editor > [data-testid="rich-text-editor"]');
    

    That said, if you're testing rather than scraping, using "heavy" selectors and CSS often might be a code smell. Consider adding specific test ids to the top-level container <div> elements or using additional properties and structures that may be in your markup to keep your locators simple and avoid CSS selectors.

    It may also be possible to select based on layout, depending on your use case (but this is not always reliable, so proceed with caution).