Selenium - Error getting WebElement within iFrame - html

I am building a small automated test script with Selenium Chrome WebDriver last version, but now I am facing an issue when I try to get a WebElement within an iFrame, even when I switch to it.
This is the way HTML is built:
As you can check, there is another page "encrusted" inside iFrame, and the button is defined below (it's the part I selected):
This is the way I am using to get the WebElement (obviously failing):
WebElement frameAperturar =
driver.findElement(By.xpath("//iframe[#title='Aperturar']"));
driver.switchTo().frame(frameAperturar);
asociarSiniestroButton = driver.findElement(By.xpath("//button[#aria-label='Asociar Siniestro']"));
asociarSiniestroButton.click();
This is the exception I got when I tried to get the WebElement:
no such element: Unable to locate element: {"method":"xpath","selector":"//button[#aria-label='Asociar Siniestro']"}
(Session info: chrome=60.0.3112.113)
Do you know how I can get an element of the page inside the iFrame after I switch to the frame?

You can actually select an iFrame using the below methods:
frame(index)
frame(Name of Frame [or] Id of the frame)
frame(WebElement frameElement)
defaultContent()
So you can switch by passing the any above information about the frame. Yes you need to switch every time according to require action.
Example:
driver.SwitchTo().Frame(0);
driver.SwitchTo().Frame("top");
.... Perform your action on frame
driver.SwitchTo().defaultContent();
driver.SwitchTo().Frame("navigation");
.... Perform your action on frame
driver.SwitchTo().defaultContent();
Try below XPath
//span[#class='apexButtonText' and contains(.,'Asociar Siniestro')]
OR
//span[contains(text(),'Asociar Siniestro')]
OR
//span[#class='apexButtonText'][contains(text(),'Asociar Siniestro')]
OR
//button[#aria-label='Asociar Siniestro']//span[contains(.,'Asociar Siniestro')]

I am new to selenium but seems like your button is actually 'span' and xpath wont work like this, try //span[contains(text(),'Asociar Siniestro')]

Use this xpath
//span[#class='apexButtonText'][contains(text(),'Asociar Siniestro')]

Related

Selenium cannot find element

Having some issues using Selenium web driver in Chrome.
My goal is to give the user ~15-30 seconds to log in on there own and then start doing automated testing.
The problem is after I click the login button and go to the next page, I am not able to find elements by xpath, id, etc.
public static void runTest() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"/chromedriver");
WebDriver driver = new ChromeDriver();
driver.get("http://www.url.com");
driver.manage().window().maximize();
Thread.sleep(15000);
driver.findElement(By.xpath("//*[#id=\"content-main\"]/div/div/form/div/p/input")).click();
System.out.println("User has logged in and it has found element for Attachment Upload.");
Thread.sleep(15000);
driver.findElement(By.xpath("//*[#id=\"invoiceMenu\"]/a")).click();
}
I have also tried using explicit waits and have had no luck for example:
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("someid")));
The error I am usually getting back is:
Exception in thread "main" org.openqa.selenium.TimeoutException: Expected condition failed: waiting for visibility of element located by By.xpath: //*[#id="invoiceMenu"]/a (tried for 10 second(s) with 500 milliseconds interval)
Edit:
Was able to get some of the elements (angular ones) working with a few plugins for Chrome. Element Locator and ChroPath worked fantastic. Took some playing around with, but once I got one I was able to piece together the rest of them.
I would suggest that you open the chrome console on your browser and try to interact with the element in question e.g. using:
document.getElementById('someId').click()
If you are able to click on the element like that, then you can use javascript executor in your code as follows:
((JavascriptExecutor)driver).executeScript("document.getElementById('someId').click();");

PhantomJS / CasperJS Canvas selector

