how to deal with reused elements in selenium (duplication) - java

I am unable to locate element that is a button.
1st Button
<div class="col-md-12 col-sm-12 col-xs-6">
<input type="hidden" value="113" name="vendor_id"/>
<input id="vendor_submit" class="btn btn-primary mb10 SaveBtn" type="submit" value="Save & Close" name="submit"/>
I have used this command to locate it
driver.findElement(By.xpath(".//*[#id='vendor_submit']") ).click();
2nd Button
<div class="col-md-12 col-sm-12 col-xs-6">
<input type="hidden" value="113" name="vendor_id"/>
<input type="hidden" value="" name="vendor_hr_account_id"/>
<input id="vendor_submit" class="btn btn-primary mb10 SaveBtn" type="submit" value="Save" name="submit"/>
Problem
Now as they both are on same page i am unable to locate 2nd button due to duplication factor. Only the difference is type.
1st has value="Save & Close"
2nd has value="Save"
Please help me to locate 2nd button.

If there are two elements with the same id, I would suggest you try using cssSelector with its attribute value which would be unique for both and much faster than xpath as below :-
driver.findElement(By.cssSelector("input#vendor_submit[value = 'Save']")).click();
Edited1 :- If you are getting element is not visible exception when you're going to click, you should wait before click using WebDriverWait until element visible and clickable as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement submit = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("input#vendor_submit[value = 'Save']")));
submit.click();
Edited2 :- If unfortunately above does not work, try to click using JavascriptExecutor as below :-
WebElement el = driver.findElement(By.cssSelector("input#vendor_submit[value = 'Save']"));
((JavascriptExecutor)driver).executeScript("arguments[0].click()", el);

You can use only the value Attribute in xpath:
driver.findElement(By.xpath(".//input[#value='Save']")).click();

You can differentiate by adding the value condition also in your xpath.
So basically you can use.//*[#id='vendor_submit' and #value='Save'] instead in your driver.findelement

You can use absolute xpath for both the button, as their positions are different in HTML.
For eg : html/body/div[1]/div[3]/form/div[2]/div[2]/div[1]/div[1]/div[3]
To get this add plugin firebug and firepath in mozilla and get absolute xpath from there by inspect element.

Related

no such element: Unable to locate element: {"method":"css selector","selector":"input#btnshow"}

I am a beginner in selenium, I am using java for that, I am getting a error saying Unable to locate element although that element is present in the web page.
Java Code:
WebDriver dChromedriver=new ChromeDriver();
dChromedriver.get("https://erp.mitwpu.edu.in/");
dChromedriver.manage().window().maximize();
WebElement txtPassword=dChromedriver.findElement(By.id("txtPassword")) ;
WebElement txtUserId=dChromedriver.findElement(By.id("txtUserId")) ;
txtUserId.sendKeys("S1032200787");
txtPassword.sendKeys("FynS#3XbZH6ZMWH");
//
WebDriverWait w =new WebDriverWait(dChromedriver, Duration.ofSeconds(30));
w.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[#id='ReCaptchContainer']")));
dChromedriver.findElement(By.xpath("//div[#id='ReCaptchContainer']")).click();
// Thread.sleep(3000);
w.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("label#lblMessage")));
WebElement success_lablElement=dChromedriver.findElement(By.cssSelector("label#lblMessage"));
Assert.assertEquals(success_lablElement.getText(),"Success" );
dChromedriver.findElement(By.id("btnLogin")).click();
WebElement resultWebElement=dChromedriver.findElement(By.xpath("//nav[#class=\"mt-2\"]/ul/li[12]/a[#href=\"Examination/Report/StudentGradeCardDetail.aspx?MENU_CODE=Web_Result\"]"));
resultWebElement.click();
Thread.sleep(30000);
dChromedriver.findElement(By.cssSelector("input#btnshow")).click();
html code:
<div class="labelinfo col-md-12 col-sm-7 col-xs-12 padd6"> <input type="submit" name="btnshow" value="Show" onclick="return funValidation();" id="btnshow" class="btn btn-primary" style="">
<input type="submit" value="Show" onclick="return funValidation();" id="btnshow" class="btn btn-primary" style="">
</div>
The element Show button is inside an iframe.
In order to access the element, you need to switch to iframe first and then you can access the element.
Use WebDriverWait() and wait for frameToBeAvailableAndSwitchToIt() and wit for elementtobeclickable() to click on the Show button.
WebDriverWait w =new WebDriverWait(dChromedriver, Duration.ofSeconds(30));
w.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("FrameContent")));
w.until(ExpectedConditions.elementToBeClickable(By.id("btnshow"))).click();
To jump out from iframe you need to use this code.
dChromedriver.switchto().defaultcontent();
Snapshot iframe:

#FindBy Selenium how to find ::before

::before
I have following structure on site and ::before is checkbox where I'm supposed to click, found some topics, but there was no #FindBy annotation. Is it possible to find this ::before in code?
<span class="jJ">
<label class="kJ" data-test-id="checkbox_bonus_card">
<input class="mJ" type="checkbox" name="hasBonusCard" value="">
<span data-test-id="checkbox_bonus_card_text" class="lJ">
::before
</span>
</label>
</span>
I tried #FindBy(xpath = "//label[#data-test-id='checkbox_bonus_card'//span['::before']") but it didn't work.
If I use something like this:
#FindBy(xpath = "//input[#name='hasBonusCard']")
WebElement checkboxBonusCard;
Error appears:
Caused by: ElementClickInterceptedException: element click intercepted: Element <input class="mJ" type="checkbox" name="hasBonusCard" value=""> is not clickable at point (568, 78). Other element would receive the click: <span class="jJ">...</span>
I think it's in input field that you wanna interact with :
#FindBy(name = "hasBonusCard")
WebElement bonusCard;
:: basically means this :
In CSS, ::before creates a pseudo-element that is the first child of
the selected element. It is often used to add cosmetic content to an
element with the content property.
More :
Since ::after & ::before are a pseudo element which allows you to
insert content onto a page from CSS (without it needing to be in the
HTML). While the end result is not actually in the DOM, it appears on
the page as if it is - you see it but can't really locate it with
xpath for example
Read more here

