I am automating UI flow using Webdriver and Java. Need help in the following:
Clicking a link, verifying the title, clicking browser back button - these steps are repeated for number of links in the content. I am using page object design and all the objects are in different class. My code is:
objectBase.clickLink1();
titleVeri(pageTitle1);
driver.navigate().back();
objectBase.clickLink2();
titleVeri(pageTitle2);
driver.navigate().back();
objectBase is the name of the object where I kept all my page objects. clickLink1 and clickLink2 are methods on page objects class which does clicking on links. titleVeri is utility method for verifying the title.
What I need is construct this inside loop as I have more this.
you could use a map for this, make a method clickLink(key) in objectBase
then do something like
Map<String,String> myMap = new TreeMap();
myMap.put("1",pageTitle1);
myMap.put("2",pageTitle2);
for(Map.Entry<String,String> entry : myMap.entrySet()){
objectBase.clickLink(entry.getKey());
titleVeri(entry.getValue());
driver.navigate().back();
}
What you are describing is not strictly possible. The reason is that you cannot have a pointer to a function.
However, you said that you are using the Page objects pattern. Rather than using the clickLink1() function, do you have a function that returns link1()? That way you could use a Map (like BevynQ said).
Map<WebElement, String> linksAndTitles = new HashMap();
linksAndTitles.put(page.getHomePageLink(), "Home");
linksAndTitles.put(page.getUserPageLink(), "Contact Details");
...and so on for each of the different links...
for (WebElement link: linksAndTitles.keySet()){
link.click();
titleVeri(linksAndTitles.get(link));
driver.navigate().back();
}
As a side note...if one of those links is the Logout link...that has to be tested seperatly.
Furthermore...I really don't recommend this test...it's likely just a waste of time. On each of your pages, in your isLoaded() function, you should test the title. That way, whenever you call page.get(), the title will be automatically tested, and it isn't part of your test.
Related
Each time the web page has changes I want to get the text elements of web page. So for having the text elements, here is my method:
public void getContentPage(WebDriver driver) {
WebDriverWait wait = new WebDriverWait(driver, 15);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.tagName("body")));
System.out.println(element.getText());
}
What I need is a kind of listener using Selenium to call the above method each time there are changes in HTML body content:
public void listen (WebDriver driver) {
// some kind of listner that waits for any changes to happen in HTML
if (changed) getContentPage(driver);
else keeplistning()
}
I'm not sure there is a way to track all and every change on the page and I'm not sure you want this since this will trigger you on many irrelevant changes.
What can be useful here is to track changes on some specific relevant element(s).
So, to wait until some specific element is changed you can use refreshed ExpectedCondition like the following:
WebElement button = driver.findElement(By.id("myBtn"));
wait.until(ExpectedConditions.refreshed(button));
In case you wish to monitor several elements it will be something like this:
wait.until(ExpectedConditions.or(
ExpectedConditions.refreshed(element1),
ExpectedConditions.refreshed(element2),
ExpectedConditions.refreshed(element3)));
You should, of cause, wrap this in some method according to your specific code use. I wrote here the basic idea only.
UPD
To track the entire page you can use driver.getPageSource(); method. Polling the page state with some time interval and comparing the value of previous result of this method with the new result will give you indication of any page content change.
I am trying to automate testing with Selenium Webdriver without the need of xpath. I'm facing problem when the site is modified then xpath is being changed. For elements(like buttons, drop downs etc) which needs some action to be performed any how it needs xpath or someother things to identify that element. If I want to fetch data(table contents) from site to validate its excecution,then here I will need lots of xpaths to do so.
Is there a better way to avoid some xpaths?
Instead of using xpath, you can map the elements by css selectors, like this:
driver.findElement(By.cssSelector("css selector"), OR
by ID, like this:
driver.findElement(By.id("coolestWidgetEvah")).
There are much more than these 2. See Selenium docomentation
Steven, you basically have 2 choices the way I see it. One is to inject your own attributes (i.e qa attrib for instance) into your web elements which will never change. Please see this post, on how you can achieve this:
Selenium: Can I set any of the attribute value of a WebElement in Selenium?
Alternatively you can still use 'naked' xpath in order to locate your elements.
By 'naked' i mean generic, so not so specific.
Consider this element sitting below this:
div id="username"
input class="usernameField"
button type='submit
So, instead of locating it like this (which is specific/aggresive):
//div[#id='username']//input[#class='usernameField']//button[#type='submit']
you can use a more mild approach, omitting the specific values, like so:
//div[#id]//input[#class]//button[#type]
Which is less likely to break upon change. However, beware you need to be 100% sure that with the 2nd approach you are locating a unique element. In other, words if there are more than 1 buttons you might select the wrong one or cause a Selenium exception.
I would recommend this Xpath helper add-on for Chrome which highlights on the screen when your xpath is correct and also shows you how many elements match you Xpath (i.e. unique or not?)
xpath Helper
Hope the above, makes sense, don't hesitate to ask if it does not!
Best of luck!
Ofcoarse there are certain other ways without using id/xpath/CSS and even "sendKeys". The solution is to do that via Sikuli.
Things to do:
You have to download the Sikuli exe jar (sikulixsetup-1.1.0). (from https://launchpad.net/sikuli/+download)
Install the Sikuli exe jar which extracts the "sikulixapi" and adds to the PATH variable.
Add the External jar "sikulixapi" at project level through Eclipse.
Now take images of the elements where you want to pass some text or click.
Use the reference of the images in Selenium Java code to write text & perform clicks.
Here is a simple code to browse to "https://www.google.co.in/" move on to Login page & enter Emailid & Password without any xpath or sendkeys.
package SikuliDemo;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.sikuli.script.Pattern;
import org.sikuli.script.Screen;
public class SikuliDemoScript {
public static void main(String[] args) throws Exception
{
Screen screen = new Screen();
Pattern image1 = new Pattern("C:\\Utility\\OP_Resources\\Sikuli_op_images\\gmailLogo.png");
Pattern image2 = new Pattern("C:\\Utility\\OP_Resources\\Sikuli_op_images\\gmailSignIn.png");
Pattern image3 = new Pattern("C:\\Utility\\OP_Resources\\Sikuli_op_images\\Email.png");
Pattern image4 = new Pattern("C:\\Utility\\OP_Resources\\Sikuli_op_images\\EmailNext.png");
Pattern image5 = new Pattern("C:\\Utility\\OP_Resources\\Sikuli_op_images\\Password.png");
Pattern image6 = new Pattern("C:\\Utility\\OP_Resources\\Sikuli_op_images\\SignIn.png");
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://www.google.co.in/");
screen.wait(image1, 10);
screen.click(image1);
screen.wait(image2, 10);
screen.click(image2);
screen.type(image3, "selenium");
screen.click(image4);
screen.wait(image5, 10);
screen.type(image5, "admin123");
screen.click(image6);
driver.quit();
}
}
Let me know if this answers your question.
I'm using HtmlUnit in Java to deal with a DropDown Window (Java).
I tried as User skaffman suggests:
WebDriver driver = new HtmlUnitDriver();
driver.get("https://...");
......................
WebClient client = new Webclient();
Page page = client.getPage("https://...");
HtmlSelect select = (HtmlSelect) page.getElementById(mySelectId);
HtmlOption option = select.getOptionByValue(desiredOptionValue);
select.setSelectedAttribute(option, true);
It does not recognize: getElementById. Eclipse recommends to swith to findElement(By.id(" ")) PLEASE HELP
I agree with my college. The above code is correct, make sure you set javascript enabled, otherwise you will have issues with HtmlUnit
driver = new HtmlUnitDriver();
((HtmlUnitDriver) driver).setJavascriptEnabled(true);
In your code, you are declaring the local variable to be of the type Page that will contain the return value from client.getPage("https://...");
Although it's usually good practice to develop toward the generic interface (in this case, Page), the generic interface does not contain the method to getElementById(...).
Try changing your 4th line of code to the following:
HtmlPage page = client.getPage("https://...");
(I am assuming that the conent being returned by client.getPage("https://..."); is of MimeType text/html).
You could also use XmlPage or XhtmlPage, depending on your MimeType.
If it is none of these that you are retrieving via client.getPage("https://...");, then you should not be attempting to call getElementById on a structure that does not have this as part of its API.
In my Wicket application I used one radio button with "yes" and "no" options. If I select "No", I should display one dropdown choice. I wrote code using AjaxFormChoiceComponentUpdatingBehavior. How do I unittest this using WicketTester?
Solution for Wicket 1.5.x:
AbstractAjaxBehavior behavior = (AbstractAjaxBehavior)WicketTesterHelper.
findBehavior(getTester().getComponentFromLastRenderedPage("path:to:component"),
AjaxFormChoiceComponentUpdatingBehavior.class);
getTester().executeBehavior(behavior);
First select the radio button that you want.
form.select("path to radio button", 0/1)
Then execute ajax behaviour:
tester.executeBehavior((AbstractAjaxBehavior)tester.getComponentFromLastRenderedPage("path to radio buttons").getBehaviors().get(0));
Here is my piece of code which works perfectly for me with select box but should fiat as well for radio button if you change Behaviour class. Needed steps are:
Insert new value into form (use FormTester)
Find behaviour
Execute behaviour on change
Here is an example of code:
//simulate insert new value
FormTester formTester = tester.newFormTester(PANEL_ID + FORM);
formTester.setValue("selectBox", "newValue");
//Find onchange behaviour
AjaxFormComponentUpdatingBehavior behavior =
(AjaxFormComponentUpdatingBehavior) WicketTesterHelper.findBehavior(
tester.getComponentFromLastRenderedPage(PANEL_ID + FORM + ":" + "selectBox"),
ajaxFormComponentUpdatingBehavior.class);
//execute onchange
tester.executeBehavior(behavior);
I missed the par how to update form value in previous answers.
If the radio button is on a form I think you should use the FormTester class:
http://wicket.apache.org/apidocs/1.4/org/apache/wicket/util/tester/FormTester.html
For an example of an Ajax form submit test you can take a look at:
http://www.java2s.com/Open-Source/Java-Document/J2EE/wicket-1.4/org/apache/wicket/ajax/form/AjaxFormSubmitTest.java.htm
Try something like this:
tester.executeAjaxEvent("form:myRadioButtonId", "onchange");
This turns out to be somewhat painful, at least in Wicket 1.4 (I haven't tried with 1.5).
Via a web search, I found hints in Mischa Dasberg's blog. Basically, you can't use the BaseWicketTester.executeAjaxEvent((String componentPath, String event) method because the behavior you're using isn't an AjaxEventBehavior and you can't use the BaseWicketTester.executeBehavior(final AbstractAjaxBehavior behavior) because it wipes out the request parameters.
Mischa's solution was to implement his own executeBehavior method in a parent test case, which worked for his situation, but not for my need, as it assumed the request parameter id was the same as the full component path.
I've done something similar by implementing my own executeAjaxBehavior in an extension of WicketTester, but assuming (as is true in my case) that the request parameter is the last ":" separated section of the component path:
public void executeAjaxBehavior(String path, String value) {
AbstractAjaxBehavior behavior = (AbstractAjaxBehavior) getComponentFromLastRenderedPage(path).getBehaviors().get(0);
CharSequence url = behavior.getCallbackUrl(false);
WebRequestCycle cycle = setupRequestAndResponse(true);
getServletRequest().setRequestToRedirectString(url.toString());
String[] ids = path.split(":");
String id = ids[ids.length-1];
getServletRequest().setParameter(id, value);
processRequestCycle(cycle);
}
Both his solution and mine (based on his) also assume that the behavior is the first (or only) one on the component.
This is a bit clunky, but something like this may work for you.
It might be better if the ids and behavior were gotten separately and passed as parameters, and of course you might do well to find the first behavior that actually was an AjaxFormChoiceComponentUpdatingBehavior instead of blithely assuming it was the first behavior, but this is a start.
This is also similar code to what's inside the BaseWicketTester class for the other behavior testing methods, which might be worth looking through.
I need to execute the following steps:
1. Start an IE browser window and open a URL (Done using StartBrowser(final string URL)
2. Start a session (done by logging in)
3. Now, I want to enter a different URL in the same browser window which has the same session.
My question is related to Step 3. How can I overwrite the URL in the existing IE window.
Note: I am using a keyword driven framework written in java.
From the IBM RFT online help: You can use the loadURL() method of the browser object.
If you do not have the browser object already 'learned' into your object map, just record a click on the browser toolbar. Then you can modify that line to be Browser_htmlBrowser().loadURL("http://stackoverflow.com");
Thanks Tom. I agree that loadURL has the implementation to do what I need.
There is one more aspect that may interest others looking at this question, i.e. the way the appropriate browser object is captured. Obviously the easist way is to use the RFT record and click way, and use the appropriate recognition properties or the other way is to implement it is find the existing browseron the fly when the method is called irrespective of recognistion properties etc which may be more useful for some scenarios or frameworks, like it is done below.
RootTestObject root = getRootTestObject();
TestObject[] testobj = root.find(atDescendant(".class", "Html.HtmlBrowser"));
BrowserTestObject bto;
bto = new BrowserTestObject(testobj[0]);
bto.loadUrl(curParamOne);