Selenium WebDriver access a sub element - selenium

I have a div with a unique ID. Under that div are a bunch of span elements that have className=foo. There are several span elements with className=foo but they are unique to each div (if that's clear). So my Selenium code first gets the unique div as a web element then tries to take that element and get by class name the span like so
element = sDriver.findElement(By.id("c_"+cID));
String sTest = element.findElement(By.className("actions")).getText();
On the second line it throws an exception every time
org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
Command duration or timeout: 22 milliseconds
Do I misunderstand how to get that span from under a unique div?

Nope you'right accessing the span but the problem is that the Dom has changed since StaleReferenceException is about (see StaleReferenceException )
This may be caused because the page isn't loaded completely when the code starts or changes when the code is executed. You can either try to wait a little longer for the element or catch the StaleReferenceException and try again finding the div and the span.

My solution is not fancy but it works like a Swiss watch (in my situation of course). So my code is calling the parent element in a loop looking for different child elements in it. Nothing got changed at all - just simple querying and the exception began to occur. So! I've added the Thread.Sleep(2000) command before every search of parent element and it solver the problem. Not elegant but works every time with minimum code to debug afterwards.

Related

RSelenium: Entering search term - trouble with css selector

I am trying to trigger a search on this site. First, I want to enter a search term, then click the search button. I am able to to do the second step, however I am unfortunately unable to access the search field. Below my attempt.
Start RSelenium
link_to_page<-"https://www.cec.ro/sucursale"
library(RSelenium)
rD <- rsDriver(browser = "firefox", port = 483L, verbose = F)
remDr <- rD[["client"]]
# Navigate to site, and wait
remDr$navigate(link_to_page)
Sys.sleep(5)
#Search for element by its id
remDr$findElement(using="css", "#edit-localitate--_jjPr3WukFY")
Error: Summary: NoSuchElement
Detail: An element could not be located on the page using the given search parameters.
class: org.openqa.selenium.NoSuchElementException
Further Details: run errorDetails method
There is apparently something wrong with the css selector. I checked, it's not nested in an iframe or so, but mabe it's related to the 'form' element it is nested in? Grateful for any hint. Many thanks.
The error is NoSuchElement which indicates an element could not be located on the page using the given search parameter
The second part of the classname i.e. _jjPr3WukFY is dynamically generated and is bound to change sooner/later. They may change next time you access the application afresh or even while next application startup. So can't be used in locators.
Solution
You need to consider any of the other attributes which is static in nature. Example:
remDr$findElement(using="css", "button[id^edit-localitate]")
or
remDr$findElement(using="xpath", "//button[starts-with(#id, 'edit-localitate')]")

Is there a difference between "is visible" and "click element" in Robot Framework/Selenium?

These two lines don't work as expected:
wait until element is visible ${my xpath}
SeleniumLibrary.click element ${my xpath}
Approximately half of the time the second line fails. I am not in front of my computer now but it either fails with stale element or couldn't find element with id....
If I add a sleep 3 or so inbetween the lines the second line never fails.
These two lines work frequently but they also fail frequently. Is there a difference in how RF detects that something is visible and how Selenium sends a click to the same element?
You can include a custom timeout in the first keyword instead of using sleep.
Wait Until Element Is Visible ${my xpath} 3 seconds
Click Element ${my xpath}
To answer your question in short no there is no difference between how RF detects that something is visible and how selenium sends a click to that same element. I looked at the source code for Selenium and both functions use the same locator argument.
#keyword
def click_element(self, locator, modifier=False, action_chain=False):
and
#keyword
def wait_until_element_is_visible(self, locator, timeout=None, error=None):
A keyword instead I would suggest is
wait until page contains element ${my xpath}
This allows for the web page to be fully loaded before looking for the element.

How to get the text from an element which disappears quickly using protractor

I need to get the text from element P but protractor keeps returning error
Code:
<div class = "ui-growl-message">
<span class = "ui-growl- title">Sucesso</span>
<p>cargo Cadastrado cm sucesso!</p>
</div>
I've tried this way:
const msgValidacao = element(by.css('ui-growl-message')).all(by.tagName('p')).first().getText().then(() => {
expect(msgValidacao).toContain('Cargo cadastrado com sucesso');
});
and the Error is:
Failed: No element found using locator: By(css selector,
ui-growl-message)
The problem is the element is a warning so it quickly disappears from the screen.
In addition to the css correction, you'll also want to employ some sort of wait strategy to anticipate the message and grab the content as close to the moment of the initial rendering as possible. Automation around very short-lived messages can be challenging due to intricate timing factors.
It might be not the real problem why it returns that element is not found. I thing that the selector is not good. If the element disappears quickly as You say sometimes the test will pass and sometimes it will fail. Try another selector and make sure that You have the correct one.
If you want to select first element use get(0) not first()
element(by.css('ui-growl-message')).all(by.tagName('p')).get(0)

element not visible Selenium capybara

I am getting below error while executing below capybara command,
The interesting thing is the same XPath is not giving any error in I am expecting that XPath to be present.
But when I am trying to perform click on that XPath, it's throwing below error.
--------------code----------------
Then(/^I click on "([^"])" on left tree child of "([^"])"$/) do |child, parent|
within(:xpath, ".//div/span[#class='folder-nav-tree-fileroom' and text()='DND-IndexTwistyExpClps']/../../../../..", wait:5) do
find(:xpath, ".//span[contains(text(),  '1 IndexTwistyLevel1')]/../../../span[#class='ui-tree-toggler fa fa-fw fa-caret-right']", wait:5).click
end
end
Error : Capybara::ElementNotFound: Unable to find visible xpath "//div[.//span[contains(text(),  '1 IndexTwistyLevel1')]]/span[#class='ui-tree-toggler fa fa-fw fa-caret-right']"
Your code has a number of issues, which indicate it can't actually be working like you claim. If you fix the code and provide the HTML fragment it should be matching against we can narrow done to the issue, but for now the errors are:
Firstly, you have mismatched/non-escaped
's and )s in your XPath expressions (can't have inside a string surrounded bys so it's obvious you haven't copy/pasted your actual code)
Secondly, ::after is not valid XPath - ::after pseudo elements are purely CSS and can't be accessed from XPath, so including that in your selector isn't going to give the expected results. This should result in an invalid selector error being raised by Chrome.
Thirdly, by not starting your selectors with . you're completely defeating the within scoping block - see https://github.com/teamcapybara/capybara#beware-the-xpath--trap
Finally, using visible: false on an element you want to click makes no sense, since you can't click on an element that isn't displayed on the page.
Unfortunately its tough to tell which of these may be causing your actual issue (if any) since the code you have provided isn't valid.
within(:xpath, config['documents_obj']['FRChildTreeXpath'].sub('TEXT', parent), wait:5) do
elem = find(:xpath, config['documents_obj']['childTwistyXpath'].sub('TEXT', child), visible:false, wait:5).native
page.driver.browser.action.click(elem).perform
To avoid the error which iwas gettign what i simply did, is I used capybara action builder,
Take the native element then perform the action.
It worked perfectly in my case.
Reference : https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/ActionBuilder.html

wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.ClassName(className)) doesn't return any element

I need to find IReadOnlyCollection<IWebElement> using WebDriverWait to make sure that elements had been rendered on page.
This is my code
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeout));
return wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.ClassName("TextInput")));
This code failing on timeout.
Meaning that could not find any elements on page with given class name.
I added this line of code BEFORE my original code just to make sure that elements are present
var allInputs1 = container.FindElements(By.ClassName("textInput"));
And that line returns elements as expected.
So my conclustion is that
wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.ClassName("TextInput")))
doesn't work as expected since that couldn't find elements that are for sure present on page.
What is the best way to find array of elements using WebDriverWait?
Your conclusion is wrong. With FindElements you just make sure that elements are present.
The API documentation for VisibilityOfAllElementsLocatedBy states:
An expectation for checking that all elements present on the web page
that match the locator are visible. Visibility means that the elements
are not only displayed but also have a height and width that is
greater than 0.
And obviously present is not visible.
I think you should try ExpectedConditions.PresenceOfAllElementsLocatedBy