selecting input-field via placeholder - Element is not visible

Having a hard time entering text into the credentials page on:
Pixiv
<div class="input-field-group">
<div class="input-field">
<input placeholder="E-mail address / pixiv ID" autocapitalize="off" value="" type="text">
</div>
<div class="input-field">
<input placeholder="Password" autocapitalize="off" value="" type="password">
</div>
</div>
I am selecting the field using the following code as id attribute is not available:
driver.findElement(By.xpath("//input[#placeholder='Password']"));
but I am unable to manipulate the element via sendKeys nor clear.
it throws the following exceptions respectively:
org.openqa.selenium.ElementNotInteractableException: Element is not visible
org.openqa.selenium.InvalidElementStateException: Element is not currently interactable and may not be manipulated
There are actually two elements on this page that use that XPath. The webdriver will choose the first element that meets the requirements set by the developer. Unfortunately the element you want is the second element in the DOM. However updating your XPath to be more specific will help:
driver.findElement(By.xpath("//div[#id='container-login']//input[#placeholder='Password']"));

Selenium WebDriver Java - Element is not visible

I am new to Selenium WebDriver tests and I try to use it at work. I tried many combinations of selectors, xpaths and so on, but I can't move past it. I searched also many similiar topics on stackoverflow, sadly without expected results. What I need is to be able to click on "NO SERVICE" button (a href). When I try, I keep getting error, that this element is not visible. When I try to handle this error using "wait"s, I keep getting another error "Expected condition failed: waiting for visibility of element...". What am I doing wrong?
My code:
WebDriverWait waitWait = new WebDriverWait(driver, 40);
waitWait.until(ExpectedConditions.visibilityOfElementLocated(By.className("withoutService")));
WebElement x = driver.findElement(By.className("withoutService"));
x.click();
and also a html code snippet from webpage:
<div id="fancybox-outer">
<div id="fancybox-content">
<div style="width:auto;position:relative;">
<div id="serviceReminder" style="width: 765px">
<form id="serviceReminderFrom" method="post">
<div class="homeMessage">
<div class="innerMessage">
<input type="hidden" id="serviceToAddReminderFromAction" name="F_ACTION" value="">
<input type="hidden" id="itemsWithServices" name="itemsWithServices" value="">
<input type="hidden" name="eventTypeName" value="Something">
<div class="ServicesDelivery"><span class="disable-button"></span>
NO SERVICE
ADD SERVICE
<div class="none">
</div>
<div class="clear"></div>
</div>
</div>
</div>
</form>
</div></div></div><a id="fancybox-close" style="display: inline;"></a><div id="fancybox-title" class="" style="display: none;">
</div><span class="fancy-ico" id="fancybox-left-ico"></span><span class="fancy-ico" id="fancybox-right-ico"></span></div>
Your locator By.className("withoutService") can match several elements. You need more specific selector. Try below code:
WebDriverWait waitWait = new WebDriverWait(driver, 40);
WebElement x = waitWait.until(ExpectedConditions.elementToBeClickable(By.linkText("NO SERVICE")));
x.click();
Try the following XPath:
//a[contains(#class, 'withoutService')]
Complete Code:
WebDriverWait waitWait = new WebDriverWait(driver, 40);
WebElement x = waitWait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//a[contains(#class, 'withoutService')]")));
x.click();
If above code is NOT working, then the element might be inside an iframe. please look my detailed answer here.

How to select a value from Kendo UI MVVM drop down in automated test?

Could anyone please help me with selecting a value from Kendo UI MVVM drop down using Selenium Java?
<input class="k-input fieldFullWidth" autocomplete="off" style="width: 100%;" title="" role="combobox" aria-expanded="false" tabindex="0" aria-disabled="false" aria-autocomplete="both" aria-owns="ddStore_listbox" type="text">
<input id="ddStore" class="fieldFullWidth" data-role="combobox" style="display: none;" aria-disabled="false" data-bind="value: selectedAsset.StoreID, comboboxText: selectedAsset.StoreName">
I tried to use JavascriptExecutor. But, it gives me org.openqa.selenium.WebDriverException: unknown error: Cannot set property 'value' of null error.
jse.executeScript("document.getElementById('ddstore').value = '1';");
Thanks
Use ExplicitWait to wait until visibility of <input>tag element and then send your dropdown value as input
WebDriverWait wait = new WebDriverWait(driver, 120);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("ddStore")));
driver.findElement(By.id("ddStore")).sendKeys("dropDown_Value"); // send your dropdown value as input
`
The another alternative way is to use JavascriptExecuter as your tag contains attribute style="display: none;" so might be changes of invisibility of element
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("arguments[0].value='your_dropdown_value';",driver.findElement(By.id("ddStore")));
You can try the following code to select dropdown value:
Select mydrpdwn = new Select(driver.findElement(By.id("ddStore"))); //id of dropdown
mydrpdwn.selectByVisibleText("name");// Value you wanted to select

Categories