diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..1570f4be Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 0275ff56..bae88618 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build .idea -.gradle \ No newline at end of file +.gradle +/target \ No newline at end of file diff --git a/Review_Comment.txt b/Review_Comment.txt new file mode 100644 index 00000000..59d87c27 --- /dev/null +++ b/Review_Comment.txt @@ -0,0 +1,15 @@ +THIS FILE LISTS ALL THE REVIEW COMMENTS/ NEW CHANGES ON THE CURRENT FRAMEWORK +ALSO I HAVE IMPLEMENTED MOST OF THE REVIEW COMMENTS + +=> Each test can be executed and is passing right now. +=> The thread.sleep is a hard pause, removed that to introduce dynamic waits. +=> Having selectors local to every test case is code repetition and hard to manage, +hence introduced POM framework. +=> Added surefire plugin to be able to get variables at runtime. +=> Action methods like click, sendKeys have been segregated to a new class "ActionSupport" +=> Added testng.xml file +=> Added BaseTest class to have framework level data initialization globally and +using inheritance to avail it throughout the classes. +=> Updated chromedriver to latest version to support latest chrome version. +=> Introduced property file which is also environment specific to store constants like URL. +=> Utility class to have the common methods like property initialization, getting web elements diff --git a/chromedriver b/chromedriver index 93c906e2..4ff3bcce 100755 Binary files a/chromedriver and b/chromedriver differ diff --git a/chromedriver_ b/chromedriver_ new file mode 100755 index 00000000..93c906e2 Binary files /dev/null and b/chromedriver_ differ diff --git a/pom.xml b/pom.xml index 839ed21f..7ddc1657 100644 --- a/pom.xml +++ b/pom.xml @@ -1,28 +1,67 @@ - - 4.0.0 - com.testvagrant.codingRound - codoingRound - 1.0-SNAPSHOT - - - junit - junit - 4.11 - compile - - - org.seleniumhq.selenium - selenium-java - 3.6.0 - compile - - - org.testng - testng - 6.11 - compile - - + + 4.0.0 + com.testvagrant.codingRound + codoingRound + 1.0-SNAPSHOT + + Stage + testng.xml + UTF-8 + UTF-8 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + + env + ${env} + + + + ${suiteXmlFile} + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + true + + + + + + + junit + junit + 4.11 + compile + + + org.seleniumhq.selenium + selenium-java + 3.6.0 + compile + + + org.testng + testng + 6.11 + compile + + diff --git a/src/main/java/ActionSupport.java b/src/main/java/ActionSupport.java new file mode 100644 index 00000000..85bf2bb2 --- /dev/null +++ b/src/main/java/ActionSupport.java @@ -0,0 +1,68 @@ +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.support.ui.Select; + +import java.util.Calendar; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +public class ActionSupport { + + WebDriver driver; + WebElement element = null; + Utility oUtility; + + public ActionSupport(WebDriver driver) { + this.driver = driver; + oUtility = new Utility(driver); + + } + + public void clickElement(By selector) { + + element = oUtility.getWebElement(selector); + try { + element.click(); + } catch (Exception e) { + System.out.println("element could not be clicked, Exception - " + e.getMessage()); + } + } + + public void setTextToInputfield(By selector, String text) { + + element = oUtility.getWebElement(selector); + try { + element.clear(); + element.sendKeys(text); + } catch (Exception e) { + System.out.println("The text - " + text + " could not be set to element due to exception - " + e.getMessage()); + } + } + + public String getElementText(By selector) { + element = oUtility.getWebElement(selector); + return element.getText(); + } + + public void switchToFrameByWebElement(By selector) { + element = oUtility.getWebElement(selector); + try { + driver.switchTo().frame(element); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + + public void selectValueByTextInDropdown(By selector, String text) { + try { + Select dropdown = new Select(oUtility.getWebElement(selector)); + dropdown.selectByVisibleText(text); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + } +} diff --git a/src/main/java/BaseTest.java b/src/main/java/BaseTest.java new file mode 100644 index 00000000..057354b2 --- /dev/null +++ b/src/main/java/BaseTest.java @@ -0,0 +1,62 @@ +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.BeforeTest; + +import java.util.Properties; +import java.util.concurrent.TimeUnit; + + +public class BaseTest { + + WebDriver driver; + WebElement element = null; + Utility oUtility; + String BASE_URL = ""; + Properties propObj; + String environment = ""; + ChromeOptions options = null; + ActionSupport actions; + @BeforeSuite + public void setupSuiteConfig() { + setEnvironment(); + options = new ChromeOptions(); + options.addArguments("--disable-notifications"); + driver = new ChromeDriver(options); + driver.manage().window().maximize(); + driver.manage().timeouts().implicitlyWait(45, TimeUnit.SECONDS); + actions = new ActionSupport(driver); + oUtility = new Utility(driver); + oUtility.setDriverPath(); + propObj = oUtility.getProperty(environment); + BASE_URL = propObj.getProperty("BASE_URL"); + } + + @BeforeTest + public void testSetup() { + + + } + + @AfterTest + public void testTearDown() { + //driver.quit(); + } + + @AfterSuite + public void tearSuiteConfig() { + driver.quit(); + } + + public void setEnvironment() { + environment = System.getProperty("env"); + if (environment == null) { + environment = "stage"; + } + + } +} diff --git a/src/main/java/FlightBookingTest.java b/src/main/java/FlightBookingTest.java index 19d98ddf..830dfde2 100644 --- a/src/main/java/FlightBookingTest.java +++ b/src/main/java/FlightBookingTest.java @@ -1,4 +1,3 @@ -import com.sun.javafx.PlatformUtil; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriver; @@ -7,83 +6,52 @@ import org.openqa.selenium.support.ui.Select; import org.testng.Assert; import org.testng.annotations.Test; +import pom.HomePageElements; +import pom.SearchSummaryPOM; import java.util.List; -public class FlightBookingTest { - - WebDriver driver = new ChromeDriver(); +public class FlightBookingTest extends BaseTest { @Test public void testThatResultsAppearForAOneWayJourney() { - setDriverPath(); - driver.get("https://www.cleartrip.com/"); - waitFor(2000); - driver.findElement(By.id("OneWay")).click(); - driver.findElement(By.id("FromTag")).clear(); - driver.findElement(By.id("FromTag")).sendKeys("Bangalore"); + driver.get(BASE_URL); - //wait for the auto complete options to appear for the origin + oUtility.waitForElementToBeVisible(HomePageElements.one_way_radio_button()); + actions.clickElement(HomePageElements.one_way_radio_button()); + + oUtility.waitForElementToBeVisible(HomePageElements.from_input_text_field()); + actions.setTextToInputfield(HomePageElements.from_input_text_field(), propObj.getProperty("STARTING_DESTINATION")); - waitFor(2000); - List originOptions = driver.findElement(By.id("ui-id-1")).findElements(By.tagName("li")); - originOptions.get(0).click(); + //wait for the auto complete options to appear for the origin + oUtility.waitForElementToBeVisible(HomePageElements.from_search_result()); + actions.clickElement(HomePageElements.from_search_result()); - driver.findElement(By.id("toTag")).clear(); - driver.findElement(By.id("toTag")).sendKeys("Delhi"); - //wait for the auto complete options to appear for the destination + actions.setTextToInputfield(HomePageElements.to_input_text_field(), propObj.getProperty("END_DESTINATION")); - waitFor(2000); - //select the first item from the destination auto complete list - List destinationOptions = driver.findElement(By.id("ui-id-2")).findElements(By.tagName("li")); - destinationOptions.get(0).click(); + //wait for the auto complete options to appear for the origin + oUtility.waitForElementToBeVisible(HomePageElements.to_search_result()); + actions.clickElement(HomePageElements.to_search_result()); driver.findElement(By.xpath("//*[@id='ui-datepicker-div']/div[1]/table/tbody/tr[3]/td[7]/a")).click(); //all fields filled in. Now click on search driver.findElement(By.id("SearchBtn")).click(); - waitFor(5000); - //verify that result appears for the provided journey search - Assert.assertTrue(isElementPresent(By.className("searchSummary"))); + // remove the hard pause and introduced explicit wait - //close the browser - driver.quit(); + //oUtility.waitFor(5000); + oUtility.waitForElementToBeVisible(SearchSummaryPOM.search_summary()); - } + //verify that result appears for the provided journey search + Assert.assertTrue(oUtility.isElementPresent(SearchSummaryPOM.search_summary())); - private void waitFor(int durationInMilliSeconds) { - try { - Thread.sleep(durationInMilliSeconds); - } catch (InterruptedException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } } - private boolean isElementPresent(By by) { - try { - driver.findElement(by); - return true; - } catch (NoSuchElementException e) { - return false; - } - } - - private void setDriverPath() { - if (PlatformUtil.isMac()) { - System.setProperty("webdriver.chrome.driver", "chromedriver"); - } - if (PlatformUtil.isWindows()) { - System.setProperty("webdriver.chrome.driver", "chromedriver.exe"); - } - if (PlatformUtil.isLinux()) { - System.setProperty("webdriver.chrome.driver", "chromedriver_linux"); - } - } } diff --git a/src/main/java/HotelBookingTest.java b/src/main/java/HotelBookingTest.java index 2be026bb..c5c66729 100644 --- a/src/main/java/HotelBookingTest.java +++ b/src/main/java/HotelBookingTest.java @@ -1,53 +1,33 @@ -import com.sun.javafx.PlatformUtil; +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.support.FindBy; import org.openqa.selenium.support.ui.Select; import org.testng.annotations.Test; +import pom.HomePageElements; +import pom.HotelsPOM; -public class HotelBookingTest { - - WebDriver driver = new ChromeDriver(); - - @FindBy(linkText = "Hotels") - private WebElement hotelLink; - - @FindBy(id = "Tags") - private WebElement localityTextBox; - - @FindBy(id = "SearchHotelsButton") - private WebElement searchButton; - - @FindBy(id = "travellersOnhome") - private WebElement travellerSelection; +public class HotelBookingTest extends BaseTest { @Test public void shouldBeAbleToSearchForHotels() { - setDriverPath(); - driver.get("https://www.cleartrip.com/"); - hotelLink.click(); + driver.get(BASE_URL); - localityTextBox.sendKeys("Indiranagar, Bangalore"); + actions.clickElement(HomePageElements.hotels_link_text()); - new Select(travellerSelection).selectByVisibleText("1 room, 2 adults"); - searchButton.click(); + actions.setTextToInputfield(HotelsPOM.location_inputfield(), propObj.getProperty("HOTEL_INPUT_TEXT")); + oUtility.waitForElementToBeVisible(HotelsPOM.first_search_result()); + actions.clickElement(HotelsPOM.first_search_result()); - driver.quit(); + actions.clickElement(HotelsPOM.start_date()); + oUtility.waitForElementToBeVisible(HotelsPOM.end_date()); + actions.clickElement(HotelsPOM.end_date()); + actions.selectValueByTextInDropdown(HotelsPOM.travellers_section(), "1 room, 2 adults"); - } + actions.clickElement(HotelsPOM.search_button()); - private void setDriverPath() { - if (PlatformUtil.isMac()) { - System.setProperty("webdriver.chrome.driver", "chromedriver"); - } - if (PlatformUtil.isWindows()) { - System.setProperty("webdriver.chrome.driver", "chromedriver.exe"); - } - if (PlatformUtil.isLinux()) { - System.setProperty("webdriver.chrome.driver", "chromedriver_linux"); - } } } diff --git a/src/main/java/SignInTest.java b/src/main/java/SignInTest.java index 2c109950..447cada4 100644 --- a/src/main/java/SignInTest.java +++ b/src/main/java/SignInTest.java @@ -1,51 +1,31 @@ -import com.sun.javafx.PlatformUtil; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.Assert; import org.testng.annotations.Test; +import pom.HomePageElements; -public class SignInTest { +public class SignInTest extends BaseTest{ - WebDriver driver = new ChromeDriver(); @Test public void shouldThrowAnErrorIfSignInDetailsAreMissing() { - setDriverPath(); + driver.get(BASE_URL); - driver.get("https://www.cleartrip.com/"); - waitFor(2000); + oUtility.waitForElementToBeVisible(HomePageElements.your_trips()); - driver.findElement(By.linkText("Your trips")).click(); - driver.findElement(By.id("SignIn")).click(); + actions.clickElement(HomePageElements.your_trips()); - driver.findElement(By.id("signInButton")).click(); + actions.clickElement(HomePageElements.sign_in()); - String errors1 = driver.findElement(By.id("errors1")).getText(); - Assert.assertTrue(errors1.contains("There were errors in your submission")); - driver.quit(); - } + actions.switchToFrameByWebElement(HomePageElements.frame_for_sign_in_modal()); + oUtility.waitForElementToBeVisible(HomePageElements.sign_in_button()); + actions.clickElement(HomePageElements.sign_in_button()); - private void waitFor(int durationInMilliSeconds) { - try { - Thread.sleep(durationInMilliSeconds); - } catch (InterruptedException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - - private void setDriverPath() { - if (PlatformUtil.isMac()) { - System.setProperty("webdriver.chrome.driver", "chromedriver"); - } - if (PlatformUtil.isWindows()) { - System.setProperty("webdriver.chrome.driver", "chromedriver.exe"); - } - if (PlatformUtil.isLinux()) { - System.setProperty("webdriver.chrome.driver", "chromedriver_linux"); - } - } + String text = actions.getElementText(HomePageElements.sign_in_error1()); + Assert.assertTrue(text.contains(text)); + } } diff --git a/src/main/java/Utility.java b/src/main/java/Utility.java new file mode 100644 index 00000000..8ba8c19e --- /dev/null +++ b/src/main/java/Utility.java @@ -0,0 +1,94 @@ +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Properties; + +public class Utility { + + //BaseTest oBaseTest; + private FileInputStream fileInput = null; + Properties properties = null; + WebDriver driver; + File file = null; + WebDriverWait wait; + + public Utility(WebDriver driver) { + this.driver = driver; + //oBaseTest = new BaseTest(); + } + + + public void setDriverPath() { + if (System.getProperty("os.name").toLowerCase().contains("mac")) { + System.setProperty("webdriver.chrome.driver", "chromedriver"); + } + if (System.getProperty("os.name").toLowerCase().contains("windows")) { + System.setProperty("webdriver.chrome.driver", "chromedriver.exe"); + } + if (System.getProperty("os.name").toLowerCase().contains("linux")) { + System.setProperty("webdriver.chrome.driver", "chromedriver_linux"); + } + } + + public Properties getProperty(String env) { + Properties properties = new Properties(); + + try { + file = new File("src" + + File.separator + + "main" + + File.separator + + "resources" + + File.separator + + "propertyFiles" + + File.separator + + env.toLowerCase() + "_property.properties"); + fileInput = new FileInputStream(file); + properties.load(fileInput); + //fileInput.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return properties; + } + + public void waitFor(int durationInMilliSeconds) { + try { + Thread.sleep(durationInMilliSeconds); + } catch (InterruptedException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + + + public boolean isElementPresent(By by) { + try { + driver.findElement(by); + return true; + } catch (NoSuchElementException e) { + return false; + } + } + + public void waitForElementToBeVisible(By selector) { + wait = new WebDriverWait(driver, 45); + WebElement element = wait.until(ExpectedConditions + .visibilityOfElementLocated(selector)); + } + + public WebElement getWebElement(By selector) { + return driver.findElement(selector); + } + +} + diff --git a/src/main/java/pom/HomePageElements.java b/src/main/java/pom/HomePageElements.java new file mode 100644 index 00000000..7b5a51c4 --- /dev/null +++ b/src/main/java/pom/HomePageElements.java @@ -0,0 +1,78 @@ +package pom; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +public class HomePageElements { + + WebDriver driver; + private static final String ONE_WAY_RADIO_BUTTON = "OneWay"; + private static final String FROM_INPUT_TEXT_FIELD = "FromTag"; + private static final String FROM_SEARCH_RESULT = "//*[@id='ui-id-1']//li"; + private static final String TO_INPUT_TEXT_FIELD = "ToTag"; + private static final String TO_SEARCH_RESULT = "//*[@id='ui-id-2']//li"; + private static final String YOUR_TRIPS = "Your trips"; + private static final String SIGN_IN = "SignIn"; + private static final String SIGN_IN_BUTTON = "signInButton"; + private static final String SIGN_IN_ERROR1 = "errors1"; + private static final String FRAME_SIGN_IN_MODAL = "//div//iframe[@name='modal_window']"; + private static final String HOTELS_LINK = "Hotels"; + private static final String TAG = "Tags"; + + public static By tags() + { + return By.xpath(TAG); + } + public static By hotels_link_text() + { + return By.linkText(HOTELS_LINK); + } + public static By frame_for_sign_in_modal() + { + return By.xpath(FRAME_SIGN_IN_MODAL); + } + public static By sign_in_error1() + { + return By.id(SIGN_IN_ERROR1); + } + public static By sign_in_button() + { + return By.id(SIGN_IN_BUTTON); + } + public static By sign_in() + { + return By.id(SIGN_IN); + } + public static By your_trips() + { + return By.linkText(YOUR_TRIPS); + } + public static By one_way_radio_button() + { + return By.id(ONE_WAY_RADIO_BUTTON); + } + + public static By from_input_text_field() + { + return By.id(FROM_INPUT_TEXT_FIELD); + } + + public static By from_search_result() + { + return By.xpath(FROM_SEARCH_RESULT); + } + public static By to_input_text_field() + { + return By.id(TO_INPUT_TEXT_FIELD); + } + + public static By to_search_result() + { + return By.xpath(TO_SEARCH_RESULT); + } + + + + +} diff --git a/src/main/java/pom/HotelsPOM.java b/src/main/java/pom/HotelsPOM.java new file mode 100644 index 00000000..bb830974 --- /dev/null +++ b/src/main/java/pom/HotelsPOM.java @@ -0,0 +1,33 @@ +package pom; + +import org.openqa.selenium.By; + +public class HotelsPOM { + + private static final String LOCATION_INPUT_FIELD = "Tags"; + private static final String SEARCH_BUTTON = "SearchHotelsButton"; + private static final String TRAVELLERS_SECTION = "travellersOnhome"; + private static final String FIRST_SEARCH_RESULT = "#ui-id-1 .list:nth-child(2) >a"; + private static final String START_DATE = ".ui-datepicker-days-cell-over"; + private static final String END_DATE = ".ui-state-active"; + + public static By start_date() { + return By.cssSelector(START_DATE); + } + public static By end_date() { + return By.cssSelector(END_DATE); + } + public static By first_search_result() { + return By.cssSelector(FIRST_SEARCH_RESULT); + } + public static By travellers_section() { + return By.id(TRAVELLERS_SECTION); + } + public static By location_inputfield() { + return By.id(LOCATION_INPUT_FIELD); + } + + public static By search_button() { + return By.id(SEARCH_BUTTON); + } +} diff --git a/src/main/java/pom/SearchSummaryPOM.java b/src/main/java/pom/SearchSummaryPOM.java new file mode 100644 index 00000000..59bf96a9 --- /dev/null +++ b/src/main/java/pom/SearchSummaryPOM.java @@ -0,0 +1,12 @@ +package pom; + +import org.openqa.selenium.By; + +public class SearchSummaryPOM { + + private static final String SEARCH_SUMMARY = "searchSummary"; + + public static By search_summary() { + return By.className(SEARCH_SUMMARY); + } +} diff --git a/src/main/resources/propertyFiles/stage_property.properties b/src/main/resources/propertyFiles/stage_property.properties new file mode 100644 index 00000000..84307b9a --- /dev/null +++ b/src/main/resources/propertyFiles/stage_property.properties @@ -0,0 +1,10 @@ +BASE_URL=https://www.cleartrip.com/ + +STARTING_DESTINATION=Bangalore +END_DESTINATION=Delhi + +TIMEOUT_SECONDS=30 +MEDIUM_TIMEOUT_SECONDS=45 +LARGE_TIMEOUT_SECONDS=60 + +HOTEL_INPUT_TEXT=Indiranagar, Bangalore \ No newline at end of file diff --git a/testng.xml b/testng.xml new file mode 100644 index 00000000..86e3dc33 --- /dev/null +++ b/testng.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file