::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
Related
I have this HTML now using Selenium I ant to toggle the li element with given index position say 1, where it indicates I want to click the toggle checkbox for spring.
<ul id="todo-list" data-woven="abc">
<li class="active" data-index="0">
<div class="view">
<input class="toggle" type="checkbox">
<label>Java</label>
<button class="destroy"></button>
</div>
<input class="edit">
</li>
<li class="active" data-index="1">
<div class="view">
<input class="toggle" type="checkbox">
<label>Spring</label>
<button class="destroy"></button>
</div>
<input class="edit">
</li></ul>
I am completely new to selenium so not able to understand how can we achieve this.
I know to get the UL elements using the code:
driver.findElement(By.id("todo-list"));
Now how can get the li element based on its index and click the corresponding checkbox.
To click on the checkbox element with respect to the ancestor <li> nodes index attribute you can use either of the following Locator Strategies:
cssSelector:
driver.findElement(By.cssSelector("ul#todo-list li.active[data-index='1'] input")).click();
xpath:
driver.findElement(By.xpath("//ul[#id='todo-list']//li[#class='active' and #data-index='1']//input")).click();
You can use xpath to locate an element with data-index=1
driver.findElement(By.xpath("//li[#data-index='1']//input[#class='toggle']"));
Or with cssSelector
driver.findElement(By.cssSelector("[data-index='1'] .toggle"));
You could find the element you are looking for directly with the answer #Guy gave you and that would be the right way if you knew exactly what the data-index attribute would be set to, but you could also find a collection of the li elements and then proceed to do what you need within each like this:
var container = driver.findElement(By.id("todo-list"));
var elements = container.findElements(By.tagName("li"));
with elements you can loop through each or go directly to the one you want.
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']"));
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.
I have this html code below and I want to differentiate between these two PagePostsSectionPagelet as I only want to find web elements from the first PagePostsSectionPagelet. Is there any way I can do it without using <div id="PagePostsSectionPagelet-183102686112-0" as the value will not always be the same?
<div id="PagePostsSectionPagelet-183102686112-0" data-referrer="PagePostsSectionPagelet-183102686112-0">
<div class="_1k4h _5ay5">
<div class="_5sem">
</div>
</div>
<div id="PagePostsSectionPagelet-183102686112-1" class="" data-referrer="PagePostsSectionPagelet-183102686112-1" style="">
<div class="_1k4h _5ay5">
<div class="_5dro _5drq">
<div class="clearfix">
<span class="_5em9 lfloat _ohe _50f4 _50f7">Earlier in 2015</span>
<div id="u_jsonp_3_4e" class="_6a uiPopover rfloat _ohf">
</div>
</div>
<div id="u_jsonp_3_4j" class="_5sem">
<div id="u_jsonp_3_4g" class="_5t6j">
<div class="_1k4h _5ay5">
<div class="_5sem">
</div>
</div>
Tried using //div[#class='_1k4h _5ay5']//div[#class ='_5sem'] but it will return both.
Using //div[#class='_5dro _5drq']//span[contains(#class,'_5em9 lfloat _ohe _50f4 _50f7') and contains(text(), '')] will help me find the second PagePostsSectionPagelet instead.
you need to use the following xpath:
//div[contains(#class,'_1k4h') and contains(#class,'_5ay5')]
as selenium doesn't work properly with search of several classes in one attribute.
I mean By.Class("_1k4h _5ay5") will found nothing in any case and By.Xpath("//div[#class='_1k4h _5ay5']") can also found nothing in case of class will be "_5ay5 _1k4h" or " _5ay5 _1k4h".(as they possibly generated automatically, its may be have different position on page reload)
But for the best result by performance and by correctness I think will be the following xpath:
".//div[contains(#id, 'PagePostsSectionPagelet')][1]" -- for first div
".//div[contains(#id, 'PagePostsSectionPagelet')][2]" -- for second div
I see that dynamic in the div id is only the number so you can use something like:
WebElement element = driver.FindElements(By.XPath("//div[contains(.,'PagePostsSectionPagelet')])")[1];
This will take only the first web element.
Try using a css selector as below and refine further if required.
The code below returns a List of matching WebElements and then you grab the first one in the List.
List<WebElement> listOfElements = driver.findElements(By.cssSelector("div[data-referrer]"));
WebElement myElement = listOfElements.get(0);
Hint: use the Chrome console to test your css and xpath selectors directly. e.g. use
$$("div[data-referrer]") in the console to reveal what will get selected.
I wrote some codes to parse the html using xpath and Java. The html file is something like:
<div class="field_row">
<label for="names">Names *</label>
<input id="address.A" type="text" maxlength="15" size="32" value="12345" name="address.work">
<span class="additional_info"> Information 1 </span>
</div>
<div class="field_row">
<label for="names">Names *</label>
<input id="address.B" type="text" maxlength="15" size="32" value="12345" name="address.work">
<span class="additional_info"> Information 2 </span>
</div>
And Java codes:
public static final Element INFOFIELD= Element.findXPath(".//*[#class='additional_info'");
will let me get 'Information 1'; however, I need to retrieve 'Information 2'. Therefore, I use:
public static final Element INFOFIELD= Element.findXPath(".//*[#class='additional_info' and #id='address.B']");
But got errors. Could you give me some hint please? Thanks. A.
You can create an XPath based on your input field (address.B), and then specify you want to access one of its sibling nodes and thus retrieve its data...
XPath:
//input[#id='address.B']/following-sibling::span[#class='additional_info']
as you can see after we find the input node with the id attribute 'address.b', we specify 'following-sibling'. This indicates that we want to select one of the siblings after the current node('address.B's input field). Then we specify which node that is followed by the attribute details: span[#class='additional_info']
some working code implementing the above XPath:
WebElement element = driver.findElement(By.xpath("//input[#id='address.B']/following-sibling::span[#class='additional_info']"));
System.out.println(element.getText());
will print 'Information 2'
You can use XPath axes in other related ways to access other nodes in the DOM (parents, children, siblings,etc).
http://www.w3schools.com/xpath/xpath_axes.asp
An axis defines a node-set relative to the current node.