How to test sublinks on a page in Selenium - java

How to test sub links on a page in Selenium. I have an events page. Then from that events page i collect all the different events links. Then i want to recursively run tests on those links.
I have attached an image of the page. The green text are all links. So i collected the href values of all these. After that I have some tests to run on those pages. I have a test class called EventsPageTest for the main page. The test class for the sub pages is called SingleEventsPageTest. How do I transfer the href values from the main class to the other class. Or is there any other method I need to follow.
I searched the internet so much but was of no use.
Any help would be appreciated.
Thanks
EventsPageTest
package test;
import pages.EventsPageObjects;
#Listeners(listeners.TestListener.class)
public class EventsPageTest {
private static ExtentHtmlReporter htmlReporter;
private static ExtentReports extent;
private static ExtentTest test;
static WebDriver driver = null;
private static EventsPageObjects eventsPage;
public MutableCapabilities capabilities;
static Set<String> eventsLinks = new HashSet<String>();
String url;
#BeforeSuite
public void setUp() {
// initialize the HtmlReporter
htmlReporter = new ExtentHtmlReporter("extentReportsEventsPage.html");
// initialize ExtentReports and attach the HtmlReporter
extent = new ExtentReports();
// attach only HtmlReporter
extent.attachReporter(htmlReporter);
}
#BeforeTest
public void setUpTest() throws IOException{
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
url = "abc.com";
driver.get(url);
System.out.println("Inside setUpTest");
//Create eventsPageObject
eventsPage = new EventsPageObjects(driver);
}
#Test(alwaysRun=true)
public void collectEventsLinks() throws InterruptedException, IOException {
test = extent.createTest("Collect all Events Links on a page","Test to Collect all Events Links on a page ");
test.log(Status.INFO, "Starting Test Case");
List<WebElement> links = driver.findElements(By.tagName("a"));
for (int i = 0; i<links.size(); i++) {
if(Pattern.matches("^https://"+ TestRunner.url +"/events/[^/]+[^\\s]$", links.get(i).getAttribute("href")))
eventsLinks.add((links.get(i).getAttribute("href")));
}
test.log(Status.INFO, "Finished Test Case");
}
#AfterTest(alwaysRun = true)
public void tearDownTest() {
//close browser
driver.close();
driver.quit();
}
#DataProvider(name="getURLS")
#AfterTest
public Object[] getURLS() {
System.out.println("Inside get Urls");
System.out.println("getURLS : " + eventsLinks.size());
Object[] objArray = eventsLinks.toArray();
System.out.println(eventsLinks.size());
return objArray;
}
#AfterSuite
public void tearDown() {
extent.flush();
}
}
SingleEventsPageTest
package test;
#Listeners(listeners.TestListener.class)
public class SingleEventsPageTest{
private static ExtentHtmlReporter htmlReporter;
private static ExtentReports extent;
private static ExtentTest test;
static WebDriver driver;
private static SingleEventsPageObjects singleEventsPage;
static List<Object> eventsURLS = new ArrayList<Object>();
#BeforeSuite
public void setUp() {
PropertiesFile.getProperties();
// initialize the HtmlReporter
htmlReporter = new ExtentHtmlReporter("extentReportsSingleEventsPage.html");
// initialize ExtentReports and attach the HtmlReporter
extent = new ExtentReports();
// attach only HtmlReporter
extent.attachReporter(htmlReporter);
}
#BeforeTest
public void setUpTest() throws IOException{
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
//Create eventsPageObject
singleEventsPage = new SingleEventsPageObjects(driver);
}
#Test(dataProvider="getURLS",dataProviderClass=EventsPageTest.class,alwaysRun=true)
public void findIfEventsTitleExists(String url) throws InterruptedException, IOException {
driver.get(url);
System.out.println("Inside findIfEventsTitleExists : " + driver.getCurrentUrl());
test = extent.createTest("Events Title Exists","Test to verify if the Events Title exists after opening the page");
test.log(Status.INFO, "Starting Test Case");
test.log(Status.INFO, "Checking If the URL points to the events page else navigate to that");
Assert.assertEquals(true,singleEventsPage.findIfEventsTitleExists());
test.log(Status.INFO, "Finished Test Case");
}
#Test(dataProvider="getURLS",dataProviderClass=EventsPageTest.class,alwaysRun=true)
public void verifyIfEventDescriptionExists(String url) throws InterruptedException, IOException {
driver.get(url);
test = extent.createTest("Events description Exists","Test to verify if the Events description exists");
test.log(Status.INFO, "Starting Test Case");
test.log(Status.INFO, "Checking If the URL points to the events page else navigate to that");
if(singleEventsPage.getCurrentUrl() != url)
singleEventsPage.navigateTo(url);
test.log(Status.INFO, "Checking If the Page Sub Title Exists");
Assert.assertEquals(true,singleEventsPage.checkIfElementExists(singleEventsPage.getEventDesc()));
test.log(Status.INFO, "Finished Test Case");
}
#AfterTest(alwaysRun = true)
public void tearDownTest() {
//close browser
driver.close();
driver.quit();
}
#AfterSuite
public void tearDown() {
extent.flush();
}
}

