How to find "Cursor" position in webpage with Selenium Webdriver? - java

I just started learning Selenium Webdriver using java Script, the question what I have asked might me a silly one. But still wanted to know whether it is possible or not.
As per my question, please go through the below example
In any Login page, enter valid "Username" and click on "signin" button, it throws an error message "Please enter password" and the "cursor" will be located in "Password" field
So, we can get the error message via code. Now, how can we locate or identify the "Cursor" position in the webpage via code?

By definition, any widget that has focus also has the cursor. So driver.switchTo().activeElement() will return the currently focused WebElement. It doesn't actually change anything, just returns the active element. You can call
expectedElement.equals(driver.switchTo().activeElement());
to verify that expectedElement has focus.

Hey user3313128 with Selenium Web driver library it is only possible to figure out the current position by knowing the last place you moved it to.
Javascript sadly dose not give you an option to quickly get the X & Y.
An easy work around this is to simple run an simple function in the browser
async function (){
await this.driver.executeScript(function( ) {
let mouse = { x:0, y:0 }
onmousemove = function(e){ mouse.x = e.clientX, mouse.y = e.clientY }
})
}
this function will track your mouses X and Y in the browser the whole time
Then when you need to know mouse's location just call this script
mouse = driver.executeScript( function (){return mouse})
although the smart move is to track all of this within your JS on the server side at each mouse move and click().

Related

How to use applescript to close upload dialog window from chromedriver instance?

I have a selenium test (selenide to be precise) where the scenario requires a file upload.
The element to which I'm uploading the file is a hidden input field which is located at the end of DOM;
<input type="file" style="height: 0; width: 0; visibility: hidden;" tabindex="-1" accept="*">
and appears only after clicking on the area where the file is supposed to be "drag&dropped" or loaded from the system;
<a class="browse" ref="fileBrowse" href="#">select files...</a>
that means I am unable to use any method I've known until now without the need to click the element first - e.g., sendKeys, uploadFile, uploadFromClassPath, etc. However, the moment I click the element, a dialog window appears. After loading the file, the window won't close and I have yet to find a robust solution to close that window.
Situation how the dialog window looks within the macOS and chrome setup
I am using macOS and chrome, which means I cannot use "autoIT", and I was not able to run "sikuliX" either to create a simple screenshot script.
I was able, however, to scramble up an applescript using Automator which worked fine provided we omit the web driver's instance existence. Meaning; if I run the script from the console, setting the website exactly as the automated test would find it - it works... Unfortunately, it does not work once the test instantiates and runs within the webdriver.
I have two questions I hope someone with more experience could answer:
1) How to make the applescript use the webdriver's instance and not the regular chrome window - should this be solved somehow, it's a pretty neat solution
2) Any other idea on how to close the upload dialog window?
The applescript
on run {input, parameters}
-- Click “Google Chrome” in the Dock.
delay 6.006100
set timeoutSeconds to 2.000000
set uiScript to "click UI Element \"Google Chrome\" of list 1 of application process \"Dock\""
my doWithTimeout( uiScript, timeoutSeconds )
return input
-- Click the ÒCancelÓ button.
delay 3.763318
set timeoutSeconds to 2.0
set uiScript to "click UI Element \"Cancel\" of sheet 1 of window \"PowerFLOW portal - Google Chrome\" of application process \"Chrome\""
my doWithTimeout(uiScript, timeoutSeconds)
return input
end run
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"
" & uiScript & "
end tell"
exit repeat
on error errorMessage
if ((current date) > endDate) then
error "Can not " & uiScript
end if
end try
end repeat
end doWithTimeout
the code used to run the script within the test
try {
new ProcessBuilder("/path/to/the/script").start();
} catch (IOException e) {
e.printStackTrace();
}
}
Besides trying to use the applescript, I've tried "java robot class" but I wasn't able to close the dialog window.
Using the snippet below, the uncommented part escapes the entire chrome window (the window goes "grey"/inactive) and not the dialog window, which honestly surprised me, as I have thought the dialog window was the main working window at that moment.
The part that is commented works, but as you can imagine, it is useless, should the test be run on any other machine as the coordinates are specific to my machine only.
try {
Robot robot = new Robot();
//robot.mouseMove(906, 526);
//robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
//robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.keyPress(KeyEvent.VK_ESCAPE);
robot.keyRelease(KeyEvent.VK_ESCAPE);
} catch (AWTException e) {
e.printStackTrace();
}
The method itself looks just about like this
$$x("#ElementsCollection")
.findBy("text1")
.scrollIntoView(true)
.find(byXpath("#xpath")).val("text2")
.find(byXpath("#xpath") //this is the location of the <a> element mentioned above that needs to be clicked in order for <input type file> element to appear
.click();
$x("//input[#type=\"file\"]").sendKeys("/path/to/the/uploadedFile");
As I see, the original complexity on the way to achieve the goal is
the file is a hidden input field
and appears only after clicking on the area where the file is supposed to be "drag&dropped" or loaded from the system;
I.e. – the hidden file. Correct me if am wrong:)
But this should not be the problem, because the Selenium WebDriver's sendKeys command works with hidden elements of input tag with type=file. So just simple sendKeys should pass. The Selenide's uploadFromClassPath command is based on the original sendKeys - so it should pass too.
Here is a simple test that shows that uploading file does not depend on visibility of input element:
import org.junit.jupiter.api.Test;
import static com.codeborne.selenide.Condition.hidden;
import static com.codeborne.selenide.Condition.text;
import static com.codeborne.selenide.Selenide.*;
import static com.codeborne.selenide.Selenide.$;
public class TheInternetTest {
#Test
void fileUpload() {
// GIVEN
open("https://the-internet.herokuapp.com/upload");
executeJavaScript(
"document.getElementById('file-upload').style.display = 'none'"
);
$("#file-upload").shouldBe(hidden);
// WHEN
$("#file-upload").uploadFromClasspath("temp.txt");
$("#file-submit").click();
// THEN
$("#uploaded-files").shouldHave(text("temp.txt"));
}
}
Check the full working project with this code here: https://github.com/yashaka/selenide-file-upload-demo/blob/main/src/test/java/TheInternetTest.java
P.S.
The common best practice when writing Web UI Tests is "find the simple way to reach the goal instead of the best way in context of real user simulation". That's why we try to bypass all windows that are out of control for application under test. So my recommendation would be - forget apple script, and work with the input file directly through selenium webdriver.

