I need to check that a button is disabled (checking for a last page of a table). There are two with the same id
(top and bottom of the table).
const nextPageButtons = await this.page.$$('button#_btnNext'); // nextPageButtons.length is 2, chekced via console.log
const nextPageButtonState = await nextPageButtons[0].isDisabled();
But when I do the above I get: elementHandle.isDisabled: Unable to adopt element handle from a different document.
Why doesn't this work?
I need to check that a button is disabled (checking for a last page of a table). There are two with the same id
(top and bottom of the table).
const nextPageButtons = await this.page.$$('button#_btnNext'); // nextPageButtons.length is 2, chekced via console.log
const nextPageButtonState = await nextPageButtons[0].isDisabled();
But when I do the above I get: elementHandle.isDisabled: Unable to adopt element handle from a different document.
Why doesn't this work?
Share Improve this question edited Jul 13, 2021 at 11:19 flamey asked Jul 13, 2021 at 9:54 flameyflamey 2,3894 gold badges34 silver badges40 bronze badges 7-
Did you try
this.page.isDisabled('button#_btnNext')
? It will check the first one. – hardkoded Commented Jul 13, 2021 at 11:58 - 1 More an observation than an answer, but if you are in control of the page content you should get the duplicated IDs fixed as the ID should be unique – sahmeepee Commented Jul 13, 2021 at 12:11
- @sahmeepee we don't, it's generated by third party library – flamey Commented Jul 13, 2021 at 13:39
- @hardkoded this works, but I want to learn and understand this.. according to docs page.$$(selector) returns Promise<Array<ElementHandle>>, so nextPageButtons[0] would be that. And elementHandle.isDisabled() returns Promise<boolean>. So why would it think this ElementHandle is "from different document"? – flamey Commented Jul 13, 2021 at 13:43
- Are you sure that your page is not changing in between? maybe between the first call and the second you have elements with the same ID but those are not the same element you got before. – hardkoded Commented Jul 13, 2021 at 17:32
4 Answers
Reset to default 3So, this works:
const nextPageButtons = await this.page.$$('button#_btnNext');
const nextPageButton1 = await nextPageButtons[0];
const nextPageButton1State = await nextPageButton1.isDisabled();
To add on the first accepted answer, we can also do this:
// given
const saveButton = page.getByRole('button', { name: 'Save' });
// then
expect(saveButton.isDisabled()).toBeTruthy();
This is the solution I used, which condenses Zekarias's answer into a single line:
await expect(page.getByRole("button", { name: "Save" })).toBeDisabled();
Doesn't address the question exactly, but this came up first in Google when I was wondering how to check if a button was disabled - so hope it helps someone else out ;)
Use of page.$$
is discouraged per playwright docs.
WHY?
Because it's static , once defined it stays the same throughout the test even though in between test page may refresh or re- loaded for any reason and the element definition may bee stale which may cause the classic "Stale element reference" issue.People ing from selenium world will recognize it instantly.
Use locator-based page.locator() toBeDisabled method instead.
WHY?
The biggest difference between the Locator and ElementHandle is that the ElementHandle points to a particular element, while Locator captures the logic of how to retrieve an element.
This happens because locator definitions are evaluated lazily only when an action is performed like 'click' using them instead of at the time of declaring the locator which makes it truly dynamic as now even if the pages gets refreshed or re- loaded and an action is performed using one of those locators will not affected as its definition will be evaluated only when it's used in 'action' so you will never encounter stale element reference exception error.
Even if you go back to previous page and e back , any locator still works as is.
Example:
const locator = page.locator('yourLocator');
await expect(locator).toBeDisabled();