Using wait with selenium web driver async content - javascript

I am trying to automate a test on my site using selenium web driver for javascript.
How can I approach running tests here using the wait method with content that may not be ready when the page loads eg data comes from an external api etc?
In my example my content is getting loaded by an external js file. You can see what the page looks like in this fiddle I couldn't link it in my code below as the fiddle gets wrapped in an iframe.
<head>
<script src="https://cdn.auth0.com/js/lock/10.2/lock.min.js"></script>
</head>
<body onload="lock.show();">
<div id="content">
<script type="text/javascript">
var domain = 'contoso.auth0.com';
var clientID = 'DyG9nCwIEofSy66QM3oo5xU6NFs3TmvT';
var lock = new Auth0Lock(clientID, domain);
lock.show({
focusInput: false,
popup: true,
}, function (err, profile, token) {
alert(err);
});
</script>
</div>
</body>
I can get it working using sleep, but can't guarentee my content will be ready after the timeout has finished.
const {Builder, By, Key, until} = require('selenium-webdriver');
let driver = new Builder()
.forBrowser('firefox')
.build();
driver.get('MY_URL')
driver.sleep(2000).then(function() {
driver.findElement(By.name('email')).sendKeys('test#test.com')
driver.findElement(By.name('password')).sendKeys('test')
//driver.findElement(By.className('auth0-lock-submit')).click()
})
But if I try with wait
function login() {
return driver.findElement(By.name('email')).sendKeys('test#test.com')
}
driver.get('MY_URL')
driver.wait(login, 5000)
I get NoSuchElementError: Unable to locate element: *[name="email"]
How can I get this working so that I wait for my content to be available before proceeding.

The implicit wait will tell to the web driver to wait for certain amount of time before it throws a "No Such Element Exception". The default setting is 0. Once we set the time, web driver will wait for that time before throwing an exception..
driver.manage().timeouts().implicitlyWait(TimeOut, TimeUnit.SECONDS);
Try to use FluentWait. Create a by function of your element which you want to wait and pass it in below method
WebElement waitsss(WebDriver driver, By elementIdentifier){
Wait<WebDriver> wait =
new FluentWait<WebDriver>(driver).withTimeout(60, TimeUnit.SECONDS) .pollingEvery(1, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
return wait.until(new Function<WebDriver, WebElement>()
{
public WebElement apply(WebDriver driver) {
return driver.findElement(elementIdentifier);
}});
}
Code for Explicit wait:
WebDriverWait wait = new WebDriverWait(driver, 60);
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//span[contains(.,'Next')]")));
refer :-
https://www.guru99.com/implicit-explicit-waits-selenium.html

Related

Puppeteer not executing anonymous function in a page

For my tests, I would like to login to this page: https://www.ebay-kleinanzeigen.de/m-einloggen.html
When first requested, this page returns a page like the following:
<html><head><meta charset="utf-8">
<script>
function(){/* some logic*/}();
</script>
</head><body></body></html>
This script has functions and an anonymous function that should be executed when the browser loads the page.
In a normal browser, this function fires a xhr request (where the server will set cookies) and then reloads the same page, that thanks to the cookies will contain the login form.
To see this in action, open a private tab in your favorite browser, open the dev tools, set the networking logs to persist and visit the page. The first network requests will look like this:
Using the following Puppeteer script, the browser doesn't execute the anonymous function and gets stuck waiting for the login form, that never appears:
import puppeteer from 'puppeteer';
const main = async () => {
try {
const browser = await puppeteer.launch({devtools: true});
const page = await browser.newPage();
await page.goto('https://www.ebay-kleinanzeigen.de/m-einloggen.html');
await page.waitForSelector('#login-form', { visible: true });
await page.screenshot({path: 'login.png', fullPage: true})
await browser.close();
} catch (e) {
console.log('error',e);
}
}
main();
I can't use page.evaluate because the content of the function is dynamically created by the server.
Is there a way to let this anonymous function get executed at page load?

I want to display a loader while I download a file through a C# controller method

I want to display a loader while I download a file. I am calling a method "DownloadFile" in my controller, it works properly. I tried to use the "onbeforeunload" Javascript trigger to display my loader. It works super fine on the all website but I have a problem with the download. It call a method in a controller, so the window expects a View to be returned. I am returning a File() so the loader is looping to the infinite and never stops, even when the file is downloaded !
I have tried several Javascript/Jquery triggers but none of them worked. Do you have any idea of how to trigger the end of a C# method execution to stop the display of the loader ?
Javascript :
$(window).on('beforeunload', function () {
displayBusyIndicator();
});
Display busy indicator :
function displayBusyIndicator() {
$("#AjaxLoader").show();
}
function hideBusyIndicator() {
$("#AjaxLoader").hide();
}
C# :
public async System.Threading.Tasks.Task<ActionResult> DownloadCertificates([FromQuery]string certificateName)
{
// instantiate a CertficatesService Class which contains key vault client connexion
CertificatesService service = new CertificatesService();
// Instantiates download service
Download download = new Download();
// Instantiates memory stream object
System.IO.MemoryStream ms = new System.IO.MemoryStream();
var user = await Dynamic365APICalls.getClientInformation(Request.Headers["X-Ms-Client-Principal-Name"], config.Value.Dynamic365ApiUrl, config.Value.EspaceClientSubKey);
if (user.Value[0].Mobilephone.ToString() != null)
{
var SASToken = SASManager.GetAccountSASToken(config.Value.StorageConnection);
// Gets the client certificates using session variable stored during landing page connexion
// which contains the company name of the client
CertificatePasswordModel certificatePassword = await service.GetCertificatePassword(certificateName, config.Value.ApiKeyVaultUrl, config.Value.EspaceClientSubKey);
service.SendPasswordBySMS(user.Value[0].Mobilephone.ToString(), certificatePassword.Password, config.Value.TwilioAccount, config.Value.TwilioAuthToken, config.Value.TwilioAccountPhoneNumber);
var fileStream = await download.DownloadFile(SASToken, config.Value.AccountName, certificateName, config.Value.StorageConnection, config.Value.PFXContainer);
await fileStream.DownloadToStreamAsync(ms);
System.IO.Stream blobStream = fileStream.OpenReadAsync().Result;
return File(blobStream, fileStream.Properties.ContentType, certificateName + ".pfx");
}
else
{
throw new System.ArgumentException("Please enter your mobile phone to access this service");
}
}
I expect the loader to be diplayed during the download and to stop when download ends

Measurement of UI application page load time

I have recently started working on UI testing and was wondering if there is any tool to figure out the time it takes to load the UI page to load in browser including the server response time ( i mean total browser time from request send till page load ).
I know that firebug/developer tools can be used to find it manually but is there any other way of doing it. Using selenium, i could use firefox driver and find out the time it takes to get the page and report that time, but i am not sure if it is the correct time.
A few words about the solution:
We will take help of Google Chrome browser for our reference. As we know when a page loads completely the browser returns Document.ReadyState as Complete to Selenium. That's when Selenium executes the next line of code. We will start the timer and start loading the webpage. When ever the document.readyState will be set to complete we will stop the timer. Here is the Selenium-Java code block:
package demo;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Q_44643596_measurement_application_load {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, 30);
long start = System.currentTimeMillis();
driver.get("https://stackoverflow.com/");
boolean pageLoaded = wait.until(ExpectedConditions.jsReturnsValue("return document.readyState")).equals("complete");
long finish = System.currentTimeMillis();
System.out.println("Page has loaded? " + pageLoaded);
long totalTime = finish - start;
System.out.println("Total Time (in Milli Seconds) for page load - "+totalTime);
}
}

