Problem in doing action on new window using Selenium Webdriver with java - java

I am working on Selenium with java, I open a driver change its proxy and do some actions, when I tried to switch to another window and change its proxy the actions don't happened, it showed this error
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.SearchContext.findElement(org.openqa.selenium.By)" because "this.searchContext" is null
if their is someone who has already worked with switching to windows and change proxy please help
I tried to use the method swith().to but I couldn't change the proxy so I tried to use another driver.
The code, First driver:
Proxy proxy = new Proxy();
proxy.setHttpProxy("http://" + proxyy);
proxy.setSslProxy("http://" + proxyy);
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.setCapability("proxy", proxy);
driver = new ChromeDriver(options);
randomSleep();
driver.get(JDD.url);
driver.manage().window().maximize();
Second driver:
Proxy proxy = new Proxy();
proxy.setHttpProxy("http://" + "104.227.100.66:8147");
proxy.setSslProxy("http://" + "104.227.100.66:8147");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.setCapability("proxy", proxy);
driver2 = new ChromeDriver(options);
randomSleep();
driver2.get(JDD.url);
driver2.manage().window().maximize();
profil("djfbadhz", "s9djq1ri28fz");
driver2.getWindowHandle();

Since you haven't provided reproducible code, I am just going to provide a simple example on how to switch tabs using Selenium 4 (and JUnit 5). If you are using Selenium 3, the way to do it is almost the same. I can provide an appropriate example if you require it.
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class ChromeTest {
#Test
void helloWorldTest () {
System.setProperty("webdriver.chrome.driver",
"F:/drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.google.com");
driver.manage().window().maximize();
String firstTabHandle = driver.getWindowHandle(); // save the first tab handle
// Open a new tab in the same browser session
WebDriver newTab = driver.switchTo().newWindow(WindowType.TAB);
newTab.get("https://www.msn.com/");
String secondTabHandle = driver.getWindowHandle(); // save the new tab handle
assertNotEquals(firstTabHandle, secondTabHandle); // not needed.. test the handles are different if you would like
sleep(driver);
driver.switchTo().window(firstTabHandle); // switch back to first tab
sleep(driver);
driver.switchTo().window(secondTabHandle); // switch back to new tab
sleep(driver);
driver.quit(); // end your browser session
}
private void sleep (WebDriver driver) {
new WebDriverWait(driver, Duration.ofSeconds(3))
.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//body")));
}
}
Can a web driver gain access to a window controlled by another web driver?
To my knowledge, the only way to do this is by using a driver created from the same session. You cannot start two independent sessions and hand off control to the other driver (to the best of my knowledge).
When invoking driver.switchTo().window(String windowHandle), a web driver is returned that has focus on the newly created window. HOWEVER, this is the same instance as the "driver" used to call switchTo().window(). Therefore, whether you used the returned driver or the original driver is immaterial, since they the same. Honestly, I don't know why this method returns an object at all. That said, when I ran this test using the returned driver, the test was more stable. When I used the same original instance, it tended to fail more for NoSuchElement during the second iteration. I know this could be fixed with the appropriate WebDriverWait, but I found this interesting.
To simulate the fact that this driver can interact with either window, I created the test below. The test passes three inputs to iterate over, and uses these strings to search on both Yahoo (original window) and Google (new window); all of which is done with the second (new) driver. This course of action is not necessary. Of course, each driver can interact with whichever window they created. However, in order to interact with a page, it needs to contain focus.
What does this mean related to using proxies? I do not know. All I know is that
A browser session can be interacted with by one and only one driver
Proxies (along with other options) are set before the session starts and cannot be changed after the session has begun.
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.time.Duration;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class ChromeTest {
private static WebDriver driver;
#BeforeAll
static void setup () {
System.setProperty("webdriver.chrome.driver",
"F:/drivers/chromedriver.exe");
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}
#AfterAll
static void teardown () {
if (driver != null) {
driver.quit();
}
}
#ParameterizedTest
#ValueSource(strings = {"dog", "cat", "birds"})
void simulateCodeTest (String input) {
driver.get("https://www.yahoo.com");
driver.manage().window().maximize();
String originalWindow = driver.getWindowHandle();
WebDriver newWindowDriver = driver.switchTo().newWindow(WindowType.WINDOW);
newWindowDriver.get("https://www.google.com");
String newWindowHandle = newWindowDriver.getWindowHandle();
newWindowDriver.switchTo().window(originalWindow);
assertTrue(originalWindow.equals(newWindowDriver.getWindowHandle()));
newWindowDriver.switchTo().window(newWindowHandle);
WebElement searchField = new WebDriverWait(newWindowDriver,
Duration.ofSeconds(5), Duration.ofMillis(10))
.until(ExpectedConditions
.elementToBeClickable(By.xpath("//input[#title='Search']")));
new Actions(newWindowDriver).sendKeys(searchField, input)
.sendKeys(Keys.ENTER).perform();
newWindowDriver.switchTo().window(originalWindow);
searchField = new WebDriverWait(newWindowDriver, Duration.ofSeconds(5),
Duration.ofMillis(10))
.until(ExpectedConditions
.elementToBeClickable(By.xpath("//input[#name='p']")));
new Actions(newWindowDriver).sendKeys(searchField, input)
.sendKeys(Keys.ENTER).perform();
WebElement searchButton =
newWindowDriver.findElement(By.xpath("//button[#type='submit']"));
searchButton.click();
}
}

