How can I use xpath instead of id to find the element in DOM. I know that for id I can use: $("#id")[0].
I use $("#id")[0] inside Developer mode in browser in order to get the element by id to see what methods (like .getText(), innerHTML or others) am I able to use for the element. I want to know how to do this by XPATH
Thanks in advance
On Firefox console you can find (and explore) the element like this:
$x("//button[#id='myButton']")
But if you want to call a function on the element, you have to call it like this:
$x("//button[#id='myButton']")[0].click()
because there is always an array of elements returned (provided that the element is present and the first one in the array).
Thanks for the comments. I found out the answer. It can be done with:
$x("xpath")
Related
I am trying to write a locator where the next text descendant is returned. I wont know the text. The following xpath works:
//*[#id='myChart']//label[contains(text(),"Show:")]/following::div[4]
but I dont like the div[4] as this could easily change. The element is the first div type descendant under show that contains text. Any suggestions?
A
Considering the following clauses:
the next text descendant
I wont know the text
div[4] as this could easily change
element is the first div type descendant
To locate the element a couple of effective approaches are as follows:
Using xpath:
//*[#id='myChart']//label[contains(., "Show")]//div[text()]
Using xpath with descendant:
//*[#id='myChart']//label[contains(., "Show")]//descendant::div[text()]
Using xpath with following:
//*[#id='myChart']//label[contains(., "Show")]//following::div[text()]
I think this will work for you:
//*[#id='myChart']//label[contains(text(),"Show:")]//div[text()]
To give more confident answer we need to see the actual page / XML.
In case the desired div is a direct child of the label containing the "Show:" the above expression can be presided to
//*[#id='myChart']//label[contains(text(),"Show:")]/div[text()]
Actually i want to read emails one by one in junk folder of "outlook:live" and mark emails "Not spam".
emails = WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH,"//div[#class = 'xoCOIP8PzdTVy0T6q_uG6']")))
This xpath matches 400 instances. I want to make a loop to select one email at a time like select first email, click on the div and perform action and then 2nd email and so on. I'm trying this
emails = WebDriverWait(driver,
5).until(EC.element_to_be_clickable((By.XPATH,"//div[#class =
'xoCOIP8PzdTVy0T6q_uG6']")))
for count in range(0,len(emails)):
(emails)[count+1].click()
Please help me know where im doing wrong. Thanks in advance
It appears that the function you're using to return the clickable elements is only returning a single element, so you'll have to use a different function, make a change in your logic, etc.
For instance, you could use Selenium's find_elements_by_xpath("//div[#class = 'xoCOIP8PzdTVy0T6q_uG6']") which will return a list of WebElement object(s) if the element(s) are found, or an empty list if the element(s) is not found. This will, of course, not take into consideration the possibility of the elements not being completely loaded on the page. In my experience, just slapping a time.sleep(10) after you open the page is "'good enough".
I recommend making sure your elements can be discovered and interacted with first to make sure this isn't all in vain, if you haven't already.
Another option is to add another function, something like a elements_to_be_clickable() function, to the Expected Conditions source code.
From the Expected Condition documentation, I've done some research and it looks like the element_to_be_clickable() function only returns a single element. Moreover, from the source code, said function mainly makes use of the visibility_of_element_located() function. I believe you could follow similar logic to the element_to_be_clickable() function, but instead use the visibility_of_all_elements_located() function, in order to return multiple WebElements (since visibiilty_of_all_elements_located() returns a list of WebElements).
I wrote a directive, list, that displays a list of items.
Then I wanted to reuse this component in another directive, wrapped-list that would modify the list (add some items, change some values), and add some cosmetic stuff around it.
The list expects a list of items as parameter, then, wrapped-list expects the same list, plus the method that will change the list values and content.
The issue occurs when I try to invoke the method from wrapped-list in order to pass the data to list.
See fiddle here.
I tried many crazy combinations, and could not make it work.
items="listFactory({items:items})"
items="listFactory(items)"
items="{{listFactory(items)}}"
...
No luck so far.
Any idea?
Note: I could make it work with items="$parent.listBuilder(items)", but I don't want to depend on the parent's scope.
Also, I know this will generate the $digest() iteration reached error, which is not part of this question!
As Ohjay44 commented it, the error is that listFactory should be referenced as list-factory in the HTML side.
Usually in protractor you can select singular element with:
element(protractor.By.css('#fdfdf'));
Occasionally you get something like this:
element(protractor.By.css('.dfdf'));
which potentially has more than one element. What's the correct way to select an index from a locator that locates multiple elements, and still contain the protractor's methods for sending Keys?
You can get an indexed element from an array returned with
// Get the 5th element matching the .dfdf css selector
element.all(by.css('.dfdf')).get(4).sendKeys('foo');
If you want to get the first element then
element.all(by.css('.dfdf')).first();
element.all(by.css('.dfdf')).get(0);
Try this one. It will work:
element.all(by.css('.dfdf')).get(4).getText();
I don't know why xpath is so much underestimated but you can solve thousands of problems with it, including this one
let elem = element(by.xpath('(//div//a)[3]'))
You can specify the number of element to use. Keep in mind the numbers start from 1, not 0 as usually in js
For instance, is it possible to define:
#FindBy(By.id("id1") OR By.id("form1:id1"))
public WebElement button
So that button having either "id1" or "form1:id1" should work fine?
You can use the #FindBys annotation, the syntax is:
#FindBys({#FindBy(id = "foo"),
#FindBy(className = "bar")})
The JavaDoc describes it here:
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/FindBys.html
Well,
use whathever you want, as long as it works
Personally I would use #FindBy(By.id("id1")) but it is just point of choice.
Also, there is no value added in referring same element twice with two different methods. It will only cause mess in your code
EDIT
As I understood your comment, there is element on the page which constantly changes its ID. If you need to refer to such elements, try using xPath See for example this xpath tutorial
The idea is that you will point to some place in the DOM rather than to specific ID
Use Xpath or CSS selector to do that. Or Java to store the ID name in String and then you can fill it to your Id.