admin管理员组

文章数量:1244420

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.
});

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.
});
Share Improve this question edited Nov 22, 2022 at 10:27 robd 9,8336 gold badges44 silver badges61 bronze badges asked Apr 28, 2022 at 13:54 MachtynMachtyn 3,2728 gold badges43 silver badges69 bronze badges 1
  • Promise.all([ must be awaited or you have a race condition. page.$eval is strongly discouraged. – ggorlen Commented Jan 1 at 3:05
Add a ment  | 

3 Answers 3

Reset to default 6

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

Well this is one way, but not sure if it will work for all possible locators!.

// Get a selector from a playwright locator
import { Locator } from "@playwright/test";
export function extractSelector(locator: Locator) {
    const selector = locator.toString();
    const parts = selector.split("@");
    if (parts.length !== 2) { throw Error("extractSelector: susupect that this is not a locator"); }
    if (parts[0] !== "Locator") { throw Error("extractSelector: did not find locator"); }
    return parts[1];
}

I am 95% sure that you can not get the selector which was previuously used. However there is way to get selector by changing your class and making the selectors as public class attributes.

exports.MyWebPageModel = class MyWebPageModel {

//think it can be declared as const
public let multiSelectSelector:string = '#select-group select';
public let submitButtonSelector:string = '#submit-btn';

  constructor(page) {
    this.myMultiSelect = page.locator(this.multiSelectLocator);
    this.submitButton = page.locator(this.submitButton);
  }
}

本文标签: javascriptIs it possible to get the selector from a locator object in playwrightStack Overflow