Related

Getting NoSuchElementException while trying Datepicker in jquery

Tring to click on the input box, with script able to open the URL-https://jqueryui.com/datepicker/.In locator the id is available still getting No element foun.
Tried with thread.sleep as well
when i am running the script getting exception
package SeleniumWebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class HandlingCalender {
public static void main(String[] args) throws InterruptedException {
WebDriver driver =new ChromeDriver();
driver.get("https://jqueryui.com/datepicker/");
//driver.manage().window().maximize();
Thread.sleep(1000);
driver.findElement(By.id("datepicker")).click();
Element you trying to access is inside an iframe.
So, to access it you need first to switch into that iframe, as following:
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.class("demo-frame")));
wait.until(ExpectedConditions.elementToBeClickable(By.id("datepicker"))).click();

Can I make the WebDrivers as global variables in Java

I want to create a class where I set all the common actions of the WebDrivers such as: waitExplicit, findElement, click. But if I create a method then I have to create the WebDriver and WebDriverWait over and over on each method of the class, I already tried having a class for the Drivers, but when I call the methods, they just create instances over and over, so multiple windows open, I tried this way, but still cannot get to it:
public class AutomationActions{
static LoadProperties prop = new LoadProperties(); //This class has the System.setProperty for the driver
prop.getSysProp(); //***This is the issue, how can I solve this?****
WebDriver driver = new ChromeDriver(); //this will not work without the one above working
WebDriverWait wait = new WebDriverWait(driver, 30);//this will not work without the one above working
public void waitForPageToLoad() throws Exception {
ExpectedCondition<Boolean> pageLoadCondition = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
// WebDriverWait wait = new WebDriverWait(driver, 30); // I want to avoid having to set this in every method
wait.until(pageLoadCondition); //this is supposed to replace the line of code above
}
I don't really work on Java much any more, I've written our framework in C# but I put together some quick classes in Java to show you how I set things up. I use page object model and I recommend you do too so I've written this example using page object model. I've written a simple test that uses Dave Haeffner's (one of the Selenium contributors) demo site, http://the-internet.herokuapp.com.
The basic concepts are:
There is a class BaseTest that holds things that correspond to tests, e.g. setting up the driver at the start of the test, quitting the driver at the end of the test, etc. All of your tests will inherit from BaseTest
There is a class BasePage that holds things that correspond to generic methods for finding elements, clicking on elements, etc. Each of your tests inherit from BasePage. (This is what I think the main part of your question is asking about).
To follow the page object model, each page (or part of a page) is its own class and holds all locators and actions done on that page. For example, a simple login page would have the locators for username, password, and the login button. It would also hold a method Login() that takes a String username and a String password, enters those in the appropriate fields and clicks the Login button.
The final class of this example is a sample test aptly named SampleTest.
You shouldn't have any FindElements() or related calls in your tests, all those should be in the appropriate page object.
This is using TestNG as the unit test library. Use it or JUnit, your preference but if you use JUnit, you will need to change the asserts and the annotations.
Under 'src', I create a folder for page objects, 'PageObjects', and a folder for tests, 'Tests'. Here's what the files look like on disk.
\src
\PageObjects
BasePage.java
DropdownListPage.java
\Tests
BaseTest.java
SampleTest.java
BasePage.java
package PageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class BasePage
{
private WebDriver driver;
private final int shortWait = 10;
public BasePage(WebDriver _driver)
{
driver = _driver;
}
public void ClickElement(By locator)
{
new WebDriverWait(driver, shortWait).until(ExpectedConditions.elementToBeClickable(locator)).click();
}
public WebElement FindElement(By locator)
{
return new WebDriverWait(driver, shortWait).until(ExpectedConditions.presenceOfElementLocated(locator));
}
// add more methods
}
DropdownListPage.java
package PageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.Select;
public class DropdownListPage extends BasePage
{
private final By dropdownListLocator = By.id("dropdown");
public DropdownListPage(WebDriver _driver)
{
super(_driver);
}
public String GetSelectedOption()
{
return new Select(FindElement(dropdownListLocator)).getFirstSelectedOption().getText();
}
public void SelectOptionByIndex(int index)
{
new Select(FindElement(dropdownListLocator)).selectByIndex(index);
}
}
BaseTest.java
package Tests;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
public class BaseTest
{
public WebDriver driver;
public WebDriver GetChromeDriver()
{
System.setProperty("webdriver.chrome.driver", "C:\\Path\\To\\Chrome\\Driver\\chromedriver.exe");
return new ChromeDriver();
}
#BeforeTest
public void Setup()
{
driver = GetChromeDriver();
driver.manage().window().maximize();
driver.get("http://the-internet.herokuapp.com/dropdown");
}
#AfterTest
public void Teardown()
{
driver.close();
}
}
SampleTest.java
package Tests;
import org.testng.Assert;
import org.testng.annotations.Test;
import PageObjects.DropdownListPage;
public class SampleTest extends BaseTest
{
#Test
public void SampleTestCase()
{
DropdownListPage dropdownListPage = new DropdownListPage(driver);
dropdownListPage.SelectOptionByIndex(1);
Assert.assertEquals(dropdownListPage.GetSelectedOption(), "Option 1", "Verify first option was selected");
}
}
You will need to create a project that contains Selenium for Java and TestNG. Download them and put them on your build path. Create the folder structure as described above and create each of these classes and copy/paste the contents into them. Now all you need to do is run SampleTest as a TestNG Test and it should go.
The test creates a new Chromedriver instance, navigates to the sample page, selects the first option in the dropdown, asserts that the dropdown text is correct, and then quits the driver.
That should get you started. There's a lot of info crammed into the above wall of text, let me know if you have some questions.

Hover over dropdown menu in Amazon

I just want to hover over the "Departments" drop-down list on the Amazon website. The code looks alright but the list is not showing. It's the Department drop-down list I am trying to show
Here's my code
driver = new ChromeDriver();
driver.get("https://www.amazon.com");
Actions actions = new Actions(driver);
WebElement ele = driver.findElement(By.xpath("//span[#class='nav-line-2']"));
Thread.sleep(300);
actions.moveToElement(ele);
actions.perform();
actions.perform();
Looks like the xpath is not unique and with the same locator, locating 6 elements in the page. When we have more than one element with same locator, selenium go for first element. In your case, unfortunately 'Departments' is not the first element with that locator.
Change your xpath to below: [Tested & worked]
//span[#class='nav-line-2' and contains(.,'Departments')]
To Mouse Hover over the element with text as Departments you need to induce WebDriverWait for the desired element to be visible and use moveToElement() method in conjunction with perform() method and you can use the following solution:
Code Block:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class amazon_com_Departments {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
WebDriver driver = new ChromeDriver(options);
driver.get("https://www.amazon.com");
WebElement department = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//a[#id='nav-link-shopall' and normalize-space()='Departments']")));
new Actions(driver).moveToElement(department).perform();
}
}
Browser Snapshot:

