Selenium Firefox do not attach onClick event to submit button - java

I have a for that with a submit button that looks like this:
<input type="submit" class="btn btn-info pull-right save_button" id="save_button" value="Save"/>
Using JQuery I attach a onclick event to popup a confirmation box:
$('body').on("click", ".save_button", function() {
bootbox.confirm("Do you want these changes to be live in the website?",
function(result) {
if(result) {
$("#editPageForm").parsley().validate();
if( $("#editPageForm").parsley().isValid()) {
$("#editPageForm").submit();
}
}
});
return false;
});
When I test this step by hand everything works fine the form is validated and shows the confirmation box, and after pressing the OK button it saves the content as expect.
But if I use Selenium test I see all the steps going ok, but when the save button is pressed instead of firing this function it just submit the form.
This is the code used to create the driver:
FirefoxProfile profile = new FirefoxProfile();
profile.setEnableNativeEvents(true);
return new FirefoxDriver(profile);
Other Javascript code does work, but I am getting problems with this specific one.
I am using FF44 and selenium drivers I tried 2.48.2, 2.49.1, 2.50 and none of them worked
Did any of you experienced any similar issue?
Thanks

It may be because the page hasn't fully rendered and therefore the click listener hasn't been registered yet. Adding a wait may solve your problem, something like:
WebDriverWait buttonWait = new WebDriverWait(driver, 30L);
buttonWait.until(ExpectedConditions.visibilityOfElementLocated(By.id("someButton")));

Related

Button not working as expected in headless mode

I am using the latest chrome driver with selenium to test a web application hosted on Microsoft Azure.
The script starts by logging into the web application. An authentication window opens that requires the user to login through Azure and then press a, "Grant" button that will allow the web application to speak to a Therefore database to populate a few metadata fields.
This all works perfectly when headless mode is disabled. However, when headless mode is enabled it seems as though the, "Grant" button doesn't function. I am logging and taking screenshots during this process, which is how I know that the "Grant" button element is found and is being clicked. The button becomes highlighted when clicked, which is shown in the screenshot, but nothing happens and the authentication window times out in headless which kills the test.
I have tried different clicking methods, but this made no difference as the element is found and is being clicked. I have also pressed the, "Sign in as a different user" button on the form to ensure that the .click() method is functioning as expected, which of course works. I tried to add longer wait times but to no avail.
I have also added the following Chromium driver options:
ChromeOptions options = new ChromeOptions();
options.addArguments("enable-automation");
options.addArguments("--headless");
options.addArguments("--start-maximized");
options.addArguments("--window-size=1920,1080");
options.addArguments("--no-sandbox");
options.addArguments("--disable-extensions");
options.addArguments("--dns-prefetch-disable");
options.addArguments("--disable-gpu");
options.addArguments("--incognito");
options.addArguments("--disable-web-security");
options.addArguments("--allow-running-insecure-content");
options.addArguments("--disable-dev-shm-usage");
options.addArguments("--allow-insecure-localhost");
options.addArguments("--disable-popup-blocking");
options.setPageLoadStrategy(PageLoadStrategy.EAGER);
How I am clicking the element:
System.out.println("Grant permission...");
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//button[contains(text(),'Grant')]"))).click();
What baffles me is how this works seamlessly when headless is disabled but not when it's enabled. I'm wondering if this could be a Chrome driver issue? However I know that this is unlikely.
Any recommendations are appreciated, thanks.
Adding button HTML as requested:
<form method="POST">
<p>Hello, Test</p>
<ul>
<li class="text-left">Act with your access permissions</li>
<li class="text-left">Allow continuous access while you are not online.</li>
</ul>
<p>
<button type="submit" name="submit.Grant" value="Grant" class="btn btn-primary btn-block">Grant</button>
<button type="submit" name="submit.Login" value="Sign in as different user" class="btn btn-outline-primary btn-block">Sign in as different user</button>
</p>
Try adding a wait. I mean use WebDriverWait to wait for the element to be clickable.
Something like:
WebDriverWait wait = new WebDriverWait(webDriver, 20);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body/div/div/div/div/div/div/div[2]/form/p[3]/button[1]"))).click();
Also you need to improve your locator.
Absolute XPaths are extremely fragile.
First, try to avoid very long CSS or Xpath expression. You can find the button you need to click on like this:
driver.findElement(By.xpath("//button[contains(text(),'Grant')]"));
This code is more readable. If the site will be changed and the element will be moved to another div or span - your code will not work if it relays on the structure of all the divs and spans.
Next, never just click on an element of hover over it in a Selenium test. First check if the element is clickable, then click:
WebElement term = driver.findElement(By.xpath("//button[contains(text(),'Grant')]"));
WebDriverWait wait = new WebDriverWait(webDriver, 20);
wait.until(ExpectedConditions.elementToBeClickable(term));
term.click();

Problem with button with IE driver and Xpath Selenium with Java

