Switch to top-level frame with Selenium - selenium

What is the best way to switch to the top-level frame in Selenium if I'm unsure of the nesting level?
I tried using this code, but ParentFrame() doesn't throw an exception if you are already at top-level so it doesn't work.
while (true)
{
try { driver.SwitchTo().ParentFrame(); } catch { break; }
}

If you want to return to the main content from Iframe use this
driver.switchTo().defaultContent();

Related

protractor + cucumber - element not visible even though element is visible

this.When(/^the user clicks on login button$/, function () {
return browser.wait(wagLoginPage.loginPage.signIn.isPresent().then(function (visible) {
if(visible){
console.log("element is visible !!!!!!!");
wagLoginPage.loginPage.signIn.click().then(function(){
expect(visible).to.be.true;
});
}
else{
expect(visible).to.be.true;
}
}, function () { chai.assert.isFalse(true, "SingIn is not visible!") }));
});
My test randomly fails in the above step. For the above code, in console window protractor prints 'element is visible'. But if I perform click event on the element it throws element is not visible exception.
Update
Questions is answered here
Your element is present, but it's probably not visible.
Try this:
return browser.wait(wagLoginPage.loginPage.signIn.isDisplayed().then(function (visible){
//Your stuff
}
Note, I'm using isDisplayed() vs. isPresent().
isPresent() is useful if you are checking if an element is on the page, but may or may not be visible.
isDisplayed() is useful if you are checking if an element is visible on the page.

How to continue webdriver/selenium after error

I'm doing a test bot with webdriver. I have a scenario where it clicks on a button, a new windows open, and it searches for an element by a specific xpath, but sometimes there is no such element because it can be disabled and i get this error: org.openqa.selenium.NoSuchElementException. How can i bypass it/continue the bot so it just closes the new windows if it doesn't find the element with that xpath and just continue with the code?
In Java :
List<WebElement> foundElement = driver.findElements(By.xpath("<x-path of your element>"));
if (foundElement.size() > 0)
{
// do whatever you want to do in **presence** of element
} else {
// do whatever you want to do in **absence** of element
}
You need to surround the click event with a try/catch statement, and inside the catch statement check if the exception is the one you are trying to bypass:
try {
driver.findElement(by).click();
} catch(Exception e) {
if ( !(e instanceof NoSuchElementException) ) {
throw e;
}
}

protractor iframe inside an iframe inside an iframe

I'm trying to get to controls inside a frame that is located inside a frame that is located inside another frame.
The last (deepest) frame is used only for login - that I manage to do.
The problem is that after the login I basically need to return to the upper frame and click a button. For some reason I keep getting the error:
NoSuchElementError: no such element
BTW, all the code in the frames is non-angular.
This is my code for the test:
it('Should get to drive sample app', function () {
login.get();
login.clickLogin();
browser.ignoreSynchronization = false;
login.goToUsecases(); //getting to the page
$('[href="/developers/api/1542"]').click();
browser.sleep(5000);
//iframe issue starts here
browser.switchTo().frame(0);
browser.ignoreSynchronization = true;
browser.switchTo().frame(0);
browser.switchTo().frame(0);
browser.driver.findElement(by.id('userName_str')).sendKeys("username");
browser.driver.findElement(by.id('password')).sendKeys("password");
browser.driver.findElement(by.name('submit')).click();
// login succeeded
browser.sleep(10000);
browser.driver.switchTo().defaultContent();
browser.driver.findElement(by.id('home')).click();
browser.sleep(10000);
});
The problem is that after the login I basically need to return to the upper frame and click a button.
From what I see in your code, you are switching to the default content, but, as you said, the button is inside the upper iframe, switch to it:
browser.driver.switchTo().defaultContent();
browser.switchTo().frame(0);
browser.driver.findElement(by.id('home')).click();
You can try this may be this helps you.. As this works for me for handling different windows.
browser.getAllWindowHandles().then(function (handles) {
newWindowHandle = handles[1];
browser.ignoreSynchronization = true;
browser.switchTo().window(newWindowHandle).then(function () {
browser.sleep(500).then(function () {
browser.ignoreSynchronization = true;
browser.driver.findElement(by.id('userName_str')).sendKeys("username");
browser.driver.findElement(by.id('password')).sendKeys("password");
browser.driver.findElement(by.name('submit')).click();
//login succeeded
});
//to close the current window
browser.driver.close().then(function () {
//to switch to the previous window
browser.switchTo().window(handles[0])
browser.driver.findElement(by.id('home')).click()
browser.sleep(10000);
});
});
});
Instead of ::browser.switchTo().frame(0);
try giving the locate of the iframe where you want to switch too.. that might help.
// Switch to iframe context in order to see inside iframe
browser.switchTo().frame(element(by.tagName('iframe')));

How to create an if statement in selenium that would run if a certain box was not checked?

I am trying to run an if statement in selenium that would verify if a checkbox was checked and if it was not perform a certain action. I tried
if (selenium.verifyChecked("checkbox")=false){
//perform actions
} else {
//perform different actions
};
and it said that that did not work. How would you do it?
The Selenium command isChecked returns a boolean, so you should be able to do the following:
if (selenium.isChecked("checked")) {
//perform actions
} else {
//perform different actions
};
if (selenium.verifyChecked("checkbox")=false){
Is wrong. It's assigning false to the return value of the function, which is clearly wrong.
It should be:
if (selenium.verifyChecked("checkbox") == false) {

Detecting browser print event

Is it possible to detect when a user is printing something from their browser?
To complicate matters, if we are presenting a user with a PDF document in a new window is it possible to detect the printing of that document ( assuming the user prints it from the browser window)?
The closest I've been able to find is if we implement custom print functionality (something like this) and track when that is invoked
I'm primarily interested in a solution that works for internet explorer (6 or later)
You can now detect a print request in IE 5+, Firefox 6+, Chrome 9+, and Safari 5+ using the following technique:
(function() {
var beforePrint = function() {
console.log('Functionality to run before printing.');
};
var afterPrint = function() {
console.log('Functionality to run after printing');
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function(mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
}());
I go into more detail into what this is doing and what it can be used for at http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/.
For Internet Exploder, there are the events window.onbeforeprint and window.onafterprint but they don't work with any other browser and as a result they are usually useless.
They seem to work exactly the same for some reason, both executing their event handlers before the printing window opens.
But in case you want it anyway despite these caveats, here's an example:
window.onbeforeprint = function() {
alert("Printing shall commence!");
}
For anyone reading this on 2020.
The addListener function is mostly deprecated in favor of addEventListener except for Safari:
if (window.matchMedia) {
const media = window.matchMedia("print");
const myFunc = mediaQueryList => {
if (mediaQueryList.matches) {
doStuff();
}
};
try {
media.addEventListener("change", myFunc);
} catch (error) {
try {
media.addListener(myFunc);
} catch (error) {
console.debug('Error', error)
}
}
}
Reference: This other S.O question
If it's only for tracking purposes, perhaps you could set a background url in CSS print media to a server page (.aspx, .php, etc) and then do something on the server?
This guy claims it works.
This is not as versitile as TJ's solution, but it may be less buggy (see TJs blog post for issues he found) when only tracking is needed.