Reputation: 1537
I'm trying to check if an element exists before I can execute this line:
driver.findElement(webdriver.By.id('test'));
This throws an error "no such element" if the id test
doesn't exist in the document, even in a try
-block.
I've found answers for Java, where you can check if the size is 0, but in Node.js this throws an error before I can check the size:
throw error; ^ NoSuchElementError: no such element
Upvotes: 16
Views: 37561
Reputation: 1028
Aaron Silverman's answer did not work for me fully, though some parts of it were helpful. Arthur Weborg's answer worked for me, though some parts caused issues.
My typical use case for "checking if element exists" is when I want to click the element, only if it exists, since if it doesn't exist, it crashes the program due to the error. All I want is for the application to note that it doesn't exist, and move on. So what I do is:
await driver.findElement(By.id("test")).then(found => {
driver.findElement(By.id("test")).click()
}, error => {
if (error instanceof webdriver.error.NoSuchElementError) {
console.log('Element not found.');
}
});
Just a simple console log, and it moves on with the rest of the program like I wanted.
Upvotes: 1
Reputation: 1953
This is the code that worked for me.
var assert = require('assert');
var expect = require('chai').expect;
var should = require('chai').should();
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
chai.should();
var webdriver = require('selenium-webdriver');
By = webdriver.By;
until = webdriver.until;
describe('checking if an element id exists', function() {
it.only('element id exists', function () {
var driver = new webdriver.Builder().forBrowser('chrome').build();
driver.get('http://localhost:3000');
this.timeout(6000);
return driver.wait(until.elementLocated(By.id('idWeWantToTest')), 5 * 1000).then((e) => {
}, function(err) {
throw {
msg: "element not found"
}
}).then(() => {
driver.quit();
});
});
})
Upvotes: 0
Reputation: 614
You want to check whether an element exists before you want to find an element in the UI. You can wait until the element gets located in the UI, and then you can perform the find element operation.
Example: Below code waits until the element located, and then it will perform the find element.
driver.wait(webdriver.until.elementLocated(webdriver.By.id(LocatorValue)), 20000)
.then(() => {
return driver.findElement(webdriver.By.id('test'));
}).then((element) => {
// Perform any operation what you to do.
return element.click();
}).catch(() => {
console.log('Element not found');
})
Upvotes: 0
Reputation: 8590
Aaron Silverman's answer did not work as expected (err.state
was undefined
and a NoSuchElementError
was always thrown)—though the concept of using the optional callbacks still works.
Since I was getting the same error as the OP is referencing, I believe NoSuchElementError
should be referenced when determining if the targeted element exists or not. As its name implies, it is the error that is thrown when an element does not exist. So the condition in the errorCallback should be:
err instanceof webdriver.error.NoSuchElementError
So the complete code block would be as follows (I also am using async
/await
for those taking advantage of that syntax):
var existed = await driver.findElement(webdriver.By.id('test')).then(function() {
return true; // It existed
}, function(err) {
if (err instanceof webdriver.error.NoSuchElementError) {
return false; // It was not found
} else {
webdriver.promise.rejected(err);
}
});
// Handle value of existed appropriately here
Upvotes: 2
Reputation: 672
Just use the isElementPresent(locatorOrElement) method. Here's a link to the code:
Upvotes: 2
Reputation: 1738
There are 2 possible cases for this answer:
async
/ await
Case 1 using promises, then()
and the error callback is already well explained in the accepted answer.
In Case 2, if you're in an async
function (and therefore likely to be using await
statements), then you have the pleasure of avoiding all the nasty chaining of then()
's and callbacks. 🎉
In this scenario, you can simply check if an element exists with code like this:
const check = async (webdriver) => {
let elementExists;
// Solution HERE:
try {
await webdriver.findElement(webdriver.By.id('test'));
elementExists = true;
} catch (error) { // error thrown is: "NoSuchElementError: no such element"
elementExists = false;
}
if (elementExists) {
// Element exists behaviour...
} else {
// Element doesn't exist behaviour...
}
};
Upvotes: 0
Reputation: 1290
Here the summary for newbies like me ;-)
As described here:
For consistency with the other Selenium language bindings, WebDriver#isElementPresent()
and WebElement#isElementPresent()
have been deprecated. These methods will be removed in v3.0. Use the findElements
command to test for the presence of an element:
driver.findElements(By.css('.foo')).then(found => !!found.length);
Upvotes: 0
Reputation: 22645
You can leverage the optional error handler argument of then()
.
driver.findElement(webdriver.By.id('test')).then(function(webElement) {
console.log('Element exists');
}, function(err) {
if (err.state && err.state === 'no such element') {
console.log('Element not found');
} else {
webdriver.promise.rejected(err);
}
});
I couldn't find it explicitly stated in the documentation, but determined this from the function definition in webdriver/promise.js
in the selenium-webdriver
module source:
/**
* Registers a callback on this Deferred.
* @param {Function=} opt_callback The callback.
* @param {Function=} opt_errback The errback.
* @return {!webdriver.promise.Promise} A new promise representing the result
* of the callback.
* @see webdriver.promise.Promise#then
*/
function then(opt_callback, opt_errback) {
Upvotes: 32