HtmlUnit HtmlImageInput.click() not working? - java

I am kinda new to HtmlUnit and am having some trouble getting a form to submit with HtmlImageInput.click(). When I call the method, nothing seems to happen, no form submission, no round trip to the server, or anything, as far as I can tell. The method returns immediately, returning the current page.
There's no Javascript event handler attached to the image input. It's just a plain old vanilla image input, nothing special going on. The input is initially set to disabled when the page is loaded, and then gets enabled as the user interacts with certain AJAXy elements within the page. But by the time I click on the input, it has already been enabled, so I don't think it's an AJAX issue.
Anybody have an idea of what is going on? Runnable source code pasted below.
Thanks,
Matthew
import java.io.*;
import java.util.*;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.*;
import org.w3c.dom.*;
public class Test {
public static void main(String args[]) {
try {
WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_7);
webClient.setThrowExceptionOnScriptError(false);
HtmlPage page = webClient.getPage("http://us.megabus.com");
System.out.println("got the page");
HtmlForm form = page.getFormByName("ctl01");
System.out.println("got the form");
HtmlSelect select = form.getSelectByName("SearchAndBuy1$ddlLeavingFrom");
select.click();
System.out.println("clicked the select");
HtmlOption option = select.getOptionByValue("13");
option.click();
System.out.println("clicked the option...going to sleep");
try { Thread.sleep(15000); } catch(InterruptedException e) {}
select = form.getSelectByName("SearchAndBuy1$ddlTravellingTo");
select.click();
System.out.println("clicked the select 2");
option = select.getOptionByValue("37");
option.click();
System.out.println("clicked the option 2...going to sleep");
try { Thread.sleep(15000); } catch(InterruptedException e) {}
HtmlImage image = (HtmlImage)page.getElementById("SearchAndBuy1_imgOutboundDate");
image.click();
System.out.println("clicked the image");
String month = "April";
String date = "09";
HtmlTable table = (HtmlTable)page.getElementById("SearchAndBuy1_calendarOutboundDate");
HtmlTableRow row = ((HtmlTable)table.getCellAt(0, 0).getChildElements().iterator().next()).getRow(0);
String monthString = row.getCell(1).getTextContent();
monthString = monthString.substring(0, monthString.indexOf(' '));
while(!monthString.equals(month)) {
row.getCell(2).getChildElements().iterator().next().click();
System.out.println("clicked to go to the next month");
try { Thread.sleep(15000); } catch(InterruptedException e) {}
table = (HtmlTable)page.getElementById("SearchAndBuy1_calendarOutboundDate");
row = ((HtmlTable)table.getCellAt(0, 0).getChildElements().iterator().next()).getRow(0);
monthString = row.getCell(1).getTextContent();
monthString = monthString.substring(0, monthString.indexOf(' '));
}
DomNodeList<HtmlElement> aList = table.getElementsByTagName("a");
for (int i = 0; i < aList.size(); i++) {
HtmlAnchor anchor = (HtmlAnchor)aList.get(i);
if (anchor.getAttribute("title").equals(DomElement.ATTRIBUTE_NOT_DEFINED) || anchor.getAttribute("title").equals(DomElement.ATTRIBUTE_VALUE_EMPTY))
throw new RuntimeException("DomElement ATTRIBUTE_NOT_DEFINED or ATTRIBUTE_VALUE_EMPTY");
if (anchor.getAttribute("title").equals(month + " " + date)) {
anchor.click();
try { Thread.sleep(15000); } catch(InterruptedException e) {}
break;
}
}
HtmlImageInput imageInput = (HtmlImageInput)page.getElementByName("SearchAndBuy1$btnSearch");
page = (HtmlPage)imageInput.click();
System.out.println("clicked search button");
} catch(FailingHttpStatusCodeException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} catch(ElementNotFoundException e) {
e.printStackTrace();
} catch(IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
}

That image is not an input field, it's just a plain old image:
<img id="SearchAndBuy1_imgOutboundDate" disabled="disabled" alt="calendar"
CausesValidation="False" src="images/icon_calendar.gif" style="border-width:0px;" />
There are no JS handlers specified there, so they must be attached elsewhere, and seems it's at the bottom of the page:
Sys.Application.add_init(function() {
$create(AjaxControlToolkit.PopupControlBehavior,
{"PopupControlID":"SearchAndBuy1_panelOutboundDate","Position":3,"dynamicServicePath":"/default.aspx","id":"SearchAndBuy1_pceImageOutboundDate"}, null, null, $get("SearchAndBuy1_imgOutboundDate"));
});
When your program clicks on the image, there is no form submit, just an AJAX call (presumably), so you're right, you don't get a new page back. But as your code proves (I just ran it with a debugger), the content of the HtmlPage has changed, since it now contains the calendar widget, which you were able to pull details from.
It can be a bit confusing knowing when you will get a net new HtmlPage back, but usually it's only when you would see a whole new page in the browser. I've never tried HtmlUnit against something like Gmail, but I suspect you might only ever deal with the one HtmlPage object, and everything takes places within it.

Related

Getting Null pointer exception while trying to validate SVG element when it does NOT exist in UI - JAVA/selenium

public void rushitem(String rushi) {
try {
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT rfp_expdt_ind\n" +
"\tFROM e2e_rfpr_o.wrkflw_ap0001_rfp where rfp_case_id ='RFP-U500-3134';");
while (rs.next()) {
rushitem_sql = rs.getString(rushi);
System.out.println("Rush Indi from DB is : " + acctname_sql);
}
} catch (SQLException | NullPointerException e) {
e.printStackTrace();
}
}
public void validaterushitem() throws NullPointerException {
JavascriptExecutor js = (JavascriptExecutor) driver;
// WebElement rush1 = driver.findElement(By.xpath("(//*[local-name()='svg'])[4]"));
List<WebElement> rush = driver.findElements(By.xpath("(//*[local-name()='svg'])[4]"));
int checkLink = rush.size();
try {
if (rushitem_sql.equals("Y")) {
System.out.println("match successful for rush indicator");
WebElement rush1 = driver.findElement(By.xpath("(//*[local-name()='svg'])[4]"));
js.executeScript("arguments[0].setAttribute('style','border: 3px solid green;')", rush1);
} else System.out.println("match failed for rush indicator");
}
catch (NoSuchElementException e) {
e.printStackTrace();
} finally {
System.out.println("case is not rush item");
}
}
Inside chrome webbrowser, screen has multiple tabs where, 'svg element' icon exists. If 'rushitem_sql' = N or no record exists in Database then 'svg element' icon should not exist.
Screen layout is as follows:
chrome web browser has few tabs inside and each tab contains the element. I am navigating between each tab and verify icon exist or not.
Issue: if rushitem_sql = Y then it all works fine
but if rushitem_sql = N or no record exist in Database then tab1 works fine but navigating to tab 2 gives NULLPOINTEREXCEPTION.
Need help with this please.
I have tried many code changes but exception still there.
what am i missing?