Using PhantomJS V 1.8.1
Thanks in advance.
I am trying to run some tests on a website that I am developing which is using backbone.js.
One of my tests involve checking to see if a Canvas is present and clicking on it. My problem is that whatever selector I use to get the Canvas Element I cannot get the selector to find it. I use the same CSS selector in Google Chrome when viewing the page and all is OK. At first I thought that the issue may have been due to the element not being present on the page but other elements which are inserted with the canvas are present so I am 99% sure that this is not the problem.
The selectors I have tried to use are:
document.querySelectorAll('#idOfCanvas');
document.querySelectorAll('canvas#idOfCanvas');
Also if I use .classClassName:nth(1) to select the tyre selector, it still fails to work (works in Google Chrome though as does the other examples provided)
The canvas has a class name which is picked up by the selector by I would rather not use a class selector.
Any help would be much appreciated.
Cheers :)
Also
Like I mentioned I am almost certain that the Canvas exists as the container div for it exists. Also I have four elements on the page with the same className (two of which are canvases) and four elements are being returned when I run
return document.querySelectorAll('.className').length = 4;
Assuming you have something like this:
<canvas id="idOfCanvas"></canvas>
This should work:
canvas = document.getElementById("idOfCanvas");
// or
canvas = document.querySelector("#idOfCanvas"); // Only get the first match, ID's should be unique, any way.;
// or
canvas = document.querySelectorAll("#idOfCanvas")[0];
// or
canvas = document.getElementsByTagName("canvas")[0]; // Get the first <canvas> element.
However, you'll have to make sure your canvas element is actually loaded when the script is executed. Have a look at this onload tutorial, for example.
Try this :
canvas = document.getElementById(#IdOfCanvas:nth-child(1));

Catch video HTML5 play/stop event

How can I listen to the events play/stop/pause of a HTML5 video?
I tried with the following code:
$("video").on('play',function(){
//my code here
});
but it does not work.
Alternatively I would be fine also intercept the click that stop and start the video (in fact I would prefer), but even this code not works:
$('video').on('click', function(event) {
//my code here
});
I think because often above the video element is placed a div with associated events start and stop, but I do not know how to select via jQuery or Javascript:
P.S. This code should work on pages that are composed dynamically / not generated by me, so I can not refer the elements indicating their ID or a specific class.
UPDATE
I did not realize that the page on which I was testing had a video inside an iframe.
The syntax is best suited to my needs:
doc.querySelector("video").addEventListener('play', function(e) {
//my code here
}, true);
See here:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events
So... :
$("video")[0].onplay = function () {
// Do play stuff here
};
Hope that helps!
Your first attempt should work. But you need to make sure that jQuery is actually finding video elements. You say that the page is generated dynamically, so perhaps it's possible that your code is running before the video elements are added. This would also be the case if your script is higher up in the document than the video elements (e.g., in the <head>).
Try placing the following code immediately before the code you have there and check the output:
console.log($("video"));
If the output is an empty array, then you aren't finding any video elements. Try placing your script at the very end of the page or inside a DOMContentLoaded event. Or, if another script is generating the video elements, make sure your script runs after that one.
A few other notes on your question:
There is no stop event. Here's a list of media events.
I don't think the click event is what you want. That will fire no matter where on the video the user clicks: play button, volume control, etc.
The video being placed inside a div shouldn't have any effect on these events. I'm not sure why you'd have start and end events on a div, so maybe I'm not following.
Give this a try!
//Direct
<video id="videoThis" src="blahhh.mp4" onended="yourFunction()"></videoThis>
-or-
//JavaScript (HTML5)
document.querySelector("#videoThis").addEventListener("ended",yourFunction,false);
-or-
//jQuery
$("#videoThis").bind("ended",yourFunction);

Should all elements return true on isDisplayed() after a selenium Webdriver get()?

WebDriver get() and isDisplayed() methods are not working as I expected.
As for the doc:
This is done using an HTTP GET operation, and the method will block
until the load is complete
As mentioned in other questions like this Wait for page load in Selenium , the get method should wait for the page to load.
But after running get(), isDisplayed() method from RenderedWebElement does not always return true on some elements.
What are the possible causes?
I'd like some elaboration on the difference between being loaded and being displayed in the context of webdrivers.
In the latest UI frameworks/APi you can hide an element on a page.
For ex. Consider a page having 5 elements. When page is loaded only 3 elements will be shown on the page, the other 2 will be hidden and on taking some action the other 2 elements will be shown.
An example you can check under the demo section in following links:
Show element link: http://api.jquery.com/show/
Hide element link: http://api.jquery.com/hide/
When you use webDriver get() method, webdriver will wait for page to load i.e. it waits for all the html content of the page to be loaded onto the browser. This does not means that all the elements are visible.
When you use isDisplayed() webdriver checks whether the said element is Displayed on the page or not. If you know that the element may be hidden on the page when running your test-cases its a good approach to verify whether the element is displayed or not. Else your test script fails with a error "Element not displayed to take an action"
Hope this helps.
isDisplayed() seems to me not so good approach. get some ideas from wait: exlplicit and implicit wait mechanisms:
Explicit wait
WebDriverWait.until(condition-that-finds-the-element)
Implicit wait
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Explicit Waits:
WebDriver driver = new FirefoxDriver();
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(new ExpectedCondition<WebElement>(){
#Override
public WebElement apply(WebDriver d) {
return d.findElement(By.id("myDynamicElement"));
}});
Implicit Waits:
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
The example what you have given both do exact same thing..
In Explicit wait, WebDriver evaluates the condition every 500
milliseconds by default ..if it is true, it comes out of loop
Where as in ImplicitWait WebDriver polls the DOM every 500
milliseconds to see if element is present..
Difference is
1. Obvious - Implicit wait time is applied to all elements in your
script but Explicit only for particular element
2. In Explicit you can configure, how frequently (instead of 500
millisecond) you want to check condition.
3. In Explicit you can also configure to ignore other exceptions than
"NoSuchElement" till timeout..
you can get some more info here
Also I use fluent wait mechanism for waiting elements get rendered on the page. Actually you pass either css selector either xpath to the function and simply get web element.
public WebElement fluentWait(final By locator){
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
}
);
return foo; } ;
fluent wait description
hope this comes clear now)

transition from one page to another jquery mobile

I'm trying to figure out how to transition from one page to the next using jQuery mobile. I have a JSON callback function, and once that function returns a value (say YES or NO), then I either want to transition to a specific page or display an error message. Could somebody provide some sample code on how to write this transition?
I get that the href should look something like this:
Next page
But how do I call this from within a javascript callback function? Thanks!
Invoking changePage from your callback should accomplish what you are trying to do.
Your_Callback(){
if(YES) {
changePage("nextPage.html");
} else if(NO){
changePage("errorPage.html");
}
}
Would it be possible to share the JS code that's not working for you?
There is a method for this purpose:
$.mobile.changePage('nextPage.html')
Check de documentation to see the parameter it accepts
Did you consider writing the page in PHP to create a session cookie?
`session_start();
$url = $_SESSION['back'];'
in the jquery you would use:
window.location ="'.$url.'";
or
maybe try location.href = "myPage.html"