How to figure out identifier of input fields from external pop up window

I am trying to put username and password to pop up window. The trouble is that this is some kind of modal or some external window where I can´t find any xpath, id etc... element how to identify this fields. I have came through all topics regarding this but non of them helped me in Java for cucumber/selenium.
Using "https://username:password#wedomain.cz/" doesn´t work.
Using code like this:
WebElement email_id = driver.findElement(By.linkText("Uživatelské
jméno"));
email_id.sendKeys("XXX");
WebElement password_id = driver.findElement(By.linkText("Heslo"));
password_id.sendKeys("xxx");
Thread.sleep(5000);
WebElement sign = driver.findElement(By.linkText("Přihlaste se"));
sign.click();
Doesn´t work. I must also say that domain I go to is different from domain I see on security pop up window.
SOLUTION - need to be done with robot class or another automation library.
https://www.guru99.com/using-robot-api-selenium.html
Closing question.

Selenium Java - Click if element exists, continue with the next command if element not found

i'm trying to create a script to test a web site (js application), code is almost done but i encounter a problem. The script its supposed to edit a question on the website (the question uses a lot of variables from a database) and depending on were the script failed or if anyone else edited the question there is a chance for the script to get a pop-up message(not a separate window or new tab). I want the code to:
Click the element if present or go to the next line of code if the element does not exist.
I tried using but it does not help:
Alert alert = driver.switchTo().alert();
alert.accept();
My code:
driver.findElement(By.xpath("//button[2]")).click();
// Click unselect all
Thread.sleep(1000);
driver.findElement(By.linkText("Romania")).click();
// Select Romania
log.debug("Select Romania");
Thread.sleep(2000);
driver.findElement(By.linkText("Germany")).click();
// Select Germany
log.debug("Select Germany");
Thread.sleep(2000);
driver.findElement(By.xpath("//div[4]/a")).click();
// Click Save Button
log.debug("Click Save");
Thread.sleep(3000);
**driver.findElement(By.xpath("//div[4]/div/div/div/div/div/button")).click();**
// Pop-up message
log.debug("Click Pop-up message");
Thread.sleep(3000);
/////////////// Single Answer
driver.findElement(By.linkText("Change")).click();
// Click Change Template
log.debug("Click Change");
Thread.sleep(2000);
The you can find the line with the issue between **** (pop-up), how can i click if the element exists or move to driver.findElement(By.linkText("Change")).click(); if element not found.
Please let me know if more info is required.
Edit:
To give more details about why the pop-up appears. The script edits a question, the questions have multiple templates and the script is supposed to go through each template after selecting the template the script will associate a variable from the database to the question.
Templates:
Single answer question
Single answer dropdown question
Multiple answer question
Multiple answer dropdown question
Date
The pop-up message appears as a warning (that the variable used will be removed )when the template is changed from multiple answer to single answer/date or the other way around.
In the perfect case if the script finishes successfully (it will end with single answer dropdown - first question is single answer so the pop-up does not appear )and no one edits the question i will not encounter the pop-up but if the script fails due to x reason after changing the template to multiple answer, when i restart the script i will receive that pop-up/warning.
The issue also occurs when changing the language of the question as shown in the code above, i have multiple steps were i encounter this problem.
At the moment in order for the script to run and avoid the problem mentioned above, i need to edit the question myself and select a specific language and template before running the script.
If no matching elements are found, an instance of NoSuchElementException is thrown.
try {
WebElement popUp = driver.findElement(By./**your expression**/);
popUp.click();
} catch(NoSuchElementException | StaleElementReferenceException e) {
log.debug("Impossible to click the pop-up. Reason: " + e.toString());
}
I'd recommend two approaches.
Simply poll the DOM for the pop-up and click the button if exists:
List<WebElement> button = driver.findElements(By.xpath("//div[4]//button"));
if (!button.isEmpty()) {
button.get(0).click();
}
....
driver.findElements() is used to avoid try-catching NoSuchElementException in case using driver.findElement()
You may use explicit wait to wait some time for the button to appear:
try{List<WebElement> button = (new WebDriverWait(driver,10)).until(ExpectedConditions.presenceOfElementsLocated(By.xpath("//div[4]//button")));
if (!button.isEmpty()) {
button.get(0).click();
}
}
catch(TimeoutException e)
{
}

Selenium - Text entered in same field, even though intended to type in different fields

Using selenium, when trying to enter username and password in login form, sometimes the text is entered on the same field. Username and password are having unique identifier.
For sending keys, the following steps are done.
sendKeys(By.id("login_username"), "abc");
sendKeys(By.id("login_password"), "efg");
public void sendKeys(By locator, String text) {
WebElement element = findElement(locator);
if(element != null) {
element.clear();
element.sendKeys();
}
}
public WebElement findElement(By locator) {
return wait(org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated(locator));
}
public WebElement wait(ExpectedCondition<WebElement> condition) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).pollingEvery(1, TimeUnit.SECONDS)
.withTimeout(60, TimeUnit.SECONDS)
.ignoreAll(Arrays.asList(NoSuchElementException.class, TimeoutException.class));
return wait.until(condition);
}
But somehow, when entering text, both the username and password texts are getting typed onto the password field. This is not happening always though. Not able to understand what could possibly go wrong or what to check. Any suggestions...
platform: Ubuntu 16.04.1 LTS 64-bit
chromedriver version: 2.25
chrome browser version: 55.0.2883.87
Thanks in advance.
The sendKeys() action performs the following steps:
Gets the coordinates of the element
Clicks at the coordinates it got (using a mouse action)
"Types" the text (that will be received by whatever element is currently focused)
It can go wrong if the element can't be focused when starting the action (because it's disabled for example), or if the coordinates change between getting the coordinates and clicking/focusing the element (because the layout is still changing).
Another common cause can be onClick action hooked on the element, that can lead to race conditions. Without seeing the actual page, it is possible that after selenium clicks, an onClick action is still working when the text is being typed. This basically looks like this:
Selenium clicks
onClick action starts (element might get focused only after it finishes)
Selenium starts typing (onClick haven't
returned yet, so the wrong elements gets the text)
the onClick
action finishes, but by that time Selenium finished too.
As a solution you can try focusing the element directly, and wait until it is really focused before sending the keys. This question might be of use for this case.

