ElementClickInterceptedException on cucumber parallel AbstractTestNGCucumberTests - selenium-webdriver

I have parallel test setup in cucumber 6.9.1 using AbstractTestNGCucumberTests and then directing the test to a grid using RemoteWebDriver
#Override
#DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
}
and creating RemoteWebDriver like below
String hubURL = "http://192.168.1.7:65299/wd/hub";
System.setProperty("webdriver.gecko.driver", "/Users/../../geckodriver");
FirefoxProfile profile = new FirefoxProfile();
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(FirefoxDriver.PROFILE, profile);
capabilities.setPlatform(Platform.ANY);
FirefoxOptions options = new FirefoxOptions();
options.merge(capabilities);
return driver = new RemoteWebDriver(new URL(hubURL),options);
It opens two instances of firefox , and they overlap each other and I keep getting
org.openqa.selenium.ElementClickInterceptedException: Element <button class="btn btn-link pull-right" on one or the other instance of firefox .
I have tried several solutions mentioned in many questions but none of them seems to help in my scenario
I tried below solutions
global.wait.until(ExpectedConditions.visibilityOf(PageObjects.AddUser));
global.jsExecutor.executeScript("arguments[0].click();", PageObjects.AddUser);
PageObjects.AddUser.sendKeys(Keys.ENTER);
Actions builder = new Actions(global.driver);
Action clickElement = (Action) builder.click(PageObjects.AddUser);
clickElement.perform();
global.wait.until(ExpectedConditions.invisibilityOfElementLocated((By) PageObjects.allDom));
I am running test on FF 77.0 and Mac OS (catalina)
How do I resolve this?
EDIT. To include ThreadLocal change
public class FirefoxManager extends DriverManager{
private final ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<>();
#Override
protected RemoteWebDriver createDriver() throws MalformedURLException , IOException {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
System.out.println("hubport from sys prop var.."+System.getProperty("hub.port"));
String hubURL = "http://192.168.1.7:65299/wd/hub";
System.setProperty("webdriver.gecko.driver", "/Users/amit/Desktop/amit/projects/misc/geckodriver");
FirefoxProfile profile = new FirefoxProfile();
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(FirefoxDriver.PROFILE, profile);
capabilities.setPlatform(Platform.ANY);
FirefoxOptions options = new FirefoxOptions();
options.merge(capabilities);
driver.set(new RemoteWebDriver(new URL(hubURL),options));
return driver.get();
}

You will need to use ThreadLocal since WebDriver is not ThreadSafe.
copied code, but idea is same
protected ThreadLocal<WebDriver> wbdriver = new ThreadLocal<WebDriver>();
String url = "https://google.com";
wbdriver.set(new ChromeDriver(options));
wbdriver.get().manage().window().maximize();
wbdriver.get().get(url);

I achieved cucumber parallelism using courgette-jvm . It worked out of the box and run parallel test at scenario level
Simply inlclude similar runner class in cucumber. My tests are further using RemoteWebdriver to open multiple instances on selenium grid. Make sure grid is up and running and node is registered to the grid.
import courgette.api.CourgetteOptions;
import courgette.api.CourgetteRunLevel;
import courgette.api.CucumberOptions;
import courgette.api.testng.TestNGCourgette;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
#Test
#CourgetteOptions(
threads = 10,
runLevel = CourgetteRunLevel.SCENARIO,
rerunFailedScenarios = true,
rerunAttempts = 1,
showTestOutput = true,
reportTitle = "Courgette-JVM Example",
reportTargetDir = "build",
environmentInfo = "browser=chrome; git_branch=master",
cucumberOptions = #CucumberOptions(
features = "src/test/resources/com/test/",
glue = "com.test.stepdefs",
publish = true,
plugin = {
"pretty",
"json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html"}
))
class AcceptanceIT extends TestNGCourgette {
}
RemoteWebdriver config is
protected RemoteWebDriver createDriver() throws MalformedURLException , IOException {
Properties properties = new Properties();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String hubURL = "http://192.168.1.7:65299/wd/hub";
System.setProperty("webdriver.gecko.driver", "/Users/amit/Desktop/amit/projects/misc/geckodriver");
FirefoxProfile profile = new FirefoxProfile();
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(FirefoxDriver.PROFILE, profile);
capabilities.setPlatform(Platform.ANY);
FirefoxOptions options = new FirefoxOptions();
options.merge(capabilities);
driver.set(new RemoteWebDriver(new URL(hubURL),options));
return driver.get();
}

