The code I am using to run the automated test for google search is below.
const webdriver = require('selenium-webdriver'),
By = webdriver.By,
until = webdriver.until;
const driver = new webdriver.Builder()
.forBrowser('chrome')
.build();
driver.get('http://www.google.com');
driver.findElement(By.name('q')).sendKeys('webdriver');
driver.sleep(10000).then(function() {
driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
});
driver.findElement(By.name('btnK')).click();
driver.sleep(20000).then(function() {
driver.getTitle().then(function(title) {
if(title === 'webdriver - Google Search') {
console.log('Test passed');
} else {
console.log('Test failed');
}
driver.quit();
});
});
and it is throwing an error which says that element is not interactable. I have added extra time delays for loading page successfully.
(node:32241) UnhandledPromiseRejectionWarning: ElementNotInteractableError: element not interactable
element not interactable is telling you that the element you are trying to click on - is just not clickable.
You have 2 ways to overcome this:
Find the child element of the element you are trying to click on or its parent element.
Force the element to be clicked by injecting JavaScript into it:
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("document.getElementsByName
('btnK')[0].click();");
You need to make a couple of adjustments as follows:
Remove the first occurance of findElement(By.name('q')) as you are already using the line of code later.
Modify the second occurance of findElement(By.name('q')) to send the text and Key.RETURN
Remove the line findElement(By.name('btnK')) as you are already using the line of code later.
Your effective line of code will be:
const driver = new webdriver.Builder()
.forBrowser('chrome')
.build();
driver.get('http://www.google.com');
driver.sleep(10000).then(function() {
driver.findElement(By.name('q')).sendKeys('webdriver' + Key.RETURN);
});
driver.sleep(20000).then(function() {
driver.getTitle().then(function(title) {
if(title === 'webdriver - Google Search') {
console.log('Test passed');
} else {
console.log('Test failed');
}
driver.quit();
});
});
Basically driver.findElement() return promise,
So it can be anywhere in your code, so basically you have sync your code
may be here:
:driver.findElement(By.name('q')).sendKeys('webdriver');
or:
driver.findElement(By.name('btnK')).click();
so you need to make your code sync. just put ==>
await driver.findElement(By.name('btnK')).click();
-> this method won't work. Because you do not know browser behaviour some time it is fast and sometimes slow so this won't help you, driver.sleep().
Better to use:
await driver.wait(until.elementedlocated(By.xpath("xpath"),5000));
Related
I was trying to use selenium-webdriver with nodeJs. Every thing was going smooth but as soon as it end it pop up with this error in terminal.What's wrong in this.
UnhandledPromiseRejectionWarning: NoSuchSessionError: Tried to run
command without establishing a connection.
Here is my code,
let webdriver = require('selenium-webdriver');
const { Builder, Key, until } = require('selenium-webdriver');
By = webdriver.By;
let driver = new webdriver.Builder().forBrowser('firefox').build();
driver.get('https://www.google.com/');
pause(2, ScraperExample);
function ScraperExample() {
console.log('Scrapping the Pagee...');
pause(3, QuitDriver);
}
function pause(Time, FuncName) {
setTimeout(FuncName, Time * 1000);
}
function QuitDriver() {
driver.close();
driver.quit();
console.log('The Driver is set to off...');
}
I found one of the solution for my own question, we can resolve it by using any one of this drive.close() or driver.quit() if both of going to be used than we will face issues.
function QuitDriver() {
driver.quit();
console.log('The Driver is set to off...');
}```
I am trying to get puppeteer to go to all a tags in a page and load them, add them to an array and return it. My puppeteer version is 1.5.0. Here is my code:
module.exports.scrapeLinks = async (page, linkXpath) => {
page.waitForNavigation();
linksElement = await page.$x(linkXpath);
var url_list_arr = [];
console.log(linksElement.length);
i=1;
for(linksElementItem in linksElement)
{
const linksData = await page.$x('(' + linkXpath + ')[' + (i + 1) +']');
if (linksData.length > 0) {
linksData[0].click();
console.log(page.url());
url_list_arr.push(page.url());
}
else {
throw new Error('Link not found');
}
}
return url_list_arr;
};
However with this code, I get an
UnhandledPromiseRejectionWarning: Error: Node is either not visible or
not an HTMLElement
I also found out through the docs that is not possible to use the xpath on the page.click function. Is there anyway to achieve this?
It is also okay if there is a function to get all the link from a page, but I couldn't find it in the docs.
To get a handle on all a-tags in an array:
const aTags= await page.$$('a')
Loop through them with:
for (const aTag of aTags) {...}
Inside the loop you can interact with each of these elementHandle separately.
Note that
await aTag.click()
will destroy (garbage collect) all elementHandles when the page context is navigated. In this case you need a workaround like loading the initial page inside a loop to always start with a fresh instance.
Everything I've seen over the past month of looking is outdated.
Here's my problem, I traverse through about 5 different pages on one website before I get to the data I need. I can't fire off a driver.get as the url stays the same for all 5 different pages.
Since Node.js is asynchronous it runs the code before the element is present. I realize I could use a timeout, but i'm running this code 100's of times so a timeout won't work.
Everyone online says to do this, but it's outdated and doesn't work:
driver.findElement(By.css('#gridsortlink')).then(function(webElement) {
webElement.isElementPresent(By.css('#gridsortlink'))
.then(function(found) { console.log(found); });
});
If you do know how to do this that'd be great as I've been looking for a month now for the solution.
Your tried attempt looks incorrect, you should try as below :-
var webdriver = require('selenium-webdriver'),
By = webdriver.By,
until = webdriver.until;
driver.wait(until.elementLocated(By.css('#gridsortlink')), 5 * 1000).then(function(found) {
console.log(found);
});
In place of webElement.isElementPresent try to use driver.isElementPresent
driver.findElement(By.css('#gridsortlink')).then(function(webElement) {
driver.isElementPresent(By.css('#gridsortlink'))
.then(function(found) { console.log(found); });
});
I don't have access to your application thats why I created a demo code for gmail where I am putting some wrong value in Email field and after some time I am getting an error message. and the output here is 'true'.
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().forBrowser('chrome').build();
var By = webdriver.By;
driver.get('http://gmail.com');
driver.findElement(By.id("Email")).then(function(emailText){
emailText.sendKeys("aaaaaaaaaaaaaaaaaaaaaaaaaadddddddddddd").then(function(){
driver.findElement(By.id("next")).then(function(submit){
submit.click().then(function(){
driver.isElementPresent(By.className("error-msg")).then(function(text){
console.log(text);
});
});
});
});
});
Java code:
if((driver.findElements(By.css('#gridsortlink')).size())==1)
{
system.out.println(executecode);
}
else
{
system.out.println(element is not exist in webpage);
}
You can check element is present or not.
driver.findElements(By.css('#gridsortlink')).size() this row returns to 0 or 1.
1 means - Element exists on webpage.
0 means - Element does not exist on webpage.
Try in your code.
I'm trying to use a selenium server grid to run multiple commands in parallel.
Here is my first test code:
var webdriver = require('selenium-webdriver');
for(var u = 0; u < 3; u++) {
makeScreenshot('foo/test' + u + '.png');
}
function makeScreenshot(path) {
var driver = new webdriver.Builder().forBrowser('firefox').usingServer('http://someurl:44111/wd/hub/').build();
console.log('Get');
driver.get('http://www.somepage.com').then(function() {
console.log('Screenshot');
driver.takeScreenshot().then(function(data){
console.log(path);
//var decodedImage = new Buffer(data, 'base64')
driver.quit();
});
});
}
That is the result:
Get
Get
Get
Screenshot
foo/test0.png
Screenshot
foo/test1.png
Screenshot
foo/test2.png
screenshot of requests
The "Get" appears immediately in sequence, "driver.get" creates a promise. My idea here is that the three requests are made asynchronously and thus appear almost simultaneously. But as you can see in the screenshot they will be made one after the other.
The grid definitely has enough selenium instances so why isn't the driver working in parallel?
It seems to me that "new webdriver.Builder()" creates some kind of singleton that doesn't work async but waits for the previous request to finish!?
Thanks for any help!
The answer may be multiple control flows:
WebDriverJS supports defining "parallel" flows using
webdriver.promise.createFlow(). This function accepts a callback which
will be passed the newly created flow. Tasks scheduled within this
flow will be synchronized with each other, but will remain independent
of any other control flows. Each call to createFlow() returns a
promise that will resolve when the flow has completed.
The example at the end of the chapter (which I'll quite verbatim) shows multiple Google search terms being tested concurrently:
var terms = [
'javascript',
'selenium',
'webdriver'
];
var flows = terms.map(function(term) {
return webdriver.promise.createFlow(function() {
var driver = new webdriver.Builder().build();
driver.get('http://www.google.com');
driver.findElement(webdriver.By.name('q')).sendKeys(term);
driver.findElement(webdriver.By.name('btnG')).click();
driver.getTitle().then(function(title) {
if (title !== (term + ' - Google Search')) {
throw Error('Unexpected title: ' + title);
}
});
});
});
webdriver.promise.fullyResolved(flows).then(function() {
console.log('All tests passed!');
});
It should be easy enough to add your custom driver build and lookups into that example. Perhaps the following:
var flows = [0,1,2,3].map(function(index) {
return webdriver.promise.createFlow(function() {
var driver = new webdriver.Builder().forBrowser('firefox').usingServer('http://someurl:44111/wd/hub/').build();
console.log('Get');
driver.get('http://www.somepage.com').then(function() {
console.log('Screenshot');
driver.takeScreenshot().then(function(data){
console.log('foo/test' + index + '.png');
//var decodedImage = new Buffer(data, 'base64')
driver.quit();
});
});
});
});
I am trying to load an image using the fromURL. The issue is that I'd like it to be able to load a default icon if it is not able to reach the Image server to download the image. Looking at the docs I did not see an error callback for the fromURL function. How are we supposed to catch that the call was not successful and therefore do the appropriate thing? It does not seem that the callback gets called at all when image load was unsuccessful.
You can use fabric.util.loadImage() method instead of fabric.Image.fromURL().
If you look at the fromURL() method implementation, internally it uses the loadImage().
The following code may help you:
fabric.util.loadImage('https://s3-eu-west-1.amazonaws.com/kienzle.dev.cors/img/image2.png', function(img) {
if(img == null) {
alert("Error!");
}else {
var image = new fabric.Image(img);
canvas.add(image).setActiveObject(image);
canvas.renderAll();
}
}, { crossOrigin: 'anonymous' });
Here is the fiddle: http://jsfiddle.net/k7moorthi/30kmn5kL/
once you have done the function, even if theres a mistake the callback keeps running, then you could check for the element (as other said) in this way:
let fabricBackgroundInstance = new fabric.Image.fromURL(imageToUse, (oImg) => {
if(oImg._element == null){
console.error('oImg', oImg._element);
return;
}
You could use getElement() to check this error.
fabric.Image.fromURL('/foo.jpg', (img) => {
if (img.getElement() === undefined) {
console.log('Failed to load image!');
return;
}
// do something on success
}
You can add the second argument isError to your callback function.
fabric.Image.fromURL("your image URL", (img, isError) => {
if (isError) {
console.log('Something Wrong with loading image');
return;
}
// do something on success
}
Also check fabric.js source code of Image.fromURL http://fabricjs.com/docs/fabric.js.html#line21471