Selenium Chrome Driver send key press combinations to window

I need to perform a key press combination on Selenium Chrome driver.
The action is not sending test to text box or clicking on a button.
I am actually not interested in sending keys to any specific web element.
For example, I would like to perform command+R (reload on Mac OS).
(Reloading is just an example for the explanation, not my ultimate goal)
My code is the following:
public static void keyPressCombnaiton() {
Actions action = new Actions(browser);
action.keyDown(Keys.COMMAND)
.sendKeys("r")
.keyUp(Keys.COMMAND)
.build()
.perform();
}
I have spend hours searching and trying only got no luck.
Any help is appreciated!
The WebDriver spec is element-focussed, and doesn't define any method to send keys to the window, the screen, to browser chrome - only to elements.
Use of the Selenium Actions class for Cmd-R works on my Mac in Firefox (45), but only when run in the foreground - and seemingly not at all in Chrome. Presumably this is down to differences in the implementations of the remote Keyboard implementation, which it's probably best not to rely upon.
The most efficient way and non-platform-specific way to request a page reload is using JavaScript:
((JavascriptExecutor) driver).executeScript("document.location.reload(true)");
However, JavaScript doesn't let you "just send keys".
The only other way is via the Java AWT Robot class:
Robot robot = new java.awt.Robot();
robot.keyPress(KeyEvent.VK_META); // See: http://stackoverflow.com/a/15419192/954442
robot.keyPress(KeyEvent.VK_R);
robot.keyRelease(KeyEvent.VK_R);
robot.keyRelease(KeyEvent.VK_META);
This "blindly" sends key combinations to whichever windows / components are on screen at the time, so if your browser window has been hidden or minimised, this will not work.

Categories

Resources