i have the follow problem:
I have a button inside a form (the web page have a login and password text box and a button), this button calls a js funtion and after the login and password validation, calls the main web page. The html code is this (this code is inside of a form calls "login" and method = POST):
<INPUT class="btn btn-mini btn-primary" onclick=submitForm(); type=button value="Sign On">
In Selenium i try with the follow statements, but without success:
driver.findElement(By.xpath("//input[#type='button']")).click();
driver.findElement(By.cssSelector("input[type='button'][#value='Sign On']")).click();
driver.findElement(By.xpath("//input[#value='Sign On']")).click();
when i run the script, login and password text are filled correctly, but the click in the button it's no working.
Could you help me with this?
Thanks!
Gonzalo from Chile
To click on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
cssSelector:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("input.btn.btn-mini.btn-primary[value='Sign On'][onclick^='submitForm']"))).click();
xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[#class='btn btn-mini btn-primary' and #value='Sign On'][starts-with(#onclick, 'submitForm')]"))).click();
i found the solution, reading a lots of issues related with this. I'm working with win 10 and IE 11, so, Selenium has a problem with this, because need the size of the text, apps, and others items in 100%. In my case, i had this configuration in 150%. Fixing this, i run the script one again and it works.
The code used is:
WebElement button = null;
List<WebElement> inputs = webDriver.findElements(By.tagName("input"));
for (WebElement input : inputs) {
if (input.getAttribute("value").equals("Log In")) {
button = input;
break;
}
}
if (button == null) {
System.err.println("Cannot find button!");
} else {
System.out.println("Clicking button now!");
button.click();
}
After this, i check another code more efficient:
driver.findElement(By.cssSelector("input[type='button'][value='Sign On']")).click();
This works too.
thanks all off you for your help

How to switch to Md-dialog in selenium?

I am having an issue in regards to a md-dialog pop-up in an angularJS app that I am unable to click in selenium. When i click a button the dialog box appears and becomes the active element on the screen, darkening the background. I have tried switchTo with active element, frame, alert and none of these seem to work. My most recent attempt was trying to swap windows using the below code:
winHandleBefore = driver.getWindowHandle();
Set<String> numOfWindows = driver.getWindowHandles();
System.out.print(numOfWindows.size());
for(String winhandle : driver.getWindowHandles())
{
driver.switchTo().window(winhandle);
report.updateTestLog("Switched to window", "", Status.PASS);
}
the S.o.p for the size is always outputted as 1. There is a wait in after the initial button is clicked before the popup appears to assure it has the proper time to appear. Not sure what else there is to do, I have been scouring the internet for an answer and I haven't come across anything that will let me click the elements in that popup
Edit: This is the html for the md-dialog
<md-dialog class="quote _md md-transition-in" aria-label="Summary" role="dialog" tabindex="-1" id="dialogContent_78" aria-describedby="dialogContent_78" style="">
Edit 2: Forgot to say, I am trying to click a button inside the md-dialog popup
Edit 3: After reviewing the code a bit more I noticed that the md-dialog popup has a container div that is taking up the entire screen and that it is also calling in html from another file. The container div html:<div class="md-dialog-container ng-scope" tabindex="-1" style="top: 972px; height: 769px;">
In case someone has same issue the pop-up was registering as hidden even though it had appeared on screen, so any attempt to click a button was futile as the button was seen as hidden. The workaround was to find the button using the findElement() method, assign it to a variable and then use a javascriptExectutor to click it even though it was hidden. This is not ideal if you are trying to reproduce user input but it is a workaround. Code is below.
WebElement hiddenButton = driver.findElement(uniqueIdentifier);
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].click();", hiddenButton);
report.updateTestLog(flowName, uniqueIdentifier + " Hidden Button Pressed", Status.DONE);
Hope this helps anyone who finds it.

Selenium / Firefox: Command ".click()" doesn't work with a found element