Unable to click any link in the web page

I am using selenium webdriver to automate a web page. My selenium code is not identifying the link. I am getting the following error.
Exception in thread "main" org.openqa.selenium.NoSuchElementException:
no such element: Unable to locate element:
{"method":"xpath","selector":"/html/body/font/font/b/a[2]"} (Session
info: chrome=44.0.2403.89)
This is the code i am using .
public static void main(String[] args)
{
System.setProperty("webdriver.chrome.driver","C:\\Program Files (x86)\\Google\\Chrome\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("url");
driver.findElement(By.xpath("/html/body/font/font/b/a[2]")).click();
}
Thanks in advance
If you are getting NoSuchElementException as your provided exception, There are may be following reasons :-
May you are locating with incorrect xpath, So you need to share HTML for better locator solution.
May be when you are going to find element, it would not be present on the DOM, So you should implement WebDriverWait to wait until element visible and clickable as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement el = wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Duty Office")));
el.click();
May be this element is inside any frame or iframe. If it is, you need to switch that frame or iframe before finding the element as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
//Find frame or iframe and switch
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("your frame id or name"));
//Now find the element
WebElement el = wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Duty Office")));
el.click();
//Once all your stuff done with this frame need to switch back to default
driver.switchTo().defaultContent();
Hope it helps...:)
There are two possible situation
1) you might type wrong url
2) your expected element xpath is wrong.
please validate your xpath with
this tolol : https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl?hl=en
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\Program Files (x86)\Google\Chrome\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("Valid url");
driver.findElement(By.xpath("your valid XPATH")).click();
driver.close();
}

How to use phantomjs in node-js environment for dynamic-page web scraping?

I am working on web scraping for few task to complete.
I have used node-js request module for page scraping.
It is working fine and great for cookie-session and all.
But it fails when time comes to render Dynamic pages build with some javascript framework like ANGULAR or BACKBONE etc.
I am trying for phantomjs to overcome this thing as i found on google that it is helpful to come over such case.
I also found one nodejs bridge for phantomjs phantom
With phantomjs and this bridge module i am able to achieve same thing nothing more.
var phantom = require('phantom');
var fs = require('fs');
var sitepage = null;
var phInstance = null;
phantom.create()
.then(instance => {
phInstance = instance;
console.log("Instance created");
return instance.createPage();
})
.then(page => {
sitepage = page;
console.log("createing page");
return page.open('https://paytm.com/shop/p/carrier-estrella-plus-1-5-ton-3-star-window-ac-LARCARRIER-ESTRPLAN5550519593A34?src=grid&tracker=%7C%7C%7C%7C%2Fg%2Felectronics%2Flarge-appliances%2F1-5-ton-3-star-ac-starting-at-rs-22699%7C88040%7C1');
})
.then(status => {
//console.log(status);
console.log("getting content of page");
return sitepage.property('content');
})
.then(content => {
console.log("success");
//console.log(content);
fs.writeFile("ok.text", content);
sitepage.close();
phInstance.exit();
})
.catch(error => {
console.log("errr");
//console.log(error);
phInstance.exit();
});
Above is code which i am trying for load one of dynamic website page which is build with angular framework.
Can anybody guide me for same or correct in above code where i am missing right things.
You're getting the content of the page before the dynamic code has run, you need to wait for the load to be completed.
The block behind the page.open would need to wait for the page to complete, if there is an element you know is being fetched from the back end you can lie in wait for that element (see the waitfor example in phantomjs doc).

Categories