Two different elements with same xpath? - java

I am trying to test this website by using JUnit and Selenium:
https://www.oanda.com/currency/converter/
I tried to select Unit from “Currency I Have” as well as "Currency I Want". Then I found out that the xpaths are the same. Only the "Currency I Have" codes can be run successfully. "Currency I want" always fail.
The Xpath is driver.findElement(By.xpath("//span[text() = 'GBP']")).click();
Could someone help on this? Thanks.
Code1:
public class Currency_I_Have {
WebDriver driver = new FirefoxDriver();
#Before
public void setUp() throws Exception {
driver.manage().window().maximize();
driver.get("https://www.oanda.com/currency/converter/");
}
#Test
public void test() {
driver.findElement(By.id("quote_currency_input")).click();
driver.findElement(By.xpath("//span[text() = 'GBP']")).click();
WebElement Amount = driver.findElement(By.id("quote_amount_input"));
Amount.clear();
Amount.sendKeys("100");
}
}
Code2:
public class Currency_I_Want {
WebDriver driver = new FirefoxDriver();
#Before
public void setUp() throws Exception {
driver.manage().window().maximize();
driver.get("https://www.oanda.com/currency/converter/");
}
#Test
public void test() {
driver.findElement(By.id("base_currency_input")).click();
driver.findElement(By.xpath("//span[text() = 'GBP']")).click();
WebElement Amount = driver.findElement(By.id("base_amount_input"));
Amount.clear();
Amount.sendKeys("200");
}
}

I count 4 elements on that page matching that XPath. (Although on further inspection it looks like you could go with either in each pair, since they are dupes.) What you need to do is find unique parent elements for the specific span you want. For example the two unique matching elements could also be referenced more uniquely via:
//div[#id='quote_currency_selector']//span[text()='GBP']
(I think this is the one you want)
The other one could be referenced more uniquely via:
//div[#id='base_currency_selector']//span[text()='GBP']
I got the "quote currency selector" and "base currency selector" bits from "ancestor" DIVs that were "higher up" the XML tree from the "GBP" entries in the drop downs.

Related

Selenium cannot find ul Element that is visible on Page

I'm currently testing an email service, and upon opening a list of options to filter email, I want to be able to automate clicking on an option in the list. The code for the list is:
However, selenium cannot find this element, even though I can find it by searching the HTML using CTRL+F. The code I'm currently using to try and find and click this list element is:
wait.until(ExpectedConditions.visibilityOfElementLocated(org.myorg.automation.Objects.ManageEmails.Locators.FilterList));
Select dropdown = new Select(driver.findElement(org.myorg.automation.Objects.ManageEmails.Locators.FilterList));
dropdown.selectByVisibleText("Unread");
The xpath of the list is:
/html/body/div[7]/div/div/div/div/div/div/ul
Any help would really be appreciated!!
The problem is that you don't have a select in this case and the: Select dropdown = new Select(); wont work. You'll need a custom method to select a value from that list
public class Testing {
public WebDriver driver;
#Test
public void TestSomething() {
driver = new ChromeDriver();
driver.get("<the url where this list is present>");
// assuming that the ul list is unique on the page if not find another way to get it
WebElement ulListParent = driver.findElement(By.xpath("//ul[contains(#class,'ms-ContextualMenu-list is-open')]"));
SelectBasedOnValue(ulListParent, "Unread");
driver.close();
}
public void SelectBasedOnValue(WebElement parentElement, String optionValue) {
parentElement.findElement(By.xpath(String.format("//li[text()='%s']", optionValue))).click();
}
}

Selenium - Issue while trying to select from a dropdown

