Create Selenium Webdriver once and use in Cucumber's all steps - selenium

I've experience in Back-End automation testing, but I'm new to Front-End.
I've created BDD format tests for a website and now I want to automate it.
I decided to use Selenium + cucumber using Maven for desktop versions of website.
Now let's start:
For example my feature file looks something like this:
Feature: User change password page
Scenario: User doesn't provide passwords
Given user is logged in
And user is on change password page
When user clicks SAVE button
Then website should notify that password fields are mandatory
Scenario: User types wrong current password
Given user is logged in
And user is on change password page
When user provides invalid current password
And user clicks on save button
Then website should notify user that current password is invalid
At first I thought it would be good that I log in the system only for first scenario. (in this example in second scenario I already would be logged in).
But as I saw it's not good approach. So I open and close browser for each scenario using the code:
#Before
public void beforeScenario(){
driver.get("https://example.com");
}
#after
public void afterScenario(){
driver.close();
}
That's OK for me. But I don't want to create WebDriver for each scenario and I don't want to initialize my POM objects for each scenario.
Now my Before method looks like it:
WebDriver driver;
HomePage home;
LoginPage login;
RegistrationPage reg;
#Before
public void beforeScenario(){
driver = new ChromeDriver();
home = new HomePage();
login = new LoginPage();
reg = new RegistrationPage();
}
I want to initialize these objects before steps are run and use them in every step.
I research and found out that cucumber-JVM doesn't support #beforeAll hook.
Also I don't want to do some manipulation like:
if( firstTime) {
//initialise everythin
firstTime = false
} else {
//do nothing
}
How can I achieve that? Where can I initialize everything I want before my tests start?

Related

Automating gmail login [During oAuth] gets blocked with user verification

This code works to login to gmail
public void login(User user) {
WebDriverWait wait = new WebDriverWait(driver, 60);
WebElement emailTextBox = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("identifierId")));
emailTextBox.sendKeys(user.email);
WebElement nextButton = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.xpath("//span[contains(text(), 'Next')]")));
nextButton.click();
WebElement passwordTextBox = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[#type='password']")));
passwordTextBox.sendKeys(user.password);
nextButton = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.xpath("//span[contains(text(), 'Next')]")));
nextButton.click();
}
Problem
We have a web application under test where users can login with google (oAuth2), however gmail traps automation script with a user verification (reset password or captcha or phone number).
Q:
Is there any way to avoid gmail user verification ?
(I am not asking to solve google verification challenge, in normal browser run by user manually this verification challenge doesn't get triggered (most of times), but with selenium it sometimes happens and fails my tests.)
Update 19.08.2018
This is a dead end, bypassing google verification is not trivial, upon searching more I found that service virtualization is the correct way to solve this issue, possibly Hoverfly.
Using cookies solved my issue
public HomePage googleAutoLogin(String cookieKey, String cookieValue) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.HOUR, 1);
Date afterOneHour = cal.getTime();
driver.manage().deleteAllCookies();
Cookie cookie = new Cookie.Builder(cookieKey, cookieValue)
.domain("qreflect.com")
.path("/")
.expiresOn(afterOneHour)
.isHttpOnly(true)
.build();
driver.manage().addCookie(cookie);
driver.navigate().refresh();
logger.log(Level.INFO, "Finished adding cookie");
return this;
}
you have to login manually once then inspect to get cookies related to your app session, store them somewhere and pass the key/value pair to this method to get logged in.

How to manage login window after session expire in Selenium

I am testing Polarion application and after testing for couple of minutes session expires and login window pops up.
Session is expiring randomly hence I don't have any fixed point to stop and resume. My test case also starts failing as expected button is on the main window which become inactive after login window comes up.
My question is does Selenium provide any way to handle this scenario?
Using Selenium in Java/TestNg on Chrome.
You can try to use retryAnalyzer of TestNG
import org.testng.Assert;
import org.testng.annotations.Test;
public class Test001 {
#Test(retryAnalyzer = Tests.RetryAnalyzer.class)
public void Test1()
{
Assert.assertEquals(false, true);
}
#Test
public void Test2()
{
Assert.assertEquals(false, true);
}
}
The details you can find in below link :-
http://toolsqa.com/selenium-webdriver/retry-failed-tests-testng/
Just write a function in retry which check if the pop-up appear then it call your login function.

SafarDriver Selenium Page title is incorrect after loading new page

