I have a program in which I am calling an iFrame within an iFrame however when I attempt to return to the first iFrame it can no longer find the elements.
I have tried both
base.getDriver().switchTo().frame("PopUpCont");
Add_Prefix_NewContact();
Add_FirstName_NewContact();
Add_MiddleName_NewContact();
Add_LastName_NewContact();
Add_Suffix_NewContact();
iFrameConvertion_Add_PrimaryAcct_NewContact();
base.getDriver().switchTo().frame("PrimaryAcctPick");
Add_PrimaryAcct_NewContact();
base.getDriver().switchTo().defaultContent();
Add_JobTitle_NewContact();
as well as
base.getDriver().switchTo().frame("PopUpCont");
Add_Prefix_NewContact();
Add_FirstName_NewContact();
Add_MiddleName_NewContact();
Add_LastName_NewContact();
Add_Suffix_NewContact();
iFrameConvertion_Add_PrimaryAcct_NewContact();
base.getDriver().switchTo().frame("PrimaryAcctPick");
Add_PrimaryAcct_NewContact();
base.getDriver().switchTo().frame("PopUpCont");
Add_JobTitle_NewContact();
however neither solution can find the next web element, so I don't believe I am returning to the first iFrame correctly. I know the web element works as I have commented out and tried that as well.
In case anyone cares to take a look I found the solution.
base.getDriver().switchTo().frame("PopUpCont");
Add_Prefix_NewContact();
Add_FirstName_NewContact();
Add_MiddleName_NewContact();
Add_LastName_NewContact();
Add_Suffix_NewContact();
iFrameConvertion_Add_PrimaryAcct_NewContact();
base.getDriver().switchTo().frame("PrimaryAcctPick");
Add_PrimaryAcct_NewContact();
base.getDriver().switchTo().parentFrame();
Add_JobTitle_NewContact();
Add_Email_NewContact();
Parent Frame got me back to where I needed.
Related
I have a java program to scrape a web page, using selenium-server-standalone-3.9.1 jar.
I create org.openga.selenium.htmlunit.HtmlUnitDriver to fetch the page which contains 2 iframes inside. JavascriptEnabled is true.
I can access the page and parse ok without issues, but for some reason, switching to those frames, doesn't seem to work. Here is a snippet of the code.
driver.switchTo().defaultContent();
//The below line works fine without issues, so I'm assuming switching is succeeding.
//FYI if I give a bogus bad frame name here, it does raise an exception, which indicates that //the driver is recognizing the frame ok
driver.switchTo().frame(driver.findElement(By.id("xyz"))); //no exceptions raised
//Here, driver.getPageSource() here shows no content, just have an empty as follows
//<html>
// <head/>
// <body/>
//</html>
// So, I can't get any actually existing elements inside the iframe at all here..
// i.e. getElements() etc would return nothing..
driver.switchTo().defaultContent();
driver.getPageSource(); //shows the full page ok again..
I don't believe it's page loading issue as the full source dump from the driver does show the contents of those embedded iframes source ok. So, I don't think "wait" would help here.
What am I missing here?
Tried to use WebDriverWait to wait for frames to be available etc, no luck.
It might be something obvious I've missed, but I've been staring at it for so long now that I decided to post it here_
I have this snipppet of markup for a submit button:
<button class="hb-knapp hb-knapp--standard" id="lastOpp_SOSIALE_UTFORDRINGER_03077000045_soker__"
type="button" data-e2e-selector="lastOpp_SOSIALE_UTFORDRINGER_03077000045_soker__"><!----><hb-ikon
class="hb-knapp-ikon" _nghost-rmd-c56=""><span _ngcontent-rmd-c56="" class="hb-ikon hb-ikon--
focusable="false"></span><!----></hb-ikon><!----><!----><span translate="" class="hb-knapp-
tekst">Last opp vedlegg<!----></span><!----><!----></button>
I'm trying to verify the visibility of the button by using "beginning with", since the number towards the end of the id and data-e2e-selector is dynamic.
So I'm trying this:
return driver.findElement(By.cssSelector("[id^=lastOpp_SOSIALE_UTFORDRINGER_]")).isDisplayed();
and this:
return driver.findElement(By.cssSelector("[data-e2e-selector^=lastOpp_SOSIALE_UTFORDRINGER_]")).isDisplayed();
Both yields the "Unable to locate element" error:
Unable to locate element: {"method":"css selector","selector":"[id^=lastOpp_SOSIALE_UTFORDRINGER_]"}
What on earth am I not seeing here? As far as I can see, I'm looking for the exact same locator(s) that are plainly visible in the markup?
EDIT:
I also tried using xpath, like this
return driver.findElement(By.xpath("//*[contains(#data-e2e-selector, 'lastOpp_SOSIALE_UTFORDRINGER_')]")).isDisplayed();
and this
return driver.findElement(By.xpath("//*[contains(#dataid, 'lastOpp_SOSIALE_UTFORDRINGER_')]")).isDisplayed();
with the exact same result. This seems completely bonkers.
EDIT2:
An also, of course, as a last test: The exact id:
boolean is = driver.findElement(By.id("lastOpp_SOSIALE_UTFORDRINGER_28037800130_soker__")).isDisplayed();
also returns "element not found".
The strange thing is - other elements on the same page are both visible and interactable.
EDIT3:
Tried adding a manual WebDriverWait, but even then Selenium insists on not finding the element:
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("lastOpp_SOSIALE_UTFORDRINGER_28037800130_soker__")));
or
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='lastOpp_SOSIALE_UTFORDRINGER_13108100073_soker__']")));
(The xpath is copied directly from the browser - Chrome.)
Result:
Expected condition failed: waiting for visibility of element located by By.id: lastOpp_SOSIALE_UTFORDRINGER_28037800130_soker__ (tried for 5 second(s) with 500 milliseconds interval)
And I'm watching the page, staring at the element in question, as the wait times out.
EDIT4: Snapshot of the html markup
Based on https://sqa.stackexchange.com/a/7889 and https://stackoverflow.com/a/39594489, I think the problem is that you need specify that you're looking for a button.
Try the following:
driver.findElement(By.cssSelector("button[id^=lastOpp_SOSIALE_UTFORDRINGER_]"))
I am trying to retrieve a JSON element, the problem is that in the source code it doesn't exist, but I can find it via inspect element.
I have tried with
C.driver.findElement(By.id("ticket-parsed"))
and via XPath
C.driver.findElement(By.xpath("//*[#id=\"ticket_parsed\"]"));
and I can't find it.
Also
C.driver.switchTo().frame("html5-frame");
System.out.println(C.driver.findElement(By.id("ticket_parsed")));
C.driver.switchTo().defaultContent();
i get
[[ChromeDriver: chrome on XP (1f75e50635f9dd5b9535a149a027a447)] -> id: ticket_parsed]
on
driver.switchTo().frame(0) or driver.switchTo().frame(1)
i get that the frame doesn't exists
and at last i tried
WebElement frame = C.driver.findElement(By.id("html5-frame"));
C.driver.switchTo().frame(frame.getAttribute("ticket_parsed"));
an i got a null pointer exception
Here's an image of the source:
what am I doing wrong?
Well!
The element #ticket-parsed is in iFrame. So, you can click it without getting into an iframe.
Here is the code to switch to iFrame,
driver.switchTo().frame("frame_name");
or
driver.switchTo().frame(frame_index);
In your case,
driver.switchTo().frame("html5-frame");
After switching into the iframe, you can click that element using either XPath or CSS.
C.driver.findElement(By.id("ticket-parsed"))
NOTE:
After completing the operation inside the iframe, you have to again return back to the main window using the following command.
driver.switchTo().defaultContent();
I didn't found a solution with my excising setup,but i did found a js command which gets the object correctly
document.getElementById("html5-frame").contentDocument.getElementById("ticket_parsed")
you can integrate js commands like this
JavascriptExecutor js=(JavascriptExecutor)driver;
js.executeScript(*yourCommandHere*);
if you want to get the output of the command just add the word return before your command (in this specific situation it didn't work but in any other situation it did)
*TypeOfData* foo = js.executeScript(return *yourCommandHere*);
at last because of limited time i had to use unorthodox methods like taking screenshots and comparing the images if they are exactly the same
Thanks for the help
I'm using Selenium to check if error message shown when user sent form with empty fields. Error message block is attached to the DOM all the time, but when there is no errors it has "display: none;" style attribute. So, when I push the "save" button, I check if this block visible this way:
Assert.assertTrue("There is no validation error!", driver.findElement(By.id("validationModal")).isDisplayed());
And this works. But when I'm trying to check that messages in this block are showed, isDisplayed method always returns "false". When I use just this:
driver.findElement(By.id("validationModal")).findElement(By.tagName("ul"))
.findElement(By.xpath("//*[contains(text(),'Empty app name field')]"));
it goes fine, but it's wrong because it wouldn't throw an exception when this text will be not visible, but will be in page code. If I write this:
Assert.assertTrue(driver.findElement(By.id("validationModal")).findElement(By.tagName("ul"))
.findElement(By.xpath("//*[contains(text(),'Empty app name field')]")).isDisplayed());
it always fails. And I don't really understand why and how I can check, that text of error message is shown, right way.
UPD:
I've found the source of problem. This string finds not element inside "validationModal" block, but inside tag, which contains text we have to find.
driver.findElement(By.id("validationModal")).findElement(By.tagName("ul"))
.findElement(By.xpath("//*[contains(text(),'Empty app name field')]")).isDisplayed()
But I still not understand why it happens, because I specify the element where it should be searched for.
It seems that you are trying to interact with some modal frame.
Generally to interact with modal element you should change driver context first.
driver.switchTo().frame("ModelFrameTitle");
or
driver.switchTo().activeElement()
Find or check elements and then come back to main frame
driver.switchTo().defaultContent()
Try this :
Assert.assertTrue("Element is not displayed",driver.findElement(By.xpath("//*[contains(text(),'Empty app name field')]")).isDisplayed());
There was an error in xpath.
Wrong string was:
findElement(By.xpath("//*[contains(text(),'Empty app name field')]"))
And right is:
findElement(By.xpath("//li[contains(text(),'Empty app name field')]"))
I'm using webdriver(java) for a unique test where a page reloads itself when you log on, I've been unable to wait for the element to load because it is already there before the reload. So far the only way I've been able to get it to work is to use a thread.sleep, is there a way to listen for a page refresh?
One way to solve this is, to get a reference to the element you need, that appears both on the login-page and the reloaded page.
Then you can use the ExpectedConditions.stalenessOf to occur, and then you can be sure, that the element is removed from the DOM and a new element is created. Well, the last part is not guaranteed by this method, but at least you know that the old element is gone.
The code could look something like this:
WebElement elementOldPage = driver.findElement(By.id("yourid"));
... do login etc ...
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.stalenessOf(elementOldPage));
WebElement elementNewPage = driver.findElement(By.id("yourid"));
Building upon the accepted answer from Kim Schiller one might be interested in the following piece of code. It is surely not perfect due to the sleeps, so be free to suggest improvements to make it more bulletproof. Also note I'm no expert with selenium.
The if branch waits for the top level node in the html to go stale in case of a page reload. The else branch simply waits until the drivers url matches the request url in case we load a different page.
def safe_page_load(url):
if driver.current_url == url:
tmp = driver.find_element_by_xpath('/html')
driver.get(url)
WebDriverWait(driver, 2).until(ExpectedConditions.staleness_of(tmp))
else:
driver.get(url)
while(driver.current_url) != url:
sleep(0.3)
sleep(0.3)
Happy if I could help someone.