Related

Unable to capture browser network logs with BrowserStack local, BrowserMobProxy embedded mode and Selenium 3.x using java

Below is the dependencies in my maven pom.xml
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>3.14.0</version>
<groupId>net.lightbody.bmp</groupId>
<artifactId>[browsermob-core][1]</artifactId>
<version>2.1.5</version>
<groupId>com.browserstack</groupId>
<artifactId>[browserstack-local-java][1]</artifactId>
<version>1.0.3</version>
Below is the code which I'm using to initiate the BrowserMobProxy.
private static void browserMobSeleniumProxyStart() {
try {
proxy = new BrowserMobProxyServer();
proxy.setTrustAllServers(true);
proxy.chainedProxyAuthorization(
System.getProperty("proxy.user"), System.getProperty("proxy.pass"), AuthType.BASIC);
proxy.setChainedProxy(new InetSocketAddress(httpProxyHost, Integer.parseInt(httpProxyPort)));
// Enable HAR.
proxy.enableHarCaptureTypes(
EnumSet.of(
CaptureType.REQUEST_HEADERS,
CaptureType.REQUEST_CONTENT,
CaptureType.RESPONSE_CONTENT,
CaptureType.RESPONSE_HEADERS
)
);
proxy.start(browserLocalProxyPort);
localHostAddress = Inet4Address.getLocalHost().getHostAddress();
localHostPort = String.valueOf(proxy.getPort());
} catch (Exception e) {
proxy.stop();
e.printStackTrace();
}
Variables httpProxyHost and httpProxyPort are the corporateProxy IP and Port.
Below is the code to initiate the BrowserStack-local
private static void browserStackLocalStart() {
bsLocal = new Local();
bsLocalArgs = new HashMap<>();
bsLocalArgs.put("key", AUTOMATE_ACCESS_KEY);
// BrowserStack local executable.
bsLocalArgs.put("binarypath", format(BROWSERSTACK_PATH, "/src/test/resources/BrowserStackLocal"));
// Force to use local and Corp proxy.
bsLocalArgs.put("forcelocal", "true");
bsLocalArgs.put("forceproxy", "true");
// Set Corp Proxy and user crendentials.
bsLocalArgs.put("proxyHost", httpProxyHost);
bsLocalArgs.put("proxyPort", httpProxyPort);
bsLocalArgs.put("proxyUser", System.getProperty("proxy.user"));
bsLocalArgs.put("proxyPass", System.getProperty("proxy.password"));
// Set local Proxy to BrowserMobProxy host - localhost ip and port and set user credentials.
bsLocalArgs.put("localProxyHost", localHostAddress);
bsLocalArgs.put("localProxyPort", localHostPort);
bsLocalArgs.put("-localProxyUser", System.getProperty("proxy.user"));
bsLocalArgs.put("-localProxyPass", System.getProperty("proxy.password"));
seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
try {
if(bsLocal.isRunning()) bsLocal.stop(bsLocalArgs);
bsLocal.start(bsLocalArgs);
log.info(format("Browser Stack Local status: %s", bsLocal.isRunning()));
} catch (Exception e) {
log.warning("!!! Cannot start browserstack local !!!");
}
}
Below is method to initiate the driver on BrowserStack
private static void setDriverWithBrowserstackOptions() {
// Start BrowserMob proxy and browserstack-local.
browserMobSeleniumProxyStart();
browserStackLocalStart();
String jobName = System.getenv("JOB_BASE_NAME");
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("browserstack.local", "true");
caps.setCapability("browserstack.selenium_version", "3.14.0");
caps.setCapability("browserstack.debug","true");
caps.setCapability("browserstack.networkLogs","false");
caps.setCapability("acceptSslCerts", "true");
caps.setCapability("name", testName);
caps.setCapability("project", "SampleProj");
caps.setCapability("sessionName", "sessionName1");
caps.setCapability("localIdentifier", "Local Test");
caps.setCapability("build", "Local");
caps.setCapability("browserstack.maskCommands", "setValues, getValues, setCookies, getCookies");
caps.setCapability(CapabilityType.PROXY, seleniumProxy);
// Chrome Options.
ChromeOptions options = new ChromeOptions();
options.addArguments("--ignore-certificate-errors");
caps.merge(ChromeOptions.CAPABILITY, options);
URL url = null;
try {
url = new URL(URL);
} catch (MalformedURLException e) {
log.warning("Browserstack URL may be incorrect."+ URL);
}
// Initiate RemoteWebDriver instanc
WebDriver d = new RemoteWebDriver(url, caps);
// Create new HAR.
proxy.newHar();
try {
d.get("https://google.com");
Thread.sleep(10000);
// Fetch Har entries.
List<HarEntry> harEntries = proxy.getHar().getLog().getEntries();
for (HarEntry h : harEntries) {
System.out.println("---------------- HAR Request -----------------");
System.out.println(h.getRequest());
System.out.println("----------------------------------------------");
System.out.println("---------------- HAR Response -----------------");
System.out.println(h.getResponse());
System.out.println("----------------------------------------------");
}
} catch (Exception e) {
e.printStackTrace();
}
}
I tried with and without BrowserMobProxy setChainedProxy but had no luck to capture the HAR entries.
Any thoughts and comments are appreciated.
You just have to set the following capability to capture the network logs on BrowserStack:
caps.setCapability("browserstack.networkLogs","true");
Also, you can capture the contents of the requests made using browserstack.networkLogsOptions. More details on https://www.browserstack.com/automate/capabilities

Authentication Window Alert is working in IE11 but not working in Chrome v60

In my scenario, when I launch a URL, an authentication alert window opens up and I need to enter Username and Password from excel and on clicking on 'Log In' it'll show me the web homepage. I've implemented this using the below code snippet and it's working perfectly in IE11. But when I'm trying to run the same code in Chrome v60, it's not working. It's showing the authentication alert window but not performing any action on it. Screenshot attached. Can anyone suggest please.
Selenium WD version - 3.4.0
Code:
public static void loadApplicationURL(WebDriver driver) throws Exception
{
String SSPathl = null;
String URL = Generic_Functions.GetParameterFromInputSheet("URL");
try
{
driver.get(URL);
Thread.sleep(6000);
LoginApplication.isAlertPresent(driver);
}
}
public static boolean isAlertPresent(WebDriver driver) {
try {
driver.switchTo().alert();
UserAndPassword UP = new UserAndPassword(UserName,Password);
driver.switchTo().alert().authenticateUsing(UP);
Thread.sleep(8000);
return true;
}
catch (Exception e) {
return false;
}
}
For test browsers, have created a separate class. Find below the snippet used for IE and Chrome browsers.
For Chrome
System.setProperty("webdriver.chrome.driver",".\\Resources\\chromedriver.exe");
driver = new ChromeDriver()
In case of IE,
[System.setProperty("webdriver.ie.driver",".\\Resources\\IEDriverServer.exe");
DesiredCapabilities ieCapabilities = DesiredCapabilities.internetExplorer();
ieCapabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS,true);
ieCapabilities.setCapability("nativeEvents", true);
driver = new InternetExplorerDriver(ieCapabilities);][1]