How can I make a search box with suggestions?

I want to have a search box for my java application which has suggestions as you type. As I have it right now, it only gives results after you press the button to search, but I want to have it just like the youtube website where it comes up with suggestions as you type. The problem is that with how slow the api requests are, it isn't possible to make a request for each new character entered into the search box. Here's the code for searching (There should be five suggestions shown):
private SearchListResponse search(String query)
{
try
{
YouTube.Search.List request = youtube.search().list("snippet").setKey(API_KEY);
SearchListResponse response = request.setMaxResults(5L).setQ(query).setType("video").execute();
return response;
} catch (IOException e)
{
e.printStackTrace();
return null;
}
}
And here's the basic search box I have right now:
JTextField searchBox = new JTextField(20);
container.add(searchBox);
JButton searchButton = new JButton("Search");
searchButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
search(searchBox.getText());
}
});
container.add(searchButton);

Validation is not working if the account got created or not while testing in Selenium

After answers given by Anand and Prophet, I made the changes in the code but now it is not validating the test results whether the account got created or not. Ideally, it should validate whether after giving all the required information account got created or not. I am not sure where it went wrong please help me on the same.
package Seleniumtesting;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class Selenium {
ChromeDriver driver;
String url ="https://login.mailchimp.com/signup/";
public void invokeBrowser() {
try {
System.setProperty("webdriver.chrome.driver","C:\\Users\\hp\\Desktop\\Selenium\\chromedriver_win32\\chromedriver.exe");
driver = new ChromeDriver();
TimeUnit.SECONDS.sleep(2);
driver.get(url);
String urlFromWebpage = driver.getCurrentUrl();
if(urlFromWebpage.equals("https://login.mailchimp.com/signup/")) {
System.out.println("PASS");
}
else {
System.out.println("FAIL");
}
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
public void signup(){
try {
WebElement createAccountHeading = driver.findElement(By.xpath("//span[text()='Create an account or ']"));
if(createAccountHeading.isDisplayed()) {
System.out.println("PASS");
}else
System.out.println("FAIL");
driver.findElement(By.name("email")).sendKeys("Testvina12435#gmail.com");
driver.findElement(By.name("username")).sendKeys("Testvina1243");
driver.findElement(By.name("password")).sendKeys("Test123#");
TimeUnit.SECONDS.sleep(2);
driver.findElement(By.name("marketing_newsletter")).click();
TimeUnit.SECONDS.sleep(2);
//driver.findElement(By.xpath("//button[#id='create-account']")).click();
driver.findElement(By.xpath("//*[#id=\"create-account\"]")).click();
TimeUnit.SECONDS.sleep(2);
String u = driver.getCurrentUrl();
System.out.println("URL: "+u);
/*if(u.equalsIgnoreCase("https://login.mailchimp.com/signup/success/"))
{
System.out.println("PASS !! Account created successfully");
}
else
{
System.out.println("FAIL !! It might have not met the criteria");
}*/
driver.close();
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
public static void main(String[] args) {
Selenium mc = new Selenium();
mc.invokeBrowser();
mc.signup();
}
}
This you can use for Sign up:
driver.find_element(By. ID, "create-account").click()
The caveat is that it gets enabled only when the password criteria is met with, which for mailchimp is at least (as per the website) : 1 lower character, 1 upper character, 1 number, 1 special character, and minimum password length is 8.
I see you used your password as 'Test123' which would not enable the button, as the set criteria is not met. Please check the password rules given just below the password input box of the website.
UPDATE:
Per your latest comment, I am updating here.
I see that when I tested, it redirects to another page where it asks for email confirmation.
https://login.mailchimp.com/signup/success/?username=Test1243&userId=168758830&loginId=181489470
Now, there is /success/ in it. And I suppose you are using this page to assert that your act was successful; in which case, I would say that you used .equals in your code, which fails it as there is more to the url than you are looking for, so it should not be .equals, but it should something be like .contains or something like that (I do not know what Java uses, so please search for that equivalent keyword)
UPDATE (Java code edit of #vicky per request)
public void signup(){
try {
WebElement createAccountHeading = driver.findElement(By.xpath("//span[text()='Create an account or ']"));
if(createAccountHeading.isDisplayed()) {
System.out.println("PASS");
}else
System.out.println("FAIL");
driver.findElement(By.name("email")).sendKeys("Testvina12435#gmail.com");
driver.findElement(By.name("username")).sendKeys("Testvina1243");
driver.findElement(By.name("password")).sendKeys("Test123#");
TimeUnit.SECONDS.sleep(2);
// code edit by #anandgautam
driver.findElement(By.xpath("//div[#id='onetrust-close-btn-container")).click();
TimeUnit.SECONDS.sleep(1);
driver.findElement(By.name("marketing_newsletter")).click();
TimeUnit.SECONDS.sleep(5);
// end of code edit by #anandgautam
//driver.findElement(By.xpath("//button[#id='create-account']")).click();
driver.findElement(By.xpath("//*[#id=\"create-account\"]")).click();
TimeUnit.SECONDS.sleep(2);
String u = driver.getCurrentUrl();
System.out.println("URL: "+u);
/*if(u.equalsIgnoreCase("https://login.mailchimp.com/signup/success/"))
{
System.out.println("PASS !! Account created successfully");
}
else
{
System.out.println("FAIL !! It might have not met the criteria");
}*/
driver.close();
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
Your password is missing a special character. The Sign Up button not appearing on that page until you filled all the fields with valid data.
So if you change your password from Test123 to f.e. Test123$ you will be able to see, locate and click the Sing Up button with this code:
driver.findElement(By.xpath("//button[#id='create-account']")).click();

Dymanically changing table content in java selenium

Requirement: In our application, when I click on scan button, the Status will be "In Progress". I should keep clicking on "Refresh button", the "Stop" Status changes to "Time, date, year", it means the scan has completed. Below is the piece of code I written, but its not working.
public void verifyScanComplete(String networkName)
{
int i=0;
try{
//here I am searching for the string "In Progress" in the page
List<WebElement> stopStatus = driver.findElements(By.xpath("//*[text()='In Progress']"));
//this is the element stop status which will change from "In Progress" to "dd/mm/yy"
WebElement stopStatusChanged = driver .findElement(By.xpath("//*[#id='div_scan_set']/form/div/table/tbody/tr/td[text()='"+networkName+"']/../td[10]"));
while ((stopStatusChanged.getText().contains("In Progress")))
{
WebUtils.sleep(40000);
driver.navigate().refresh();
i++;
}
}
catch (Exception e) {}
}

isTextPresent fails all the time in Selenium test. Not sure if I am doing anything wrong

I have this little piece of code that just checks for a particular text at a location on the page and if that text is found, it will check for something else..Here is the snippet:
if (!selenium.isTextPresent("//div[contains(concat('',#class,''),'contentLg')]/h2")) {
System.out.println("The About Us text is not present");
}
else {
verifyEquals(aboutText, "//*[#class='content contentLg']/p[3]");
}
Here is the generated output that I am trying to grab the text "About Us" from. I am trying to see if the page has "About Us" text (which is in tag). If there is, just match one of the "p" tag with predefined text:
<!-- MAIN CONTENT CONTAINER -->
About Us
<p><span class="faqQuestion">About The Site</span><br>
this is about the site</p>
<p>test one two three</p>
<p>this test test test test test test</p>
<br>
<p><span class="faqQuestion">About Company</span><br>
This is about the company</p>
<p>fafasdfsafasdfafasfasfasasfasfasfafsasf</p>
<p>afasfasdfasdffafffffffffffffffffffffffffffffffffffffffffffffffffffffffffff</p>
<br>
<p><span class="faqQuestion">Helping Businesses</span><br>
Helping business
click here to learn more.</p>
Here is what I wrote in a CustomSelenium class that extends DefaultSelenium.
public boolean waitForTextPresent(final String text, long timeout) {
Wait wait = new Wait() {
#Override
public boolean until() {
try {
return CustomSelenium.this.isTextPresent(text);
} catch (SeleniumException e) {
return false;
}
}
};
try {
wait.wait("Error: text " + text + " not present in the page", timeout, 50);
} catch (NumberFormatException e) {
log.error(e.getMessage(), e);
throw e;
} catch (WaitTimedOutException e) {
log.warn(e.getMessage(), e);
return false;
}
return true;
}
Just call this before you call isTextPresent. This is a Selenium bug.

Categories

Resources