It would be good if you could post your code here. You can try to store them in one class as List, then pass them to another.
I am not sure how your framework is working now. I am thinking of something like this. Please post more code here.
class EventsPageTest {
public List<T> getAllHref() {
// return List
}
}
class SingleEventsPage {
#Test
public void someTest () {
EventsPageTest eventsPageTest = new EventsPageTest();
List<T> hrefs = eventsPageTest.getAllHref();
}
}
Hope this helps

Related

java.lang.NullPointerException : org.openqa.selenium.OutputType)" because "screenShot" is null

I have a maven project that runs testng and cucumber. If I run the testng and my test fails my program takes screenshots and creates a report. However if I run my cucumber tests and it fails, I get java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.TakesScreenshot.getScreenshotAs(org.openqa.selenium.OutputType)" because "screenShot" is null.
Both the testng and cucumber references the same listeners and base class.
My listeners class (on failure):
#Override
public void onTestFailure(ITestResult result) {
ExtentThred.get().fail(result.getThrowable());
WebDriver driver = null;
String testMethodName = result.getMethod().getMethodName();
try {
driver = (WebDriver)result.getTestClass().getRealClass().getDeclaredField("driver").get(result.getInstance());
}
catch (Exception e)
{
}
try {
ExtentThred.get().addScreenCaptureFromPath(getScreenshotPath(testMethodName, driver),result.getMethod().getMethodName());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
My base class:
public class Base {
public static WebDriver driver;
public Properties prop;
public WebDriver initializeDriver() throws IOException {
prop = new Properties();
FileInputStream file = new FileInputStream(System.getProperty("user.dir") + "\\src\\main\\java\\resources\\data.properties");
prop.load(file);
String browserName = prop.getProperty("browser");
if (browserName.contains("chrome")) {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\chromedriver.exe");
ChromeOptions chromeOptions = new ChromeOptions();
if (browserName.contains("headless")){
chromeOptions.addArguments("headless");
}
driver = new ChromeDriver(chromeOptions);
}
else if (browserName == "firefox") {
}
else if (browserName == "edge") {
}
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
return driver;
}
public String getScreenshotPath(String testCaseName, WebDriver driver) throws IOException
{
TakesScreenshot screenShot = (TakesScreenshot) driver;
File source = screenShot.getScreenshotAs(OutputType.FILE);
String destinationFile = System.getProperty("user.dir")+"\\reports\\"+ testCaseName +".png";
FileUtils.copyFile(source, new File(destinationFile));
return destinationFile;
}
}
My testng class that works fine:
public class ValidateLoggedIn extends Base {
public WebDriver driver;
#BeforeTest
public void initialize() throws IOException {
driver = initializeDriver();
}
#Test(dataProvider = "getData")
public void HomePageTitle(String mobileNumber, String password, String access) throws IOException {
driver.get(prop.getProperty("cars"));
MainPage mainPage = new MainPage(driver);
mainPage.getLogin().click();
mainPage.getMobileNumber().sendKeys(mobileNumber);
mainPage.getPassword().sendKeys(password);
mainPage.getLoginButton().click();
if (access == "Allowed User") {
LoggedInPage loggedInPage = new LoggedInPage(driver);
Assert.assertTrue(loggedInPage.getLogOutButton().isDisplayed());
loggedInPage.getLogOutButton().click();
}
else {
mainPage.getLoginButton();
Assert.assertTrue(mainPage.getLoginButton().isDisplayed());
}
}
#DataProvider
public Object[][] getData() {
Object[][] userData = new Object[1][3];
userData[0][0] = "0720127992";
userData[0][1] = "Dr0medar!s";
userData[0][2] = "Allowed User";
return userData;
}
#AfterTest
public void teardown()
{
driver.close();
}
}
My step definition for my cucumber:
public class StepDefinition extends Base {
public WebDriver driver;
#Given("^Initilize the browser with Chrome$")
public void initilize_the_browser_with_chrome() throws Throwable {
driver = initializeDriver();
}
#When("^User enters (.+) and (.+) and logs in$")
public void user_enters_and_and_logs_in(String mobilenumber, String password) throws Throwable {
MainPage mainPage = new MainPage(driver);
mainPage.getLogin().click();
mainPage.getMobileNumber().sendKeys(mobilenumber);
mainPage.getPassword().sendKeys(password);
mainPage.getLoginButton().click();
}
#Then("^verify if user is successfully logged in$")
public void verify_if_user_is_successfully_logged_in() throws Throwable {
LoggedInPage loggedInPage = new LoggedInPage(driver);
Assert.assertTrue(loggedInPage.getLogOutButton().isDisplayed());
loggedInPage.getLogOutButton().click();
}
#And("^Navigate to \"([^\"]*)\" site$")
public void navigate_to_something_site(String strArg1) throws Throwable {
driver.get(strArg1);
}
#And("^Close Browser$")
public void close_browser() throws Throwable {
driver.quit();
}
}
My test runner:
#CucumberOptions(
features = "src/test/java/features",
glue = "stepDefinitions")
public class TestRunner extends AbstractTestNGCucumberTests {
}
My error:
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.TakesScreenshot.getScreenshotAs(org.openqa.selenium.OutputType)" because "screenShot" is null
at resources.Base.getScreenshotPath(Base.java:53)
at cars.Listeners.onTestFailure(Listeners.java:52)
at org.testng.internal.TestListenerHelper.runTestListeners(TestListenerHelper.java:96)
at org.testng.internal.TestInvoker.runTestResultListener(TestInvoker.java:220)
at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:832)
at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:147)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(Unknown Source)
at org.testng.TestRunner.privateRun(TestRunner.java:764)
at org.testng.TestRunner.run(TestRunner.java:585)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:384)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337)
at org.testng.SuiteRunner.run(SuiteRunner.java:286)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1218)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
at org.testng.TestNG.runSuites(TestNG.java:1069)
at org.testng.TestNG.run(TestNG.java:1037)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
I am not sure why cucumber gives a NullPointerException and testng one does not. using `e.printStackTrace()' I see that the driver is null.
I have looked at answers such as null-pointer-exception-when-trying-to-take-a-screenshot-with-selenium and exception-while-taking-screenshot but nothing helped.
Replace getDeclaredField with getField
driver = (WebDriver)result.getTestClass().getRealClass().getDeclaredField("driver").get(result.getInstance());
getField can get a field inherited from a superclass but getDeclaredField cannot. getDeclaredField restricts itself to the class you call the function on.
And Remove static from public static WebDriver Driver from base class.
It has a close browser step and then you are trying to access this session in the listener class so obviously, the session will be null.
remove the after test and try
I think that the problem might be with your base file, where you have:
"public static WebDriver driver;"
remove "static" and it should work properly

NullPointerException at "new RemoteWebDriver(srvc.getUrl(), options)"

I have Three Classes as below:
And When I run the test as TestNG from 'Tests.java' I get java.lang.NullPointerException exception:
NOTE:
-It picks the browser name 'chrome' successfully from the .properties file.
-If I discard the 'Tests.java' class and move the #Test method to 'LaunchBrowserTemp.java' class and add remaining corresponding tags (i.e. BeforeClass, BeforeMethod, AfterClass, AfterMethod) to corresponding methods in 'LaunchBrowserTemp.java' it works fine. It fails only when I keep the testng annotations to the 'Tests.java' class.
src\main\java\utilities\LaunchBrowserTemp.java
public class LaunchBrowserTemp {
private static ChromeDriverService srvc;
private static WebDriver driver;
private static String browser = getProperties("selenium.browser");
private static final String baseBrowserPath = "src\\main\\resources\\drivers\\";
private static ChromeOptions options;
public static void initBrowser() throws Exception {
switch (browser.toLowerCase()){
case "chrome":
options = new ChromeOptions();
options.addArguments("--start-maximized");
options.addArguments("--disable-extensions");
options.setAcceptInsecureCerts(true);
srvc = new ChromeDriverService.Builder()
.usingDriverExecutable(new File(baseBrowserPath + "chromedriver.exe"))
.usingAnyFreePort()
.build();
srvc.start();
break;
default:
throw new Exception("Browser Not handled in code!");
}
}
public static void stopDriverService() {
srvc.stop();
}
public void startDriver() {
driver = new RemoteWebDriver(srvc.getUrl(), options);
}
public void endDriver() {
driver.quit();
}
public static WebDriver driver() {
return driver;
}
}
src\main\java\utilities\LoadProperties.java
public class LoadProperties {
public static String getProperties(String propName) {
Properties prop = new Properties();
try {
FileInputStream fis = new FileInputStream("src/main/resources/config.properties");
prop.load(fis);
} catch (Exception e){}
return prop.getProperty(propName);
}
}
src\test\java\Tests.java
public class Tests {
LaunchBrowserTemp obj = new LaunchBrowserTemp();
#BeforeClass
public void init() throws Exception{
LaunchBrowserTemp.initBrowser();
}
#BeforeTest
public void start(){
obj.startDriver();
}
#Test
public void openUrl(){
driver().get("https://www.google.com");
}
#AfterTest
public void teardown(){
obj.endDriver();
}
#AfterClass
public void terminate() {
LaunchBrowserTemp.stopDriverService();
}
}
Error Screenshot

Error -> cucumber.runtime.CucumberException: Failed to instantiate class <class> - this class doesn't have an empty or a page enabled constructor"

I am using the FirefoxDriverInstance as the singleton for calling driver. Also, using a firefox profile to bypass 2-factor-authentication.
public class FirefoxDriverInstance {
public static WebDriver Instance = null;
public static void Initialize() {
if (Instance == null) {
System.out.println("Initializing Firefox Driver!!!");
System.setProperty("webdriver.gecko.driver","./src/test/resources/driver/geckodriver2.exe");
ProfilesIni profile = new ProfilesIni();
FirefoxOptions options = new FirefoxOptions();
options.setProfile(profile.getProfile("SeleniumTester"));
Instance = new FirefoxDriver(options);
}
Instance.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
Instance.manage().window().maximize();
}
public static void close() {
System.out.println("Closing Browser!!!");
Instance.close();
Instance = null;
}
public static void quit() {
System.out.println("Quitting Browser!!!");
Instance.quit();
Instance = null;
}
}
Below is my login code using cucumber-selenium-webdriver. I have used the same driver instance.
public class TC01_Login {
#BeforeMethod
public void openbrowser() throws IOException {
FirefoxDriverInstance.Initialize();
}
public Properties propertyFileReader() throws Exception {
Properties obj = new Properties();
FileInputStream objfile = new FileInputStream(System.getProperty("user.dir")+"\\src\\test\\resources\\testdata\\application.properties");
obj.load(objfile);
return obj;
}
WebDriverWait wait = new WebDriverWait(FirefoxDriverInstance.Instance, 150);
#Given("^user has entered the required URL$")
public void user_has_entered_the_required_URL() throws Throwable {
Properties obj = propertyFileReader();
System.out.println("In the First Loop!!");
FirefoxDriverInstance.Instance.get(obj.getProperty("baseUrl"));
String actualTitle = FirefoxDriverInstance.Instance.getTitle();
System.out.println("Actual Title :" + actualTitle);
if (actualTitle.contains("test")){
System.out.println("INFO : Title is being displayed as expected.");
}
else {
System.out.println("ERROR : Title is NOT being displayed as expected."); }
}
}
Unable to understand how to bypass this error.
Try to put below code in constructor :
FirefoxDriverInstance.Initialize();
Example:
public class TC01_Login {
public TC01_Login (){
FirefoxDriverInstance.Initialize();
}
}
Remove it from BeforeMethod

JUnit get tests results at AfterClass

I need to run tests classes and show the results in screen, following this structure, but just after running all.
#RunWith(Suite.class)
#Suite.SuiteClasses({
LoginTest.class,
LogoutTest.class
})
public class AllTests {
protected static WebDriver driver;
#BeforeClass
public static void beforeClass() throws Exception {
driver = Selenium.getDriver();
driver.navigate().to(Property.SITE_ADDRESS);
driver.manage().window().maximize();
}
#AfterClass
public static void afterClass() throws Exception {
String resultString = "";
Result result = JUnitCore.runClasses(AllTests.class);
for (Failure fail : result.getFailures()) {
resultString += result.getClass() +": "+ fail.toString()+"\n";
}
if (result.wasSuccessful()) {
resultString += result.getClass() +": "+ result + "\n";
}
JFrame frame = new JFrame("Results");
JOptionPane.showMessageDialog(frame, resultString, "Title", JOptionPane.INFORMATION_MESSAGE);
driver.quit();
}
My #AfterClass is re-running my test classes, is there any other solution?

How to valid a login page using Java and Selenium WebDriver?

In my database I have the username = user#javachap.com and password = javachap
If I run the code below, it passes the test although the username and password does not exist in my database.
#Test
public void testLogin()
{
String username="abc";
String password="123";
boolean valueFound=false;
// Check the db
try
{
pstmt=conn.prepareCall("select * from user where USR_EMAIL=? and USD_PASSWORD=?");
pstmt.setString(1,username);
pstmt.setString(2,password);
rs=pstmt.executeQuery();
valueFound = rs.next();
}
catch(Exception e)
{
// report some error
}
public class LoginPageTest extends IntegrationTest {
private HtmlUnitDriver driver;
#Before
public void setup() throws MalformedURLException, UnknownHostException{
driver = new HtmlUnitDriver(true);
driver.get(System.getProperty("login.url"));
}
#Test
public void testAuthenticationFailureWhenProvidingBadCredentials(){
driver.findElement(By.id("username")).sendKeys("fakeuser");
driver.findElement(By.id("password")).sendKeys("fakepassword");
driver.findElement(By.id("login")).click();
assertTrue(driver.getCurrentUrl().endsWith("failed"));
}
#Test
public void testAuthenticationSuccessWhenProvidingCorrectCredentials(){
driver.findElement(By.id("username")).sendKeys("validuser");
driver.findElement(By.id("password")).sendKeys("validpassword");
driver.findElement(By.id("login")).click();
assertTrue(driver.getCurrentUrl().endsWith("/<name_of_webapp>/"));
}
}
That's how I do it for example.
EDIT: I just noticed comments. Anyway my code shows how you test the actual login page with Selenium.
public class Ace {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.setProperty("webdriver.chrome.driver", "D://jars//chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://your login url");
driver.findElement(By.name("username")).sendKeys("enter username");
//pay attention here By.name or By.id, see the page source properly
driver.findElement(By.name("password")).sendKeys("enter password");
driver.findElement(By.xpath("//button[#value='login']")).click();
driver.findElement(By.name("participant")).sendKeys("BLRFC1");
driver.findElement(By.xpath("//button[#type='submit']")).click();
}
}

Categories