Solr basic authentication without setting credentials for each request

Currently I am using SOLR basic authentication feature on my SOLR cloud using Solrj library. According to documentation and only way I found, the code looks like this -
SolrRequest<QueryResponse> req = new QueryRequest(solrQuery);
req.setBasicAuthCredentials("admin", "foobar");
QueryResponse rsp = req.process(solrClient, liveStreamCollection);
documentList = rsp.getResults();
I am wondering if there is a way to avoid setBasicAuthCredentials for each request and perform it only once per session on solrClient?
Edit
Above approach worked both for SolrClient and SolrCloudClient (both core and collection). To avoid passing basic credentials for each request, I tried to build and use a HttpClient like this.
AuthScope authScope = new AuthScope("192.168.x.x", 8983);
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("admin", "foobar");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(authScope, creds);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.addInterceptorFirst(new PreemptiveAuthInterceptor());
builder.setDefaultCredentialsProvider(credsProvider);
CloseableHttpClient httpClient = builder.build();
solrClient = new HttpSolrClient("http://192.168.x.x:8983/solr/", httpClient);
And the PreemptiveAuthInterceptor class:
static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
#Override
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it preemptively
if (authState.getAuthScheme() == null) {
CredentialsProvider credsProvider = (CredentialsProvider)
context.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
Credentials creds = credsProvider.getCredentials(authScope);
if(creds == null){
}
authState.update(new BasicScheme(), creds);
}
}
}
This worked for a single machine Solr core but I don't know how to use this with Solr cloud(passing Zookeeper hosts etc). Any idea?
Thanks in advance!