I tried to find a solution to this thing and I spent a lot of time, but it is almost imposible to me to do that.
The matter: I am using Selenium with Java in Firefox. I need to find an element (a listbox) and click on it. So, the code finds the element, but click action does not work. It works fine in Google Chrome every time, and just sometimes in Firefox (with the same Java code sometimes works, and sometimes does not).
There is the part of code with the element when the program enters on the page:
<div id="size-btn" class="size-btn">
<span class="selected-size">SELECCIONA TALLA </span>
<div class="size-select" style="display: none;">
<table>
<tbody>
<tr id="selecsize_2" class="product-size" data-ga-props="{action:'Seleccionar_Producto', opt_label:'Escoger_Talla'}" data-catentryid="1051607">
<tr id="selecsize_3" class="product-size" data-ga-props="{action:'Seleccionar_Producto', opt_label:'Escoger_Talla'}" data-catentryid="1051608">
<tr id="selecsize_4" class="product-size" data-ga-props="{action:'Seleccionar_Producto', opt_label:'Escoger_Talla'}" data-catentryid="1051609">
<tr id="selecsize_5" class="product-size" data-ga-props="{action:'Seleccionar_Producto', opt_label:'Escoger_Talla'}" data-catentryid="1051610">
</tbody>
</table>
<button class="size-guide gaViewEvent gaTrack" data-ga-props="{action:'Seleccionar_Talla', opt_label:'Guia_de_tallas'}" data-href="http://www.anyweb.com/webapp/wcs/stores/servlet/ProductGuideSizeAjaxView?catalogId=24052&categoryId=358056&langId=-5&productId=1047599&storeId=10701">Guía de tallas</button>
</div>
</div>
And there is the part of code that changes when the element is clicked:
<div id="size-btn" class="size-btn opened">
I tried many solutions and sometimes it works, but the next time I run the program, it does not work again.
Some solutions:
It finds the element, but does not run click action. I checked with xpath and cssSelector, and there are unique elements found with those expressions.
driver.findElement(By.xpath("//div[#id='size-btn' and not(contains(#class,'opened'))]/span")).click(); // Also checked with By.cssSelector("span.selected-size")
I though it was because of the time, so I tried to solve it that way.
WebElement we = driver.findElement(By.xpath("//div[#id='size-btn' and not(contains(#class,'opened'))]/span")); // By.cssSelector("span.selected-size")
Thread.sleep(3000);
we.click();
Finally, I was a little bit desperate, and I created a new function to try to do this almost 60 times, looking for the change on the element code and if there was any change, just tried to do click action again.
clickAndWaitWhileElementIsNotPresent(By.xpath("//div[#id='size-btn' and not(contains(#class,'opened'))]/span"),By.xpath("//div[#class='size-btn opened']/span")); // By.cssSelector("span.selected-size")
private void clickAndWaitWhileElementIsNotPresent(By by1, By by2) throws Exception {
for (int second = 0;; second++) {
if (second >= 60)
fail("timeout");
try {
if (isElementPresent(by2))
{
break;
}
else
{
driver.findElement(by1).click();
}
} catch (Exception e) {
}
Thread.sleep(1000);
}
}
There are the images of the element:
Does anybody know how to do that?
Finally I found an answer that works with Firefox as well as Google Chrome.
WebElement we = this.driver.findElement(By.id("size-btn"));
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();", we);
waitForElementPresent(By.xpath("//div[#id='size-btn' and contains(#class,'opened')]/span"));
I am not sure why are you using this Xpath, if you have freedom to change Xpath then record the element using selenium IDE and use Xpath::position from drop down list of target(it picks unique path relative to html header), it will solve problem of dynamic locator. And try below mentioned events.
1- Use clickAt.
2- Use fireevent(focus) and then click. Sometime it happens some element in back ground is getting loaded, when it gets loaded, focus move there hence elementNotVisible error.
3- Use mouseDownRight.
I have the same problem in Firefox. The trick is to click the text inside of not the button itself.
I have some solution, make a class with a robot put there TAB event keys, then call that class. What it does its like a back to focus to the page. For some razon the page lost focus and never find that botton.
Robot robot;
try {
robot = new Robot();
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
} catch (AWTException e) {e.printStackTrace();}
You can try to use the Actions class from org.openqa.selenium.interactions:
WebElement element = driver.findElement(By.id("size-btn"));
Actions builder = new Actions(driver);
builder.moveToElement(element).click(element);
builder.perform();
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.click(element);
Action action = actions.build();
action.perform();
This worked for me.

Click inside iframe open event in parent (same domains)?

I want to use .slideToggle to open event details from my calendar (in iframe) My code is:
<div id="clickme"><iframe id="frame" src="index.php?option=com_jevents&view=month&task=month.calendar&template=ja_purity" mce_src="index.php?option=com_jevents&view=month&task=month.calendar&template=ja_purity">Your browser does not support iframes.</iframe></div>
<div id="book" style="display:none;"><iframe name="details" scrolling="no" frameborder="0"></iframe></div>
<script>
$('#clickme').click(function() {
$('#book').slideToggle('slow', function() {
// Animation complete.
});
});
</script>
You can see how it works here: wisko.pl
Now slide work only when i click iframe border. I'd like it to open when i click on event in calendar. Is it possible? How can i use .click function to check divs inside iframe?
Update:
Thank you. Still doesn't work. Am I doing something wrong? My main document has:
<script>
function showevent(){
$('#book').slideToggle('slow', function() {
// Animation complete.
});
}
</script>
In Iframe i put:
<script>
$('#eventstyle').click(function() {
document.parent.showevent();
}
</script>
in main document:
function showevent(){
$('#book').slideToggle('slow', function() {
// Animation complete.
});
}
inside iframe:
window.parent.showevent();
running this inside iframe will cause the function to run. And you have to catch the click event inside the iframe - you can't otherwise.
edit:
1. My bad: i put document.parent here instead of window.parent - fixed now
2. Your bad: when you use jquery to assign click events to things, you have to be sure these things already exist. all jquery code should be wrapped in $(document).ready(function(){/*your code here*/}); That's why it had no chance of working for you.

Categories

Resources