Can we catch in Selenium WebDriver events generated by the user (or events in general)? I know we can check state of page f.e. with WebDriverWait and ExpectedConditions, but that is not always appropriate.
Let's say I wanted to wait for user input to continue execution of test class. It would look something like this:
driver.get("https://www.google.com");
waitForKey(driver, org.openqa.selenium.Keys.RETURN);
/* rest of code */
driver.quit();
Where waitForKey would be implemented as:
public static void waitForKey(WebDriver driver, org.openqa.selenium.Keys key) {
Wait wait = new WebDriverWait(driver, 2147483647);
wait.until((WebDriver dr) -> /* what should be here? */);
}
Is there any way to do this?
I never heard that Selenium support it. However, you can make it yourself by adding an eventListener to the document to create or change DOM. Then you can use Selenium to detect the change. See my example below.
The example uses JavaScript Executor to add a keydown listener to the document. When the key Enter has been pressed, it will create a div with ID onEnter and then add it to the DOM. Finally, Selenium will looking for the element with ID onEnter, and then it will click a link in the web.
driver.get("http://buaban.com");
Thread.sleep(5000);
String script = "document.addEventListener('keydown', function keyDownHandler(event) {" +
" const keyName = event.key;" +
" if(keyName===\"Enter\") {" +
" var newdiv = document.createElement('DIV');" +
" newdiv.id = 'onEnter';"+
" newdiv.style.display = 'none';"+
" document.body.appendChild(newdiv);" +
" }" +
"});";
((JavascriptExecutor)driver).executeScript(script);
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("onEnter")));
driver.findElement(By.cssSelector("#menu-post a")).click();
Thread.sleep(5000);
Related
I have problem to automate this drop down using selenium web driver using Java
This is the link - Go to 5th drop down named as Github users (fetch. js)
I am not able to enter the data into search field.
I am using send keys after perform click but it throws an exception like this " element is not interact able"
Steps I follow
driver.findElement(By.xpath("xapth")).click
drop down opens with no options because it is searchable and options are coming dynamically after entering key word into the search field.
driver.findElement(By.xpath("xapth")).sendkeys("Test");
Sendkeys are not working in this case because of drop down closed when perform send keys action.
<div class="Select-placeholder">Select...</div>
Below is the code which is working.
Please do optimize the code by removing thread.Sleep and putting some meaningful waits as per your requirement.
driver.Navigate().GoToUrl("https://jedwatson.github.io/react-select/");
IWebElement element1 = driver.FindElement(By.XPath("//span[#id='react-select-6--value']"));
IWebElement element2 = driver.FindElement(By.XPath("//span[#id='react-select-6--value']/div[2]/input[1]")) ;
element1.Click();
Thread.Sleep(2000);
element2.SendKeys("Test");
Thread.Sleep(1000);
element2.SendKeys(Keys.Tab);
Please note that element2 gets activated once you click on element1.
Try the following code:
public void typeAndSelect() {
WebElement searchBox = driver.findElement(By.xpath("//div[#class='section'][5]//div[#class='Select-control']"));
searchBox.click();
WebElement inputField = driver.findElement(By.xpath("//div[#class='section'][5]//input[#role='combobox']"));
inputField.clear();
String searchWord = "test";
inputField.sendKeys(searchWord);
WebElement selectDropdown = driver.findElement(By.xpath("//div[#class='Select-menu-outer']//div[#role='option'][text()='" + searchWord +"']"));
// wait for search results.
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(selectDropdown)).click();
}
Correct the following xpath part
"//div[#class='section'][5]"
to your implementation of the dropdown
I have a question regarding selenium wait.
I want selenium to wait until a text displayed in specific xpath.
the text is: "Hensley and Workman Trading"
the xpath is: //td[#class='td_company ng-star-inserted']
I tried the wait until.attributeTobe function but can not make it wait.
What I am doing wrong (I think the until row is not working, the order or condition true)
public static void getWebElementByXpathWithWaitTextToBeSeen()
{
WebDriver driver2 = WebDriverMgr.getDriver();
// driver2.manage().timeouts().implicitlyWait(IMPLICIT_WAITE, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(driver2,EXPLICIT_WAITE);
wait.until(ExpectedConditions.attributeToBe(By.xpath("//td[#class='td_company ng-star-inserted']"),"Hensley and Workman Trading","true"));
}
From Dev Tool:
To wait for the text Hensley and Workman Trading to be displayed within the WebElement you can use the following Locator Strategies:
new WebDriverWait(driver, 20).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//td[#class='td_company ng-star-inserted']"), "Hensley and Workman Trading"));
OpenQA.Selenium.Support.UI implements wait.Until(expectedCondition) functionality. Here's an example of what you're trying to do:
public static void WaitForElementText(this IWebDriver driver, By by, string text)
{
var wait = new WebDriverWait(driver, TimeoutScope.Current.Timeout);
wait.Until(d => d.FindElement(by).Text == text);
}
In your case, it would look like this:
var wait = new WebDriverWait(driver, TimeoutScope.Current.Timeout);
wait.Until(d => d.FindElement(By.XPath("//td[#class='td_company ng-star-inserted']")).Text == text);
Try
" Hensley and Workman Trading " // With the extra spaces
instead of
"Hensley and Workman Trading"
Not positive, but those spaces may be throwing it off?
My Selenium test looks something like this: customer selects a financial product, fills some necessary data and is presented with terms / agreement document in print preview (as required by local law). After printing / closing the print preview dialog customer enters more data and proceeds further, selects some options and finally gets another print preview of the contract. After that he confirms contract and process is done. I run my tests against Chrome version 75.
So far I've tried two things:
1. Switching to the print preview using Selenium, navigating to the "Cancel" button trough DOM and clicking it. But because the dialog uses shadow DOM it's very ugly, hard to maintain and frequently breaks after Chrome updates.
2. Tried using Robot class from awt, it works well when running locally but fails when running on Selenium grid because Chrome window is not focused and does not receive keyboard events.
Current state of the method handling the closure of print dialog:
public void closePrintPreview() {
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(driver -> driver.getWindowHandles().size() > 1);
driver.switchTo().window(driver.getWindowHandles().toArray()[1].toString());
wait.until(d -> {
if (d.getWindowHandles().size() > 1) {
d.switchTo().window(driver.getWindowHandles().toArray()[1].toString());
try {
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ESCAPE);
robot.keyRelease(KeyEvent.VK_ESCAPE);
} catch (AWTException e) {
throw new RuntimeException(e);
}
return false;
}
return true;
});
driver.switchTo().window(driver.getWindowHandles().toArray()[0].toString());
}
So my question would be if there is a simpler way to get the "Cancel" button in print print preview or maybe some way to force the Chrome window to be focused so it can receive key events from Robot?
Here is the solution in python.
You can update the same to work in java.
Python:
def cancelPrintPreview():
# get the current time and add 180 seconds to wait for the print preview cancel button
endTime = time.time() + 180
# switch to print preview window
driver.switch_to.window(driver.window_handles[-1])
while True:
try:
# get the cancel button
cancelButton = driver.execute_script(
"return document.querySelector('print-preview-app').shadowRoot.querySelector('#sidebar').shadowRoot.querySelector('print-preview-header#header').shadowRoot.querySelector('paper-button.cancel-button')")
if cancelButton:
# click on cancel
cancelButton.click()
# switch back to main window
driver.switch_to.window(driver.window_handles[0])
return True
except:
pass
time.sleep(1)
if time.time() > endTime:
driver.switch_to.window(driver.window_handles[0])
break
Java:
public void closePrintPreview() {
String jsCancel = "return document.querySelector('print-preview-app')" +
".shadowRoot.querySelector('#sidebar')" +
".shadowRoot.querySelector('print-preview-header#header')" +
".shadowRoot.querySelector('paper-button.cancel-button')";
WebDriverWait wait = new WebDriverWait(driver, 5);
JavascriptExecutor jse = (JavascriptExecutor) driver;
WebElement cancelButton;
wait.until(driver -> driver.getWindowHandles().size() > 1);
driver.switchTo().window(driver.getWindowHandles().toArray(new String[0])[1]);
while (driver.getWindowHandles().size() > 1) {
driver.switchTo().window(driver.getWindowHandles().toArray(new String[0])[1]);
cancelButton = (WebElement) jse.executeScript(jsCancel);
cancelButton.click();
}
driver.switchTo().window(driver.getWindowHandles().toArray(new String[0])[0]);
}
You can check my answer here for more information on working with shadow-root elements.
Here is the Java implementation based on answer by #supputuri:
public void closePrintPreview() {
String jsCancel = "return document.querySelector('print-preview-app')" +
".shadowRoot.querySelector('#sidebar')" +
".shadowRoot.querySelector('print-preview-header#header')" +
".shadowRoot.querySelector('paper-button.cancel-button')";
WebDriverWait wait = new WebDriverWait(driver, 5);
JavascriptExecutor jse = (JavascriptExecutor) driver;
WebElement cancelButton;
wait.until(driver -> driver.getWindowHandles().size() > 1);
driver.switchTo().window(driver.getWindowHandles().toArray(new String[0])[1]);
while (driver.getWindowHandles().size() > 1) {
driver.switchTo().window(driver.getWindowHandles().toArray(new String[0])[1]);
cancelButton = (WebElement) jse.executeScript(jsCancel);
cancelButton.click();
}
driver.switchTo().window(driver.getWindowHandles().toArray(new String[0])[0]);
}
I am trying to navigate to "https://developers.google.com/".
I then click a link by the xpath and redirect to another page.
Everything works as far as finding elements and clicking links on the first page.
But I cannot seem to find the elements I want to look for after I go to the new page.
The redirected page is "https://cloud.withgoogle.com/next18/sf/?utm_source=devsite&utm_medium=hpp&utm_campaign=cloudnext_april18"
This is checking if text is equal.
confirmText("Imagine", "//*[#id=\"main\"]/span/div[2]/div/div/div[1]/div[1]/div/div[1]/div[2]/h3");
public static void confirmText(String text, String xpath) {
System.out.println("Trying to confirm that given string is equal to the text on page.");
WebElement element = driver.findElement(By.xpath(xpath));
System.out.println("Test case: " + text);
System.out.println("Result: " + element.getText());
if (element.getText() == text) {
System.out.println("\nEquals.");
}
else {
System.out.println("\nDoes not equals.");
}
System.out.println("\n\n");
}
This is sending keys.
public static void sendKeys() {
WebElement firstname = driver.findElement(By.id("firstName"));
firstname.sendKeys("John");
WebElement lastname = driver.findElement(By.xpath("//*[#id=\"lastName\"]"));
lastname.sendKeys("Doe");
WebElement email = driver.findElement(By.xpath("//*[#id=\"email\"]"));
email.sendKeys("johndoe#gmail.com");
WebElement jobtitle = driver.findElement(By.xpath("//*[#id=\"jobTitle\"]"));
jobtitle.sendKeys("Software Engineer");
WebElement company = driver.findElement(By.xpath("//*[#id=\"company\"]"));
company.sendKeys("ABCD");
}
The error is
Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id="main"]/span/div[2]/div/div/div[1]/div[1]/div/div[1]/div[2]/h3"}
Only the first page actually waits to finish loading before the script starts. If you navigate away form the page then you will need to manually wait. Without waiting, the script will continue to the next command immediately after clicking the link that changes the page, and since the page is not loaded yet you will not find the element. This gives the error.
The simplest way to wait is by using "WebDriverWait"
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id(>someid>)));
There are more simple examples here:
http://toolsqa.com/selenium-webdriver/wait-commands/
You can try this xpath using for imagine and put some wait as #chris mentioned
//div//h3[contains(text(),'Imagine')]
JavascriptExecutor can be used to get the value of an element,
Refer code,
confirmText("Imagine", "//*[#id=\"main\"]/span/div[2]/div/div/div[1]/div[1]/div/div[1]/div[2]/h3");
public static void confirmText(String text, String xpath) {
System.out.println("Trying to confirm that given string is equal to the text on page.");
WebElement element = driver.findElement(By.xpath(xpath));
JavascriptExecutor executor = (JavascriptExecutor)driver;
System.out.println("Test case: " + text);
System.out.println("Result: " + executor.executeScript("return arguments[0].innerHTML;", element););
if (text.equals(executor.executeScript("return arguments[0].innerHTML;", element))) {
System.out.println("\nEquals.");
}
else {
System.out.println("\nDoes not equals.");
}
System.out.println("\n\n");}
I have logged into a website page using automation code (Selenium) but now there are fields in which data needs to be entered
But how to do this using Selenium?
How to write the code for it?
Use sendKeys method.
driver.findElement(By.id("InputBox_ID")).sendKeys("Test data");
Use following lines of code to insert value into text.
WebElement Element1 = driver.findElementByName("abc");
Element1.sendKeys("value that you want to enter.");
When searching for a field to fill in, right click on its element in the web page and click "Inspect Element". The ID should be highlighted in the popup menu, and that is going to be the ID You specify into the "By.xpath()" Method from seleniums API.
Here is an example on how to fill in fields for Gmail.
System.setProperty("webdriver.gecko.driver", "/path/to/geckodriver");
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability("marionette", true);
WebDriver driver = new FirefoxDriver();
driver.get(Links.Register_Gmail);
driver.findElement(By.xpath("//*[#id='FirstName']")).sendKeys(firstname);
driver.findElement(By.xpath("//*[#id='LastName']")).sendKeys(lastname);
driver.findElement(By.xpath("//*[#id='GmailAddress']")).sendKeys(username);
driver.findElement(By.xpath("//*[#id='Passwd']")).sendKeys(password);
driver.findElement(By.xpath("//*[#id='PasswdAgain']")).sendKeys(password);
driver.findElement(By.xpath("//*[#id='BirthMonth']")).click();
driver.findElement(By.xpath("//*[#id=':" + random(1, 9) + "']")).click();
driver.findElement(By.xpath("//*[#id='BirthDay']")).sendKeys("" + random(1, 27));
driver.findElement(By.xpath("//*[#id='BirthYear']")).sendKeys("" + random(1950, 1990));
driver.findElement(By.xpath("//*[#id='Gender']")).click();
driver.findElement(By.xpath("//*[#id=':f']")).click();
driver.findElement(By.xpath("//*[#id='submitbutton']")).click();
driver.findElement(By.xpath("//*[#id='tos-scroll-button']")).click();
driver.findElement(By.xpath("//*[#id='tos-scroll-button']")).click();
driver.findElement(By.xpath("//*[#id='tos-scroll-button']")).click();
driver.findElement(By.xpath("//*[#id='iagreebutton']")).click();
you can do it simply by just right click on the field that you want to fill and click inspect, if you are using firefox then it is quiet simple by using firepath but if you are using chrome then simply right click on the field, click on inspect element and find a unique id of that field and put it inside these below lines
driver.findelement(By.id("")).sendelement(""),
you can use different field than id if you find something else unique.
You can use the below method and call it wherever you want to enter text
public static void enterTextInput(WebElement element, String value) throws InterruptedException{
String val = value;
element.clear();
Thread.sleep(1000);
for (int i = 0; i < val.length(); i++){
char c = val.charAt(i);
String str = new StringBuilder().append(c).toString();
element.sendKeys(str);
}
Thread.sleep(1500);
}