Selenium web driver scripts for Authenticated view

I am new for Automation testing using selenium web driver for chrome.I want to test authenticated view from selenium web driver ,so i wrote code
public void WriteReviewAfterLogin()
{string BaseUrl = "http://vps65937-6.lcnservers.com/10300/profile/login.php";
var driver = new ChromeDriver();
driver.Navigate().GoToUrl(BaseUrl);
var loginBox = driver.FindElement(By.Id("username"));
loginBox.SendKeys("govinda.silverlight#gmail.com");
var pwBox = driver.FindElement(By.Id("password"));
pwBox.SendKeys("12345");
var signinBtn = driver.FindElement(By.CssSelector("[class='btn btn-default signin']"));
signinBtn.Click();
const string url = "http://vps65937-6.lcnservers.com/10300/company-reviews/sks-security-53beee89163ce.html";
driver.Navigate().GoToUrl(url);
((IJavaScriptExecutor)driver).ExecuteScript("window.resizeTo(1024, 768);");
var reviewTitle = driver.FindElement(By.Id("review_title"));
reviewTitle.SendKeys("thi is testing titile");
var review = driver.FindElement(By.Id("review"));
review.SendKeys("this is testing");
var signinBtns = driver.FindElement(By.CssSelector("[class='submitReview']"));
signinBtns.Click();
driver.Navigate().GoToUrl("http://vps65937-6.lcnservers.com/10300/");
}
invoked as
private static void Main(string[] args)
{
SeliniumChrome loginSeliniumChrome=new SeliniumChrome();
loginSeliniumChrome.WriteReviewAfterLogin();
}
When this code runs the login view is authenticated and redirected to another url,the login state is lost how to set in log in state in that case.
I don't find any use of below mentioned lines in your code. Better to remove these lines because once you will login you will be redirected to below mentioned url.
const string url = "http://vps65937-6.lcnservers.com/10300/company-reviews/sks-security-53beee89163ce.html";
driver.Navigate().GoToUrl(url);

Changing Download Location in Google Chrome using Selenium Webdriver

I have tried the following code:
ChromeOptions profile=new ChromeOptions();
profile.addArguments("disable-popup-blocking", "true");
profile.addArguments("download.default_directory","D:\\WORKSPACE\\SeConnect\\Downloads\\");
profile.addArguments("download.directory_upgrade", "true");
profile.addArguments("download.prompt_for_download", "false");
driver = new ChromeDriver(profile);
But it is not setting the path. It is using default path.
driver.get("chrome://settings/advanced");
JavascriptExecutor js = (JavascriptExecutor) driver;
String prefId = "download.default_directory";
File tempDir=new File(System.getProperty("user.dir")+"\\Downloads\\");
if (driver.findElements(By.xpath(String.format(".//input[#pref='%s']", prefId))).size() == 0) {
driver.get("chrome://settings-frame");
driver.findElement(By.xpath(".//button[#id='advanced-settings-expander']")).click();
}
String tmpDirEscapedPath = tempDir.getCanonicalPath().replace("\\", "\\\\");
js.executeScript(String.format("Preferences.setStringPref('%s', '%s', true)", prefId,
tmpDirEscapedPath));

Resources