How to select a single item in protractor - angularjs

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

Related

How to find a specific child element with Protractor

I have a lot of difficult to find one element inside other.
enter image description here
Inside this, I need to compare if one of them, has an element with a specific text that I need, and click on it.
I already tried to use:
element.all(locator).filter(filterFn)
ERROR: - Failed: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator By(css selector, #main > app-playbook-list-page > app-playbook-grid > div.d-flex.flex-row.flex-wrap)
element(locator).$(selector)
create a variable to save the all elements
Do someone have any idea to solve this?
$$('div.d-flex.flex-row.flex-wrap>div.flex-column');
Try the locator to get the array of elements.
Try this out this may help you
element.all(by.locator(element)).filter(function(el,index){
return el.isDisplayed();
}).first().click();

How to iterate over elements in selenium

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).

Angular JS - How to find the element in DOM having the xpath?

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")

Getting the first element in an array/any collection

So the other day I had my colleague review my code and he saw that I was using array[0], in Java terms this is basically getting the first element of the array. I did this several times for different purposes, all of which is to get the first element in an array/collection, for example list.get(0), to which he strongly disagreed with.
His argument was that somebody from non-programming background would have problem understanding it and using 0 in such cases is basically hard-coding, which is bad practice. I google-ed several times and all suggestions to getting the first element in an array or any collection is providing them the index, which is 0 in this case.
Could anyone provide me with a suggestion on getting the first element in a meaningful way?
Try using linkedlist's getfirst method to get the first element of the list.
If you were to use an ArrayList is backed by an array and hence its perfectly valid to use index as 0 to get first element.

dojo.query "," (or) for combining multiple selections does not work on IE 7

I am using
dojo.query('input,select',myDiv)[0].focus();
to focus the first input element found in a div container.
This will work in Firefox, but not in IE 7.
IE 7 only takes the first query into consideration:
dojo.query('input,select')[0] will select the first input element,
even if a select element is first.
dojo.query('select,input')[0] will select the first select element,
even if an input element is first.
Does anybody know a workaround for this?
If I recall correctly, dojo.query does not necessarily guarantee "chronological" order within the NodeList it returns, especially for complex queries. This is generally due to the fact that for some browsers / in some scenarios, it does have to cobble multiple disparate result sets together, and trying to reorder this based on where each element is in the document would probably be far more of a performance hit than it's worth.
That said, off the cuff I'm not sure what to suggest as an alternative. It'd be easy enough to find the first of one OR the other separately, just not while looking for both within the same query.
If your form has some kind of consistent markup around your inputs (e.g. each field is inside let's say, a div with class="field"), I suppose you could do something like this:
dojo.query('.field:first-child select, .field:first-child input')

Resources