javascriptautomationui-automationplaywright

Is it possible to get the selector from a locator object in playwright?


I'm using the page-object-model in developing my automated tests in playwright. As such, I'm building a class to hold my locators and expose the locators, but not necessarily the used selector. Does the locator have a way to share its selector?

exports.MyWebPageModel = class MyWebPageModel {
  constructor(page) {
    this.myMultiSelect = page.locator('#select-group select');
    this.submitButton = page.locator('#submit-btn');
  }
}
test('validate multi-select submission', ({page}) -> {
  const myPage = new MyWebPageModel(page);
  const selectChoices = ['choice1', 'choice2', 'choice4'];
  await myPage.myMultiSelect.selectOptions(selectedChoices);
  Promise.all([
    page.waitForNavigation(),
    myPage.submitButton.click()
  ]);

  /* do tests on new page, click it's back button to return to previous page */

  const allSelectedValues = await page.$eval(myPage.myMultiSelect.???, e => Array.from(e.selectedOptions).map(option => option.value));  // get the selected options from select element
  expect(allSelectedValues).toEqual(selectedChoices);  // verify the selected options matches selectChoices.
});

Solution

  • By doing the following:

    const myLoc = page.locator('#myElement');
    Object.getOwnPropertyNames(myLoc).forEach(prop => { 
      console.log(prop + " = " + row_locator[prop]); 
    });
    

    I was able to discover there is a _selector, which returns the internal selector used for the Locator object.

    So the answer is to use the locator's "private" property _selector. This is the value that is used when generating a locator error.

    So, given a table:

    <table id="colors">
      <thead>
      <trow>
        <th>Key</th>
        <th>Color</th>
      </trow>
      </thead>
      <tbody>
      <trow>
        <td>R</td><td>Red</td>
      </trow>
      <trow>
        <td>B</td><td>Blue</td>
      </trow>
      <trow>
        <td>G</td><td>Green</td>
      </trow>
      </tbody>
    </table>
    

    And, perhaps you build your playwright object as follows:

    exports.ColorTable = class ColorTable {
      constructor(page) {
        this.page = page;
        this.table = this.page.locator("#colors");
        this.tableData = this.table.locator('tbody tr');
      }
    }
    

    The result of the following

    const myT = new ColorTable(page);
    console.log(myT.tableData._selector);
    

    might look like: Locator@#colors >> tbody tr