20

I have a button that has an initial state of disabled -

<button type = "submit" class="ant-btn ant-btn-primary ant-btn-lg" disabled>

The disabled attribute is not present once the conditions are met - so the HTML becomes

<button type = "submit" class="ant-btn ant-btn-primary ant-btn-lg">

I want to check that the button has attribute disabled, however since the attribute has no value in it, I am not able to find to a way to do so.

For example, if the disabled attribute had something like this

<button type = "submit" class="ant-btn ant-btn-primary ant-btn-lg" disabled = "disabled">

then I can do something like this

let button = await page.$('button');
let valueHandle = await input.getProperty('disabled');
assert.equal(await valueHandle.jsonValue(), 'disabled');

but since there is no value for the attribute, how to proceed in this case?

demouser123
  • 4,108
  • 9
  • 50
  • 82

4 Answers4

35

Here's a comprehensive solution showing how to solve your problem using:

page.$(), page.$$(), page.$eval(), page.$$eval(), page.$x(), and page.evaluate().

// Using page.$()
const is_disabled = await page.$('button[disabled]') !== null;

// Using page.$$()
const is_disabled = (await page.$$('button[disabled]')).length !== 0;

// Using page.$eval()
const is_disabled = await page.$eval('button[disabled]', button => button !== null).catch(error => error.toString() !== 'Error: Error: failed to find element matching selector "button[disabled]"');

// Using page.$$eval()
const is_disabled = await page.$$eval('button[disabled]', buttons => buttons.length !== 0);

// Using page.$x()
const is_disabled = (await page.$x('//button[@disabled]')).length !== 0;

// Using page.evaluate()
const is_disabled = await page.evaluate(() => document.querySelector('button[disabled]') !== null);
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
15

You should be able to do something like this:

const isDisabled = await page.$eval('button', (button) => {
  return button.disabled;
});

Your value for whether the button is disabled or not should then be stored in the isDisabled variable.

Hope this helps!

AJC24
  • 3,280
  • 2
  • 19
  • 30
6

Alternatively, you could change your page.$() query to button[disabled]. A null result implies the button is not disabled. To check for enabled buttons, query for button:not([disabled]).

const disabledButton = await page.$('button[disabled]');
const isDisabled = disabledButton !== null;

const enabledButton = await page.$('button:not([disabled])');
const isEnabled = enabledButton !== null;

demo

tony19
  • 125,647
  • 18
  • 229
  • 307
  • @Amit I recommend posting a question so that someone familiar with the topic can help. But fyi, I don't see `page.locator()` in the API docs for puppeteer. – tony19 Jul 01 '22 at 12:08
0

I want to check that the button has the attribute disabled, however since the attribute has no value in it, I am not able to find a way to do so.

The present attribute is what you check since disabled is a boolean attribute.

The answers provided so far all work. What I will suggest (though I do not know if at the time of the question this was available) is that you have the API work for you. Instead of checking for the condition yourself, you would wait for the element to become available. This can be done with either waitForSelector or waitForXPath. I will use XPath in this example.

HTML

<label for="account_email">Email</label>
<input type="email" autocomplete="username" autofocus="autofocus" id="account_email">
<button disabled>Continue</button>

JS

await page.goto('www.example.com', { waitUntil }) // go to page
await page.$x('//label[text() = "Email"]/following-sibling::input') // get input
  .then(([input]) => input.type('example@myemail.com')) // fulfill condition(valid email)
await page.waitForXPath('//button[text() = "Continue"][not(@disabled)]') // wait for button
  .then(button => button.click()) // click the button only after it is enabled
santanaG
  • 120
  • 6