I need a little help. I'm trying to run an automated test on the website http://zara.com and i want to select the language from the language dropdown.
This is the HTML code from Zara. https://prntscr.com/g6hdiv
This is the code i've tried with Selenium 2.53 in IntelliJ
public class RegistrationTest {
WebDriver driver;
#Before
public void setUp(){
driver = new FirefoxDriver();
driver.get("http://zara.com");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
#After
public void tearDown(){
driver.quit();
}
#Test
public void test(){
WebElement languageDropdown = driver.findElement(By.id("language"));
Select selectLanguage = new Select(languageDropdown);
selectLanguage.selectByValue("en");
}
}
I always receive the error below even if I've tried in different setups but it didn't work.
org.openqa.selenium.ElementNotVisibleException: The element is not currently visible and so may not be interacted with
Could you please tell me what am I doing wrong?
Appreciate the help.
The element is not currently visible and so may not be interacted with
You need to scroll the page, so that the element is in the current viewport. Something like this:
WebElement languageDropdown = driver.findElement(By.id("language"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", languageDropdown);
Select selectLanguage = new Select(languageDropdown);
selectLanguage.selectByValue("en");

How to Write a Function for WebElement Click in Selenium Webdriver

I am Having a Lot of WebElements
For Example I Declared a WebElement a
#FindBy(id="BtnLogin")
private WebElement btnLogin;
In the Same Manner I created "N" number of WebElements
Every time I Cant use "driver.findElement()" function So I wrote a function
public static void WebElementClick(WebElement we)
{
we.click();
}
When Ever the Control is Going to The Line we.click() in the WebElementclick Function it is Showing NullPointerException as a Result My Purpose is Failing
I am Not Getting What to Do,Some One Please Help Me on this :)
Your WebElementClick should receive the selector and it should: find element -> click, you can get an example from the above link.
In your case you it seems that you are not using wait and the WebElementClick it tries to click on the string.
Using find will return an object that will make click available.
The method should contain something like: driver.findElement(By.xpath("your_selector"));
Ant then use click on what this method returns.You can use also css if you want to.
public class testJava{
#Test
public void testMethod() throws InterruptedException {
WebDriver driver = new FirefoxDriver();
pageClass pageClass = PageFactory.initElements(driver, pageClass.class);
driver.get("http://www.facebook.com");
Thread.sleep(5000);
pageClass.clickLoginBtn();
}}
public class pageClass {
#FindBy(id = "loginbutton")
private WebElement loginBtn;
WebDriver driver;
public pageClass(WebDriver driver) {
this.driver = driver;
}
public void clickLoginBtn()
{
click(loginBtn);
}
public void click(WebElement we)
{
we.click();
}}
Its best practice to use the page class & test class..Try this it will help you i guess.
You are suppose to use driver to find & click the element.
I think that driver may try to click element before it's presented. Good practice before clicking WebElement is to wait for WebElement being clickable. I would try:
public static void WebElementClick(WebElement we)
{
wait.forElementClickable(we);
we.click();
}

JUnit/Selenium: Splitting my class to use the Page Object Model

realise this might be a bit of a big ask, but I'm having trouble splitting my test class to use the Page Object Model.
My current class basically works as so:
#BeforeClass - startUp() Loads properties file for variables and starts ChromeDriverService
#Before - createDriver() Opens Chrome browser, and navs to homepage
#Test - desktopHappyCallback() Does some page interaction, then calls:
hideDynamicElements() Hides some elements on the page
runScreenshotValidation() Saves a screenshot and compares it by calling:
compareScreen() Compares and returns a true/false
#After - tearDown() Quits the ChromeDriver
#AfterClass - stopService() Kills the ChromeDriverService
The class is currently (have cut bits out of the methods to make it shorter):
public class desktopHappy {
private static ChromeDriverService service;
private static WebDriver driver;
private static Properties obj = new Properties();
//Set up screenshot comparison via im4java
private static boolean compareScreen(String expectedImage, String currentImage, String diffImage) {
CompareCmd compare = new CompareCmd();
compare.setErrorConsumer(StandardStream.STDERR);
IMOperation comparisonExe = new IMOperation();
comparisonExe.metric("mae"); //mae = Mean Absolute error (average of all the color differences)
comparisonExe.addImage(currentImage);
}
//Compare via ImageMajick
private void runScreenshotValidation() throws IOException, InfoException {
String current = "screenshots\\current\\Current.png";
boolean compareSuccess = compareScreen(baseline, current, difference); //Run the compare method
}
}
//Hide dynamic elements on the page (if they exist)
private void hideDynamicElements() throws IOException, InterruptedException {
List<By> criteria = Arrays.asList(
By.className("telephone-number"),
By.cssSelector("#chatContainer"),
);
for (By dynamicElement : criteria) { //Loop through the criteria
List<WebElement> elements = driver.findElements(dynamicElement);
for (WebElement hideElement : elements){ //Loop through each instance of an element
((JavascriptExecutor) driver).executeScript("arguments[0].style.visibility='hidden'", hideElement);
}
}
#BeforeClass //Pulls in Properties, and starts up the ChromeDriverService before the Tests run
public static void startUp() throws IOException {
FileInputStream propfile = new FileInputStream(System.getProperty
("user.dir") + "\\src\\main\\resources\\config.properties");
obj.load(propfile);
service = new ChromeDriverService.Builder()
.usingDriverExecutable(new File(obj.getProperty("chromeDriverLoc"))) //Driver set in properties
.usingAnyFreePort()
.build();
service.start();
}
#Before //Starts up the Chrome browser (on home page) before each Test
public void createDriver() {
driver = new RemoteWebDriver(service.getUrl(), DesiredCapabilities.chrome());
driver.get(obj.getProperty("targetENV")); //Opens home page (set in properties)
}
#Test //Checks the Callback form (modal)
public void desktopHappyCallback() throws Exception {
driver.findElement(By.cssSelector("#callbackInputPhone")).sendKeys(obj.getProperty("formsPhone"));
driver.findElement(By.xpath("//input[#value='Request a callback']")).click();
WebDriverWait waitForSuccessMessage = new WebDriverWait(driver, 5);
waitForSuccessMessage.until(ExpectedConditions.elementToBeClickable
(By.cssSelector("#callbackForm > div.success-message")));
hideDynamicElements(); //Run the hide dynamic elements method
runScreenshotValidation(); //Run the screenshot comparison method
}
#After //Quits the ChromeDriver after each Test
public void tearDown() throws Exception {
driver.quit();
}
#AfterClass //Kills the ChromeDriverService at end of Tests
public static void stopService() {
service.stop();
}}
So in IntelliJ I've tried to split up my project with packages as so:
I've been trying to move into the baseCompare class:
hideDynamicElements()
compareScreen()
runScreenshotValidation()
Then into the baseSetup class:
startUp()
createDriver()
tearDown()
stopService()
Then homePage will contain my representations and desktopHappy will contain my test assertions.
However I'm getting really stuck working out how to split things up so that they work together. Is anyone able to give me an example on how I should be splitting things up under these packages? (sorry big ask!)
I think you are dividing your logic very fairly.
The only thing that i would change, is to have your base* classes under your base package, rather than an actual physical base package.
For example:
com.salessite/
baseCompare.java
baseSetup.java
basePage.java
baseTest.java
pages/
homePage.java < basePage.java
tests/
desktopHappy.java < baseTest.java
Also by creating more base's, you give yourself more leeway for future changes.
so that they work together
IF by work you mean, compile - then you should have no problem. say for example that homePage.java extends basePage.java, then in homePage.java, you'd have the appropriate import.
import com.salessite.basePage;
Importing is how to access external classes and references. (access modifiers permitting, of course.)

Getting webelement from dynamic text

firstli i write my scenario:
go http://demo.opencart.com/
search ipod
click add to compare in every found items
here is my code (java webdriver pagefactory)
searchresultspage (my object page)
#FindBy(id = "compare-total")
WebElement numberOfProductToCompare;
public void compareAllItems() {
for (WebElement compareButtons: compareButton) {
compareButtons.click();
}
}
public void areAllItemsClickedCompare() {
String text = numberOfProductToCompare.getText();
System.out.println(text);
}
My main test class
#Test
public void addToCompare() {
searchresultspage.compareAllItems();
searchresultspage.areAllItemsClickedCompare();
}
i click all compare buttons and i want to get number from link Product Compare (4) but when i use searchresultspage.areAllItemsClickedCompare(); then System.out.println(text); print me Product Compare (0), even this method is after adding to compare (should be should be Product Compare (4)) Dont know what to do, some advice?
Think, the problem appears because the compare-total element is captured by Selenium on class instantiating, but when its content is updated on the page, it doesn't affect the captured value.
Try to capture the compare-total element only after all checkboxes were clicked:
public void areAllItemsClickedCompare() {
WebElement numberOfProductToCompare = driver.findElement(By.id("compare-total"));
String text = numberOfProductToCompare.getText();
System.out.println(text);
}
Where driver is your WebDriver instance.

Categories