I am tying to parse a website with html unit. The process basically;
WebClient client = new WebClient(BrowserVersion.CHROME);
client.waitForBackgroundJavaScript(5 * 1000);
HtmlPage page = client.getPage("http://www.exapmle.com"); //here it waits to run js code.
HtmlUnorderedList ul = (HtmlUnorderedList) page.getByXPath("//ul[contains(#class, 'class-name')]").get(0);
HtmlListItem li = (HtmlListItem) ul.getChildNodes().get(1); // I want to click li and get result page. But it takes a little time to execute.
li.click();
client.waitForBackgroundJavaScript(5 * 1000); //At here it does not do what I want.
After that when I check the page, I see that its content does not change.
What can I do to get correct page result?
Thanks.
You could try polling for a javascript condition to be true
int attempts = 20;
int pollMillis = 500;
boolean success = false;
for (int i = 0; i < attempts && !success; i++) {
TimeUnit.MILLISECONDS.sleep(pollMillis);
if (someJavascriptCondition == true) {
success = true;
}
}
if (!success) throw new RuntimeException(String.format("Condition not met after %s millis", attempts * pollMillis);
A similar technique discussed here
WebClient client = new WebClient;
HtmlPage page = client.getPage("http://www.exapmle.com");
client.waitForBackgroundJavaScript(5 * 1000);
Thread.sleep(10*1000);// this code will waite to 10 seconds
HtmlUnorderedList ul = (HtmlUnorderedList) page.getByXPath("//ul[contains(#class, 'class-name')]").get(0);
HtmlListItem li = (HtmlListItem) ul.getChildNodes().get(1); // I want to click li and get result page. But it takes a little time to execute.
li.click();
client.waitForBackgroundJavaScript(5 * 1000);
// this code will waite to 10 seconds
Thread.sleep(10*1000);
use Thread.sleep() instead of waitForBackgroundJavaScript
works for me!
You can use a JavaScriptJobManager to check the amount of JavaScript jobs that have yet to complete. Try the following code after you call click().
JavaScriptJobManager manager = page.getEnclosingWindow().getJobManager();
while (manager.getJobCount() > 0) {
System.out.printlin("Jobs remaining: " + manager.getJobCount());
Thread.sleep(1000);
}
You may want to add another way to end the while loop in case your JavaScript jobs never finish. Personally, I start terminating jobs manually with:
JavaScriptJob job = manager.getEarliestJob();
System.out.println("Stopping job: " + job.getId());
manager.stopJob(job.getId());
Hope this helps.
Related
I use Selenium WebDriver 3.14 and test is executed in Chrome browser. I need to measure response time of a page in execution time to check it is under a predefined value. If it is greater than this value some additional actions should be done. So I need different solution than System.currentTimeMillis(), because check of this value should be done automatically in background. It is an AJAX like window, so when loading takes too long time, it should be closed by script. Window example:
The typical solution to this is a try/catch against a wait. E.g. if the next step is to click a button that shows once loading completes:
WebDriverWait wait = new WebDriverWait(driver, LOADING_TIMEOUT);
WebElement webElement;
try {
webElement = wait.until(elementToBeClickable(By.id(id)));
} catch (TimeoutException ex) {
// Close loading window
return;
}
webElement.click();
However, there is a common problem if you are using implicit timeouts in Selenium. This doesn't work too well, particularly if the implicit timeout is longer than the LOADING_TIMEOUT, as this slows down the polling cycle in the wait.until().
In this case, the simplest solution is to temporarily reduce the implicit timeout:
WebDriverWait wait = new WebDriverWait(driver, LOADING_TIMEOUT);
WebElement webElement;
try {
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
webElement = wait.until(elementToBeClickable(By.id(id)));
} catch (TimeoutException ex) {
// Delay any further interaction until the timeout has been restored
webElement = null;
} finally {
driver.manage().timeouts().implicitlyWait(DEFAULT_TIMEOUT,
TimeUnit.SECONDS);
}
if (webElement != null)
webElement.click();
else
// Close loading window
If I understand correctly, you could decrease time in selenium.waitForPageToLoad("100000"); to a wanted predefined value, let us say 20 seconds. So if you want the page loading to stop if it is not loaded in 20 seconds, try something like this:
long start = System.currentTimeMillis();
try {
selenium.waitForPageToLoad("20000");
System.out.println("The page load is too long!");
} catch {
long timeToLoad= (System.currentTimeMillis()-start);
System.out.println("The page loaded in " +timeToLoad+ " seconds.");
}
You should try setting Logging Preferences through capability CapabilityType.LOGGING_PREFS for performance-log.
For example:
LoggingPreferences logs = new LoggingPreferences();
logs .enable(LogType.PERFORMANCE, Level.ALL);
caps.setCapability(CapabilityType.LOGGING_PREFS, logs);
you can get performance log entries as below.
for (LogEntry entry : driver.manage().logs().get(LogType.PERFORMANCE)) {
System.out.println(entry.toString());
//do the needful
}
I think you're looking for API testing not Automation Testing.
Postman API Testing Setup and Usage Tutorial
Hopefully this will help
edit:
Alternatively, a more lightweight solution for API testing:
Online API tester
My task is simple to download a file from a url using selenium. I did till clicking on the download part. Now I want to wait till the file is downloaded.Fine. I use following and done.
do {
Thread.sleep(60000);
}
while ((downloadeBuild.length()/1024) < 138900);
Now challenge is for how much time do I wait ? Can I set some threshold ? I can think of is use a counter in do while and check till counter goes to 10 or something like that ? But any other way in Java ? As such I do not have any action to do till the file is downloaded.
How about this?
I think using TimeOut is not stable since there is no need to wait for a un-predictable downloading operation.
You can just turn to CompletableFuture using supplyAsync to do the downloading and use thenApply to do the processing/converting and retrieve the result by join as follows:
public class SimpleCompletableFuture {
public static void main(String... args) {
testDownload();
}
private static void testDownload() {
CompletableFuture future = CompletableFuture.supplyAsync(() -> downloadMock())
.thenApply(SimpleCompletableFuture::processDownloaded);
System.out.println(future.join());
}
private static String downloadMock() {
try {
Thread.sleep(new Random().nextInt() + 1000); // mock the downloading time;
} catch (InterruptedException ignored) {
ignored.printStackTrace();
}
return "Downloaded";
}
private static String processDownloaded(String fileMock) {
System.out.println("Processing " + fileMock);
System.out.println("Done!");
return "Processed";
}
}
You can use guava Stopwatch
Stopwatch stopwatch = Stopwatch.createStarted();
while ((downloadeBuild.length()/1024) < 138900 && topWatch.elapsed(TimeUnit.SECONDS) < 60);
If what you want is a time out practice, may be you can try code below:
long timeout = 10 * 60 * 1000;
long start = System.currentTimeMillis();
while(System.currentTimeMillis() - timeout <= start ){
//Not timeout yet, wait
}
//Time out, continue
It's quite common in java library.
I'm using copyURLToFile to download a file from url.
When I use it sequentially, in a loop, about 74% of the iterations sucsseds.
But when I use it in multithreading and there are 100 concurrently running Threads, it drops down to below 5%.
Interestingly enough, when i debug the program, it get back to 74% sucsses and even higher.
Every unsuccessful attempt is caused by an exception thrown:
java.net.MalformedURLException: no protocol:
My question is whether FileUtils uses some limited resource which cause a race condition, or any other reason it fails in significantly higher rate in multithreaded environment.
I have checked the documentation of copyURLToFile, but there is no refernce there to this issue.
I have also checked the source code of copyURLToFile), but couldn't spot any thing to give a hint of why those exceptions are thrown.
public void doDownload () {
try (final WebClient webClient = new WebClient()) {
// Get the page
final HtmlPage page1 = webClient.getPage(YouTubeConvertor);
// Get the form that we are dealing with and within that form,
// find the submit button and the field that we want to change.
final List<HtmlForm> form = page1.getForms();
final HtmlTextInput textField = form.get(0).getInputByName(InputName);
final HtmlSubmitInput button = form.get(0).getInputByValue(InputValue);
// Change the value of the text field
textField.setValueAttribute(this.link);
// Now submit the form by clicking the button and get back the second page.
final HtmlPage page2 = button.click();
HtmlElement down = page2.getHtmlElementById(FileElement);
String name = down.getAttribute(HrefElement);
URL linkUrl = new URL(name);
File f = new File (Dir , this.saveName + Mp3Ending);
FileUtils.copyURLToFile(linkUrl, f);
} catch(Exception ex) {
System.out.println("Some form of error happened! " + ex.toString());
// timeout based on attempts and time elapsed
if (times++ < 10 && TimeUnit.SECONDS.convert
(System.nanoTime()-this.startTime, TimeUnit.NANOSECONDS) < 60) {
doDownload ();
}
}
I have a Java code as below and when I am running through PhantomJs getting "Unsupported Command Exception" but it is working fine if I run through firefox and chrome:-
Note: With phantomJs we could able to execute till 3rd step in below code.I searched in many blogs but those answers didn't solve my problem.
1. cvvField.sendKeys(cvcData);
2. proceedToPayBtn.click();
3. Reporter.log("Card details are submitted from payment UI page");
4. Alert a1=driver.switchTo().alert();
5. Reporter.log("Alert with text:"+a1.getText());
6. a1.accept();
Here cvvField and proceedToPayBtn are WebElements and cvcData have value as "111".
Error log:-
org.openqa.selenium.UnsupportedCommandException: Invalid Command Method -
{"headers":{"Accept-Encoding":"gzip,deflate","Cache-Control":"no-cache","Connection":"Keep-Alive","Host":"localhost:30462","User-Agent":"Apache-HttpClient/4.5.1 (Java/1.8.0_101)"},"httpVersion":"1.1","method":"GET","url":"/alert_text","urlParsed":{"anchor":"","query":"","file":"alert_text","directory":"/","path":"/alert_text","relative":"
/alert_text","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/alert_text","queryKey":{},"chunks":["alert_text"]},"urlOriginal":"/session/9e392a50-ce79-11e6-b24a-2b12cf1ec4d6/alert_text"}
Command duration or timeout: 31 milliseconds
I have edited above code as below but same error is coming.Please suggest
if (driver instanceof PhantomJSDriver)
{
JavascriptExecutor je = (JavascriptExecutor) driver;
je.executeScript("window.alert = function(){};");
je.executeScript("window.confirm = function(){return true;};");
System.out.println("Alert has been handled");
} else {
Alert a1 = driver.switchTo().alert();
a1.accept();
}
I am getting "Alert has been handled" in output console but alert is not handled.
Some issue due to wait time can be the source of your problem
The code above can help to wait until element is visible (since the wait of ngWebDriver or Selenium Webdriver are not compatible with PhantomJS)
public static String waitJSResponse(PhantomJSDriver driver, String script) {
String ReturnedValue = null;
int sleeper = 10;
Boolean flag = false;
int timeOut = 30000;
int i = 0;
while ((!flag) & ((i*sleeper)<timeOut)) {
try {
Thread.sleep(sleeper);
ReturnedValue = (String) driver.executeScript(script);
} catch (Exception e) {
flag = false;
i++;
}
if (ReturnedValue != null) {
flag = true;
System.out.println("Overall wait time is : "+(i * sleeper)+" ms \n\r");
break;
}
}
return ReturnedValue;
}
This code will wait 10ms then verify that the element is visble, if there is an exception, it will loop again.
The returned value must be a text, an object or anything that is not null.
the script value must be your JS script to get the correct element.
Hope it work.
I tried the above code by:-
1.Creating a class "Test" and writing above method in it.
2.Above method is called by creating an object(TestObject) as
TestObject.waitJSResponse((PhantomJSDriver) driver, "window.confirm = function(){return true;};");
But ReturnedValue in
try
{
Thread.sleep(sleeper);
ReturnedValue = (String) driver.executeScript(script);
System.out.println(ReturnedValue);
}
returns null.So Can u please help with this?
I have issue keep throw error of unable to find the xpath , as i set the loop for opening this xpath to insert data . Although i set the time wait for existance to 60secound but it still couldn't find it. I been trying alot method calling this by using title or status hence it still not working . Kindly advise
HTML :
91.14
CODE :
public void clickOnItemTax () {
By xPath = By.xpath("//a[contains(#href,'edit_total_amt')]");
this.sleep(3);
if (this.waitForExistence(xPath,60)) {
WebElement domLink = linkGet(xPath);
domLink.click();
} else {
JLog.fail("Unable to find a writable item taxdialog!");
}
}
-waitforExistence
public boolean waitForExistence(By by, int timeoutSeconds){
boolean exists = false;
Long polling_interval = (long) 250;
Long timeout = (long) timeoutSeconds * 1000; // in seconds
Long elapsed = (long) 0;
while (elapsed <= (timeout)) {
if (exists(by)) {
exists = true;
break;
}
try {
Thread.sleep(polling_interval);
} catch (InterruptedException e) {
JLog.warning(JLog.getStackTraceAsString(e));
break;
}
elapsed += polling_interval;
}
if (elapsed >= timeout) {
JLog.warning("waitForExistence waited for " + timeout/1000 + " seconds, but unable to find: " + by.toString());
}
return exists;
}
Thanks you
If it's an internal company webpage could I suggest that you give the an 'id' to make your life easier. If not you can do this. I'm always surprised by people writing their own wait method when you could use either the implicit or explicit wait time in Selenium.
The former is as follows, the only thing to be aware using this method is that when looking for an element it will always wait this long. It is however a much safer way to write your scripts looking for elements and doesn't bloat your code:
driver.manage().timeouts().implicitlyWait(6, TimeUnit.SECONDS);
if (driver.findElements(By.cssSelector("//*[#title=\"Override total tax amount\"]")).size()!=0)
{
driver.findElement(By.cssSelector("//*[#title=\"Override total tax amount\"]")).click();
}
else
{
JLog.fail("Unable to find a writable item taxdialog!");
}
The explicit way to do it would be as follows where 10 is your seconds:
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("//*[#title=\"Override total tax amount\"]")));
See the following link for more on this.
http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp