With Robot Framework and Selenium, I want to create a keyword to keep on refreshing the page until page contains the element.
I do not think I can use Wait Until Page Contains Element <xpath> <time> because the page needs to be refreshed to show the element.
How can I write a FOR Loop to do this?
*** Keywords ***
Refresh Page until page contains the element
Reload Page
Page Should Contain Element <xpath>
Or may be I can somehow loop this?
${Reload}= Run Keyword And Return Status Page Should Contain Element <xpath>
Run Keyword If ${Reload} <don't know how to write here> ELSE Reload Page
Hi this could be achieved by using something similar to the below snippet. Using a while loop which has additional examples here: RoboCorp WHILE Loops
Refresh Page Until Page Contains Element
${Reload}= Run Keyword And Return Status Page Should Contain Element <xpath>
WHILE ${Reload} != ${TRUE}
${Reload}= Run Keyword And Return Status Page Should Contain Element <xpath>
END
Hope this helps
Related
ok so I cannot share the website I'm trying to automate but I'll share a screen shots of the inspect view.
ill add the code i used and the log i got from it
as you can see the class: data-command has three elements within in the number is dynamic but I need to click on the last one, i do not want to use absolut xpath as the class: data-command is dynamic.
ill add the code i used and the log i got from it
how do i click the last element
##{element_value}= Get WebElements class:data-value
#{elements_name}= Get WebElements class:data-label
#{element_commands}= Get WebElements class:data-command
WHILE ${i} < 5
#Log To Console ${element_commands[${i}]}
Click Element ${element_commands[${i}]}
Sleep 5s
#Capture Page Screenshot
Run Keyword And Warn On Failure Page Should Contain ${graph}
${i}= Evaluate ${i} + ${one}
END
I'm not familiar with robot framework, but is case data-command class is a unique locator, the following XPath will give you the last child inside that element:
"(//div[#class='data-command']//*)[last()]"
You can get elements store it in collection/list and then get the last one and click it:
List<WebElement> elements= driver.findElements(By.css(".data-command"));
element = elements.get(list.size() - 1); //Click only the last in the list
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')]")
I have a use case that I need to find all iframe and object tags from the page.
Currently I'm using cssSelector() method. I have noticed that there is also tagName() method.
What is the difference between these 2 methods with the above use case ?
findElement(By.tagName("a_tag")) will find elements by html tags such as <iframe> , <div>. But you can only provide it with html tags, not css classes, etc ...
With findElement(By.cssSelector("a_tag")) you can find elements with html tags but you can also give a css class for example findElement(By.cssSelector("div.myClass"))
For your case you can use :
List<WebElement> iframes = driver.findElements(By.tagName("iframe"))
List<WebElement> objects = driver.findElements(By.tagName("object"))
And then perform a for loop to do your tests
It's recommended to use cssSelector/id/xpath/etc ... By since it will wait for the "needed element" displayed if the element is not present on the page initially.
Because By.cssSelector is more specific, selenium will continue checking if the element exists until the implicit wait (x seconds) times out.
By.Tag is not specific at all. Using By.tagName, selenium will not wait for the element. On findElements(By.tagName("table"), Selenium will return an array of all the tables that are present immediately after the page loads. As the "needed" element is not present yet, it will not be in the array.
I have a function which adds a button to a div "dettaglio_utenti". After calling the function with this instruction
tab+="<button data-dojo-type='dojox.mobile.Button' id='apri_mappa' onClick=\" location.href='tel:"+telefono+"'\">apri mappa</button>"
var vText = document.getElementById("dettaglio_utente");
vText.innerHTML = tab;
require(["dojo/parser"], function(parser){
parser.parse(vText);
});
It works only the first time that I display the page. The second time the button is not parsed and I see this error in the browser console: dojo/parser::parse() error Error: Tried to register widget with id==apri_mappa but that id is already registered
When you display the page for the second time, the first page must still be part of the dom. (Maybe this is a worklight feature, single page app?). So when dojo parses the second page it gives the error because the button with that id has already been created.
I don't believe preventing the parsing of the button a second time will accomplish what you need. I think your options are:
Destroy the widgets from the first page.
If you don't need an id on the button, you can omit it and Dojo will create an id that won't collide.
If you need the id, you can or use a counter when emitting the id of the button.
id='apri_mappa_' + i where i is the counter.
Only knowing what you wrote above, I think the order of preference is 2,1,3.
EDIT - How to destroy a widget
require(['dijit/registry'], function(registry) {
registry.byId('apri_mappa').destroy();
});
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.