I have a Selenium 2 test that uses a login form and then asserts that the login has succeeded by verifying the page title has changed.
The test is written in Java/JUnit, WebDriver and Fluent Selenium
fwd.title().within(secs(5)).shouldContain(partialTitle);
The tests work on Firefox and Chrome.
On Safari the page title is still the old login page title.
The screencast we have generated shows that the URL after a successful login has changed, but the title hasn't.
I think the SafariDriver is not waiting for the page load event to complete before the assertion.
I have the same issue!!!
My test fail because title is used for checking test "Step".
With Firefox and Chrome no problem; with Safari it's a problem!!!
I found this "hack" that work, but it's necessary to manually check the title after each "click":
def static void waitForPage(driver, String title) {
//Hack to make login working on Safari&IE
(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return d.getTitle().startsWith(title);
}
});
}
I use GEB + SPOCK and with safari driver there is a "know issue" about implicit/explicit wait (ref. https://code.google.com/p/selenium/issues/detail?id=5860).
So, a nice workaround for make test runnable on Safari browser is to wait for page title:
static at = {
waitFor { title == "Homepage" }
}
This will force the driver to wait until title change (the timeout is configurable).

Handling Browser Authentication using Selenium

Does anyone know about handling Browser Authentication using Selenium or any other tool during automation?
EDIT in 2015:
This answer is outdated. WebDriver nowadays supports authentication! See How to handle authentication popup with Selenium WebDriver using Java
Original answer:
This is not handled very well by Selenium.
You can try using http://username:password#example.com/yourpage
instead of just http://example.com/yourpage
However, as far as I know, Firefox will still pop up a browser dialog requesting a confirmation.
You can try Robot if you're using Java (or any similar tool like AutoIt).
You could use driver.manage().addCookie() if you're using WebDriver.
Or a custom FirefoxProfile that has already passed the authentication once.
I spent days on this - literally.
Trying to get past browser level authentication within my company network to hit an application.
The solution was to use the 'unsername:password#' component within the URL, BUT to add a forward slash at the end of the login URL.
So total login URL looks like this (note the '/' after yourpage):
http://username:password#example.com/yourpage/
Works with Watir, Capybara and Selenium Webdriver.
Everything I have read on the Web didn't help me. So before making a request, like this:
driver.get(url);
you have to run a new thread like this:
RunScript runScript = new RunScript();
runScript.start();
In this case you are free to input login and password on another thread of follwing class
public class RunScript extends Thread {
#Override
public void run() {
try {
File file = new File("D:\\jacob-1.18-x86.dll");
System.setProperty(LibraryLoader.JACOB_DLL_PATH, file.getAbsolutePath());
AutoItX autoIt = new AutoItX();
Thread.sleep(2000);
autoIt.winActivate("yourWindowName", "");
autoIt.winWaitActive("yourWindowName");
if (autoIt.winExists("yourWindowName")) {
autoIt.send("username{TAB}", false);
autoIt.send("password{Enter}", false);
}
}
} catch (InterruptedException ex) {
//
}
}
}
All the hacks via auto-it, sikuli, etc. just wasting your time when you'll run it in your CI solution, using several browser types / OS / Version / Resolutions etc.
The way to do it correctly is to identify the authentication actual method and perform a login using Rest protocol for instance.
I used it to get the JSESIONID cookie and insert it to the selenium driver.
hint on that: go to a non-exiting url of the domian first, then set the cookie, then go to the required url - you are logged-in.
use: rest client authentication to get the JSESSION ID
and With this information:
browser().navigate(foo.getUrl()+"non-exiting-url");
//the information got from the rest client login:
Cookie cookie = new Cookie(name, value, domain, path, expiry, isSecure, isHttpOnly);
try {
driver.manage().addCookie(cookie);
} catch (Exception e) {
System.out.println(e.toString());
}
browser().navigate(foo.getUrl());
you can use auto IT script to handle this problem
WinWaitActive("[CLASS:Chrome_WidgetWin_1]", "", time)
Send("user")
Send("{TAB}")
Send("pass")
Send("{ENTER}")
with Chrome 70 and other versions :
http://username:password#example.com/yourpage
You can use Java Robot class with Selenium 2 /Selenium WebDriver using Firefox
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:9990");
WebElement myDynamicElement = driver.findElement(By.id("app"));
Alert alert = driver.switchTo().alert();
try {
Robot robot = new Robot();
alert.sendKeys("username");
robot.keyPress(KeyEvent.VK_TAB);//go to password feild
robot.keyPress(KeyEvent.VK_P);
robot.keyPress(KeyEvent.VK_A);
robot.keyPress(KeyEvent.VK_S);
robot.keyPress(KeyEvent.VK_S);
robot.keyPress(KeyEvent.VK_ENTER);
} catch (AWTException e) {
e.printStackTrace();
}
}
Using Selenium with Robot
http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Robot.html

Selenium IDE: Verify broken link 404 not found?

Any one have any idea whether Selenium IDE able to verify any broken link in page??
Short answer: yes, but probably not the best idea.
Selenium might not be the best program to do this - especially if you use only Selenium IDE.
Multiple programs exist with the sole purpose of testing broken links (do a little search), hell, even the W3C has a webapp for that.
That said, you could take the output from Selenium IDE formatted to your favourite language, program a Selenium test case with more advanced Unit Testing classes, include a while loop which would check for the existence of more links, and visit them / check headers, if you really want to do this through Selenium.
In short, you can't (yet). See a more full writeup of the situation at: How do I ask Selenium IDE to check a HTTP Status Code (e.g. 2XX, 404, 500)
Basically the selenium maintainers decided this function did not belong in selenium because error codes are read by machines not humans.
This sounds like a job for a simple spider script, for example using the wget on Linux
--spider
When invoked with this option, Wget will behave as a Web spider,
which means that it will not download the pages, just check that
they are there. For example, you can use Wget to check your book‐
marks:
wget --spider --force-html -i bookmarks.html
This feature needs much more work for Wget to get close to the
functionality of real web spiders.
You can use 404 status code to verify using REST web services.
Use gson and apache jars to get it.
public class Testing{
public static void main(String[] args) {
try{
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.navigate().to("https://www.amazon.in/");
List<WebElement> links = driver.findElements(By.tagName("a"));
System.out.println("Number of links : " + links.size());
for(WebElement e : links) {
String linkText = e.getAttribute("href");
System.out.println("Link -->>" +linkText);
if(linkText!=null && !linkText.isEmpty()) {
HttpPost post = new HttpPost(linkText);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse res = client.execute(post);
String s = res.getStatusLine().toString();
if(s.contains("404")) {
System.out.println("Navigated");
//your code to handle logic
} else {
//your code to handle logic with other response code
}
}
}
} catch (Exception e) {
System.out.println(e.getStackTrace());
}
}
}