Overview
Strict mode in Playwright means locators are strict. Any locator which resolves to more than one element will become invalid and it makes Playwright throw this ugly exception:
=> This Exception means we have violated strict mode as our locator resolved to 10 elements instead of 1. Strict mode is useful in almost situations but in some other cases, know how to handle it flexibly is also helpful too.
Locator resolves to one element
- Method 1: Using CSS or Xpath syntax
When catching element in DOM HTML, we mainly use CSS or Xpath selector. In CSS you can use:
+ first-child
+ last-child
+ nth-child
…and some other CSS selector adapted to your requirement to make your locator only resolve to one element.
Example:
(//ul[@class='sac-results']//li[@class='sac-results__item'])[1]
(//ul[@class='sac-results']//li[@class='sac-results__item'])[2]
In Xpath, you can group all elements in one array and access its element like this. Note that index of this array starts from one instead of zero.
(//ul[@class='sac-results']//li[@class='sac-results__item'])[1]
(//ul[@class='sac-results']//li[@class='sac-results__item'])[2]
- Method 2: Using Locator API
Do not want to make your locator resolved to only one element by CSS or Xpath selector, just use Playwright Locator API.
Playwright supports quite of built-in methods for this like first(), last(), nth()…
await page.locator('ul.sac-results li.sac-results__item').first()
=> return locator of the first matching element
await page.locator('ul.sac-results li.sac-results__item').last()
=> return locator of the last matching element
await page.locator('ul.sac-results li.sac-results__item').nth(1)
=> return locator to the n-th matching element. Just passing index of element to nth() method. Index equal to zero will resolve to the first element, relevant to first() method
Another way to write above statement is passing “nth=index” to locator() method like below. It just has the same effect though.
await page.locator('ul.sac-results li.sac-results__item').locator('nth=0')
You can also use $() method to resolve to one element although Playwright recommend using locator() method instead.
const element = await page.$('ul.sac-results li.sac-results__item'); console.log(await element?.innerText())
Locator resolves to multiple elements
But in some cases, you still want to keep your locator resolved to multiple elements on purpose. Consider a real-life example, in this domain I want to verify a suggestion drop down list which contains 10 elements is displayed after entering keyword to header search textbox.
1. Get all elements:
You can use all() method to get an array of locators which point to respective elements and use for loop to iterate through all elements.
const elements = await page.locator('ul.sac-results li.sac-results__item').all(); for(const element of elements) { console.log(await element.innerText()); }
Another way is using $$() method which has the same functionality as all() method although Playwright recommends using locator() method instead.
const elements = await page.$$('ul.sac-results li.sac-results__item'); for(const element of elements) { console.log(await element.innerText()); }
2. Disable strict mode by waitForSelector():
waitForSelector() is used to wait for a locator satisfies state of an element. Although our locator resolved to multiple element, using “strict: false” will bypass the restrictions.
const element = await page.waitForSelector('ul.sac-results li.sac-results__item', {state: 'visible', strict: false}); console.log(await element.innerText())
Strict mode in Selenium
Selenium is more “sloppy” than Playwright. Selenium (Java) has two methods called findElement() and findElements(). Both of those does not concern about strictness of locator. If our locator resolves to more than one element, findElement() only returns the first matching element while findElements() returns a List collection of matching elements.
Selenium (Java) | Playwright (Typescript) | |
Strict mode | None of restrictions | Locators should be resolve to only one element. Otherwise exception will be throwed |
Methods | findElement(): resolve to only the first matching element. Throw exception if no element found findElements(): resolve to a List of elements. Return an empty List if no element found | Locator(): resolve to only one element. Exception will be throwed if violating strict mode $(): resolve to the first matching element. Exception will not be throwed if violating strict mode (not recommend to use) $$(): resolve to an array of matching elements. Exception will not be throwed if violating strict mode (not recommend to use) |
Conclusion
Strict mode is a restriction of Playwright which makes us aware of using more exact locator. Our locator should resolve to only one element. Otherwise Exception will be throwed. Know how to handle in many situations will make this automation tool more flexible. Thanks for reading!