Not able to close instances of different browser using driver.quit

I have opened different browser instances and at the end i would like to close all the instances but when i use driver.close() or driver.quit() it is only closing the last instance of the browser. Please help.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
public class showClose {
static WebDriver driver;
public showClose(WebDriver driver){
this.driver=driver;
}
public static void main(String[] args) {
showClose sc = new showClose(driver);
sc.IE("http://www.msn.com");
sc.Firefox("http://seleniumhq.org");
sc.Chrome("http://google.com");
driver.quit();
}
//Internet Explorer driver
public void IE(String URL){
//Set the driver property for IE
System.setProperty("webdriver.ie.driver", System.getProperty("user.dir")+"\\IEDriverServer.exe");
DesiredCapabilities ieCapabilities = DesiredCapabilities.internetExplorer();
ieCapabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
//Create object of Internet explorer driver
driver = new InternetExplorerDriver(ieCapabilities);
driver.get(URL);
}
//Firefox driver
public void Firefox(String URL){
driver = new FirefoxDriver();
driver.get(URL);
}
//Chrome driver
public void Chrome(String URL){
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\chromedriver.exe");
driver = new ChromeDriver();
driver.get(URL);
}
}
In every call of „sc.IE“, „sc.Firefox“ or „sc.Chrome“ you are overwriting the instance variable “driver”.
So the only driver that is closed by your call “driver.quit” is the last one.
If you want to close the browser after visiting the URL you would either have to do a “driver.quit” in before each call to „sc.IE“, „sc.Firefox“ or „sc.Chrome“ or manage a list of WebDrivers and close all of them.
For example you could do something like this:
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
public class ShowClose {
private List<WebDriver> drivers;
public ShowClose(){
this.drivers = new ArrayList<WebDriver>();
}
public static void main(String[] args) {
ShowClose sc = new ShowClose();
sc.IE("http://www.msn.com");
sc.Firefox("http://seleniumhq.org");
sc.Chrome("http://google.com");
sc.CloseAll();
}
public void CloseAll() {
for(WebDriver d : drivers) {
d.quit();
}
}
//Internet Explorer driver
public void IE(String URL){
//Set the driver property for IE
System.setProperty("webdriver.ie.driver", System.getProperty("user.dir")+"\\IEDriverServer.exe");
DesiredCapabilities ieCapabilities = DesiredCapabilities.internetExplorer();
ieCapabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
//Create object of Internet explorer driver
WebDriver driver = new InternetExplorerDriver(ieCapabilities);
driver.get(URL);
this.drivers.add(driver);
}
//Firefox driver
public void Firefox(String URL){
WebDriver driver = new FirefoxDriver();
driver.get(URL);
this.drivers.add(driver);
}
//Chrome driver
public void Chrome(String URL){
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get(URL);
this.drivers.add(driver);
}
}
Step1:
In Main Class declare 'List list' Interface and declare it as 'Static'
public static List<WebDriver> drivers;
Reason for Using List: It represents an ordered list of objects, meaning you can access the elements of a List in a specific order, and by an index too. You can also add the same element more than once to a List.
Step2:
Now Create a Constructor in which we will point to out current driver from the Stored List of Drivers. (I assume my class name as Test)
public Test()
{
this.drivers = new ArrayList<WebDriver>();
}
Step3:
Add a WebDriver Instance to out ArrayList for drivers in all methods of IE, Firefox and Chrome.
this.drivers.add(driver);
Step4: In main class copy all the instances of stored drivers to an object and use that object to close all opened instances.
for(WebDriver d : drivers)
{
d.quit();
}
For one thing: driver.quit() should be used if you want to close all windows. driver.close() is for a single window.
Perhaps it has something to do with the browser windows throwing an alert when they attempt to close?
See this other topic on StackOverflow for a solution to that problem

Selenium testcase execution speed issues

I have a issue with selenium where i am able to pass the testcase, but the issue is the execution of the testcase is very quick. Is there any way or attribute through which i can control the speed of the execution. I have been facing this problem big time. Any help will be greatly appreciated.
Below is my script for reference.
package test.selenium;
import java.util.concurrent.TimeoutException;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class test{
WebDriver driver;
public TrafficGroupUpdateTestNG() {
}
/**
* #throws java.lang.Exception
*/
#BeforeTest
public void setUp() throws Exception {
// Use Internet Explorer and set driver;
System.setProperty("webdriver.ie.driver",
"D:\\IBM\\Selenium\\IEDriverServer.exe");
driver = new InternetExplorerDriver();
// And now use this to visit URL
driver.get("URL Of JSP");
}
/**
* #throws java.lang.Exception
*/
#AfterTest
public void tearDown() throws Exception {
driver.close();
}
#Test
public final void test() {
final WebElement formElement = driver.findElement(By.id("search"));
final Select drelement = new Select(drelement.findElement(By.id("my_input")));
drelement.selectByIndex(0);
final WebElement submit = driver.findElement(By.id("Submit"));
submit.click();
}
}
It sounds like elements from AJAX calls are not visible or ready when document.ready status is updated. Working with my webdevs, I had them add a waiting class while they loaded things and remove it when they're done.
As a result, I was able to create this "WaitForPageLoad" method that waits until AJAX is finished. It's in C# but simple enough to translate into Java.
I used
Thread.sleep(2000);
A convinient way for making the page wait.
There are many ways you can control speed of the execution..
Implicity wait
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
by providing this imlicity wait, webdriver waits until 20 seconds before it returns object not found
explicit wait
WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
This will wait explicitly for given element..

Categories