diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000..9eb3cf3 --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: starter.CukesRunner + diff --git a/build.gradle b/build.gradle index 960eb5b..659617a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -defaultTasks 'clean','test','aggregate' +defaultTasks 'clean', 'test', 'aggregate' repositories { mavenLocal() @@ -11,7 +11,8 @@ buildscript { jcenter() } dependencies { - classpath("net.serenity-bdd:serenity-gradle-plugin:1.8.3") +// classpath("net.serenity-bdd:serenity-gradle-plugin:${serenityCoreVersion}") + classpath("net.serenity-bdd:serenity-gradle-plugin:2.2.0") } } @@ -19,28 +20,46 @@ apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'net.serenity-bdd.aggregator' -apply from: "$rootDir/gradle/libraries.gradle" - sourceCompatibility = 1.8 targetCompatibility = 1.8 +ext { + slf4jVersion = '1.7.7' + serenityCoreVersion = '2.2.13' + serenityCucumberVersion = '2.2.6' + junitVersion = '4.12' + assertJVersion = '3.8.0' + logbackVersion = '1.2.3' +} + dependencies { - compile libs.slf4jApi, - libs.logback - - testCompile libs.test.serenity.core, - libs.test.serenity.screenplay, - libs.test.serenity.screenplayWebdriver, - libs.test.serenity.junit, - libs.test.junit, - libs.test.assertj + compile "ch.qos.logback:logback-classic:${logbackVersion}" + +// implementation "net.serenity-bdd:serenity-cucumber:${serenityCucumberVersion}" + + testCompile "net.serenity-bdd:serenity-core:${serenityCoreVersion}", + "net.serenity-bdd:serenity-cucumber5:${serenityCucumberVersion}", + "net.serenity-bdd:serenity-screenplay:${serenityCoreVersion}", + "net.serenity-bdd:serenity-screenplay-webdriver:${serenityCoreVersion}", + "junit:junit:${junitVersion}", + "org.assertj:assertj-core:${assertJVersion}" } test { testLogging.showStandardStreams = true systemProperties System.getProperties() } +jar { + from { + // Package all dependencies in the .jar + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } + manifest { + // Indicate the main class for the .jar file + attributes 'Main-Class': 'CukesRunner' + } +} gradle.startParameter.continueOnFailure = true diff --git a/out/artifacts/serenity_junit_starter_jar/serenity-junit-starter.jar b/out/artifacts/serenity_junit_starter_jar/serenity-junit-starter.jar new file mode 100644 index 0000000..9a6bb7c Binary files /dev/null and b/out/artifacts/serenity_junit_starter_jar/serenity-junit-starter.jar differ diff --git a/src/test/java/Tasks/BookClass.java b/src/test/java/Tasks/BookClass.java new file mode 100644 index 0000000..9c017e9 --- /dev/null +++ b/src/test/java/Tasks/BookClass.java @@ -0,0 +1,60 @@ +package Tasks; + +import Utils.SwitchFrame; +import Utils.SwitchPage; +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Performable; +import net.serenitybdd.screenplay.Task; +import net.serenitybdd.screenplay.actions.Click; +import net.serenitybdd.screenplay.actions.Switch; +import net.serenitybdd.screenplay.waits.WaitUntil; +import starter.login.LoginForm; + +import static net.serenitybdd.screenplay.Tasks.instrumented; +import static net.serenitybdd.screenplay.matchers.WebElementStateMatchers.isClickable; +import static net.serenitybdd.screenplay.matchers.WebElementStateMatchers.isVisible; +import static starter.login.LoginForm.FRAME_2; +import static starter.login.LoginForm.FRAME_3; + +public class BookClass implements Task { + + @Override + public void performAs(T actor) { + actor.attemptsTo( + WaitUntil.the(LoginForm.PROGRAM_BUTTON, isClickable()), + Click.on(LoginForm.PROGRAM_BUTTON), + WaitUntil.the(LoginForm.SELECT_PROGRAM, isClickable()), + Click.on(LoginForm.SELECT_PROGRAM), + Click.on(LoginForm.BEGIN), + WaitUntil.the(FRAME_2,isVisible()), + SwitchFrame.switchToFrame(FRAME_2), + WaitUntil.the(LoginForm.DROPDOWN_LIST,isClickable()), + Click.on(LoginForm.DROPDOWN_LIST), + WaitUntil.the(LoginForm.PENDINGS,isClickable()), + Click.on(LoginForm.PENDINGS), + WaitUntil.the(LoginForm.NUMBER_CLASS,isClickable()), + Click.on(LoginForm.NUMBER_CLASS), + WaitUntil.the(LoginForm.SCHEDULE_BUTTON,isClickable()), + Click.on(LoginForm.SCHEDULE_BUTTON), + Switch.toParentFrame(), + WaitUntil.the(FRAME_3,isClickable()), + SwitchFrame.switchToFrame(FRAME_3), +// WaitUntil.the(LoginForm.DAY_LIST,isClickable()), +// Click.on(LoginForm.DAY_LIST), + WaitUntil.the(LoginForm.SELECT_DAY,isClickable()), + Click.on(LoginForm.SELECT_DAY), +// WaitUntil.the(LoginForm.HOUR,isClickable()), + Click.on(LoginForm.HOUR), + Click.on(LoginForm.ENTER_BUTTON) + + +// WaitUntil.the(LoginForm.SCHEDULE_BUTTON, isClickable()), +// Click.on(LoginForm.SCHEDULE_BUTTON) + ); + + } + + public static Performable bookClass(){ + return instrumented(BookClass.class); + } +} diff --git a/src/test/java/Tasks/DoLogin.java b/src/test/java/Tasks/DoLogin.java new file mode 100644 index 0000000..4453d8e --- /dev/null +++ b/src/test/java/Tasks/DoLogin.java @@ -0,0 +1,42 @@ +package Tasks; + +import Utils.SwitchPage; +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Performable; +import net.serenitybdd.screenplay.Task; +import net.serenitybdd.screenplay.actions.Click; +import net.serenitybdd.screenplay.actions.Enter; +import net.serenitybdd.screenplay.waits.WaitUntil; +import starter.login.LoginForm; + +import static net.serenitybdd.screenplay.Tasks.instrumented; +import static net.serenitybdd.screenplay.matchers.WebElementStateMatchers.isClickable; + +public class DoLogin implements Task { + + private final String username; + private final String password; + + public DoLogin(String username, String password) { + this.username = username; + this.password = password; + } + + public static Performable withCredentials(String username, String password){ + return instrumented(DoLogin.class, username, password); + } + @Override + public void performAs(T actor) { +// String defaultHandle = BrowseTheWeb.as(actor).getDriver().getWindowHandle(); + actor.attemptsTo( +// Switch.toActiveElement(), + WaitUntil.the(LoginForm.LOGIN_FIELD, isClickable()), + Click.on(LoginForm.LOGIN_FIELD), + SwitchPage.switchBetweenPages(), + WaitUntil.the(LoginForm.USERNAME_FIELD,isClickable()), + Enter.theValue(username).into(LoginForm.USERNAME_FIELD), + Enter.theValue(password).into(LoginForm.PASSWORD_FIELD), + Click.on(LoginForm.ENTER_BUTTON) + ); + } +} \ No newline at end of file diff --git a/src/test/java/Tasks/NavigateTo.java b/src/test/java/Tasks/NavigateTo.java new file mode 100644 index 0000000..a075daa --- /dev/null +++ b/src/test/java/Tasks/NavigateTo.java @@ -0,0 +1,13 @@ +package Tasks; + +import net.serenitybdd.screenplay.Performable; +import net.serenitybdd.screenplay.Task; +import net.serenitybdd.screenplay.actions.Open; +import starter.login.EnglishPage; + +public class NavigateTo { + public static Performable theLoginEnglishPage() { + return Task.where("{0} opens the login english page", + Open.browserOn().the(EnglishPage.class)); + } +} diff --git a/src/test/java/Utils/SwitchFrame.java b/src/test/java/Utils/SwitchFrame.java new file mode 100644 index 0000000..261aba2 --- /dev/null +++ b/src/test/java/Utils/SwitchFrame.java @@ -0,0 +1,44 @@ +package Utils; + +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Performable; +import net.serenitybdd.screenplay.Task; +import net.serenitybdd.screenplay.abilities.BrowseTheWeb; +import net.serenitybdd.screenplay.actions.Switch; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import static net.serenitybdd.screenplay.Tasks.instrumented; + + + +public class SwitchFrame implements Task { + private final By locatorFrame; + + public SwitchFrame(By locatorFrame){ + this.locatorFrame = locatorFrame; + } + public WebElement SwitchDoubleTap(By locator_frame, Actor actor){ + WebElement frame= BrowseTheWeb.as(actor).find(locator_frame); + return frame; + } + + + + @Override + public void performAs(T actor) { + + actor.attemptsTo( + Switch.toFrame(SwitchDoubleTap(locatorFrame, actor)) + + ); + + + } + + public static Performable switchToFrame(By locatorFrame) { + return instrumented(SwitchFrame.class,locatorFrame); + } +} + + diff --git a/src/test/java/Utils/SwitchPage.java b/src/test/java/Utils/SwitchPage.java new file mode 100644 index 0000000..20b0c04 --- /dev/null +++ b/src/test/java/Utils/SwitchPage.java @@ -0,0 +1,40 @@ +package Utils; + + +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Performable; +import net.serenitybdd.screenplay.Task; +import net.serenitybdd.screenplay.abilities.BrowseTheWeb; +import net.serenitybdd.screenplay.actions.Switch; + + +import static net.serenitybdd.screenplay.Tasks.instrumented; + + +public class SwitchPage implements Task { + + + public static String getNewWindowHandle(Actor actor, String currentWindowHandle){ + for(String windowHandle : BrowseTheWeb.as(actor).getDriver().getWindowHandles()){ + if(!windowHandle.equals(currentWindowHandle)){ +// System.out.println("+++++++++++++++++++++++ "+windowHandle); + return windowHandle; + } + } + return null; + } + + @Override + public void performAs(T actor) { + String currentHandle = BrowseTheWeb.as(actor).getDriver().getWindowHandle(); + actor.attemptsTo( + Switch.toWindow(getNewWindowHandle(actor,currentHandle)) + + ); + + + } + public static Performable switchBetweenPages(){ + return instrumented(SwitchPage.class); + } +} diff --git a/src/test/java/starter/ASimpleTest.java b/src/test/java/starter/ASimpleTest.java index 9056671..990707a 100644 --- a/src/test/java/starter/ASimpleTest.java +++ b/src/test/java/starter/ASimpleTest.java @@ -1,27 +1,18 @@ package starter; -import net.serenitybdd.junit.runners.SerenityRunner; +import io.cucumber.junit.CucumberOptions; +import net.serenitybdd.cucumber.CucumberWithSerenity; +//import net.serenitybdd.junit.runners.SerenityRunner; import net.thucydides.core.annotations.Pending; import net.thucydides.core.annotations.Steps; import org.junit.Test; import org.junit.runner.RunWith; -import starter.steps.MathWizSteps; -@RunWith(SerenityRunner.class) -public class ASimpleTest { - - @Steps - MathWizSteps michael; - @Test - public void addingSums() { - // Given - michael.startsWith(1); +@RunWith(CucumberWithSerenity.class) +@CucumberOptions(features = "src/test/resources/features/login", +glue="starter.stepdefinitions") +public class ASimpleTest { - // When - michael.adds(2); - // Then - michael.shouldHave(3); - } } diff --git a/src/test/java/starter/CukesRunner.java b/src/test/java/starter/CukesRunner.java new file mode 100644 index 0000000..723b3fa --- /dev/null +++ b/src/test/java/starter/CukesRunner.java @@ -0,0 +1,12 @@ +package starter; + + +public class CukesRunner { + public static void main(String[] args) throws Throwable { + final String[] arguments = new String[]{ + "--glue", "starter", + "src/test/resources/features/login"// This will look for the classpath inside the jar file + }; + io.cucumber.core.cli.Main.main(arguments); + } +} diff --git a/src/test/java/starter/login/EnglishPage.java b/src/test/java/starter/login/EnglishPage.java new file mode 100644 index 0000000..6764dc3 --- /dev/null +++ b/src/test/java/starter/login/EnglishPage.java @@ -0,0 +1,8 @@ +package starter.login; + +import net.thucydides.core.annotations.DefaultUrl; +import net.thucydides.core.pages.PageObject; + +@DefaultUrl("https://smart.edu.co/estudiante") +public class EnglishPage extends PageObject { +} diff --git a/src/test/java/starter/login/LoginForm.java b/src/test/java/starter/login/LoginForm.java new file mode 100644 index 0000000..e0aab2c --- /dev/null +++ b/src/test/java/starter/login/LoginForm.java @@ -0,0 +1,36 @@ +package starter.login; + + +import net.serenitybdd.screenplay.targets.Target; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +public class LoginForm { + + public static By LOGIN_FIELD = By.xpath("//a[@href='https://schoolpack.smart.edu.co/idiomas/alumnos.aspx' and @target]"); + public static By USERNAME_FIELD = By.id("vUSUCOD"); + public static By PASSWORD_FIELD = By.id("vPASS"); + public static By ENTER_BUTTON = By.id("BUTTON1"); + + public static By PROGRAM_BUTTON = By.xpath("//img[@src='Resources/PROGRAMACION.png']"); + + public static By SELECT_PROGRAM = By.xpath("//span[@id='span_W0030TMPDESART_0001']"); + public static By BEGIN = By.xpath("//input[@id='W0030BUTTON1']"); + public static By BACK = By.xpath("//input[@id='BUTTON3']"); + public static By FRAME_2= By.id("gxp0_ifrm"); + public static By DROPDOWN_LIST = By.xpath("//select[@name='vTPEAPROBO']"); + + public static By PENDINGS = By.xpath("//option[@value='2']"); + public static By NUMBER_CLASS = By.id("span_vPRONOMPRO_0002"); + public static By SCHEDULE_BUTTON = By.xpath("//input[@value='Asignar' ]"); +// public static By DAY_LIST = By.xpath("//select[@name='vDIA']"); + public static By SELECT_DAY = By.xpath("//*[@name='vDIA']//child::option[2]"); + + public static By FRAME_3= By.id("gxp1_ifrm"); + + public static By HOUR = By.xpath("//td[@data-colindex='2']//child::span[@id='span_W0030TMPCODART_0001']"); + + public static By CONFIRMATION_TEXT = By.xpath("//div[@class='gx-warning-message']"); + + public static By CLOSE = By.xpath("//span[@id='gxp1_cls']"); +} diff --git a/src/test/java/starter/questions/CheckSchedule.java b/src/test/java/starter/questions/CheckSchedule.java new file mode 100644 index 0000000..2a2ed69 --- /dev/null +++ b/src/test/java/starter/questions/CheckSchedule.java @@ -0,0 +1,32 @@ +package starter.questions; + + +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Question; +import net.serenitybdd.screenplay.abilities.BrowseTheWeb; +import net.serenitybdd.screenplay.actions.Click; +import starter.login.LoginForm; + +import static starter.login.LoginForm.CONFIRMATION_TEXT; + + +public class CheckSchedule implements Question{ + + + + @Override + public Boolean answeredBy(Actor actor) { + if(BrowseTheWeb.as(actor).find(CONFIRMATION_TEXT).isDisplayed()){ + Click.on(LoginForm.CLOSE); + return true; + } + else { + + return false; + } + } + + public static CheckSchedule booked(){ + return new CheckSchedule(); + } +} diff --git a/src/test/java/starter/stepdefinitions/LoginStepDefinitions.java b/src/test/java/starter/stepdefinitions/LoginStepDefinitions.java new file mode 100644 index 0000000..c4ca24e --- /dev/null +++ b/src/test/java/starter/stepdefinitions/LoginStepDefinitions.java @@ -0,0 +1,51 @@ +package starter.stepdefinitions; + +import Tasks.BookClass; +import io.cucumber.java.Before; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import net.serenitybdd.screenplay.actors.OnStage; +import net.serenitybdd.screenplay.actors.OnlineCast; +import Tasks.DoLogin; +import Tasks.NavigateTo; +import starter.questions.CheckSchedule; + +import static net.serenitybdd.screenplay.GivenWhenThen.seeThat; + +import static net.serenitybdd.screenplay.actors.OnStage.theActorCalled; +import static org.hamcrest.CoreMatchers.equalTo; + +public class LoginStepDefinitions { + + String name; + + @Before + public void setTheStage(){ + OnStage.setTheStage(new OnlineCast()); + } + @Given("^(.*) has an active english account") + public void julian_has_an_active_account(String name){ + this.name=name; + theActorCalled(name).attemptsTo(NavigateTo.theLoginEnglishPage(), + DoLogin.withCredentials("1006693450","dragones123") + ); + + } + + @When("he books their class for the next day") + public void he_books_their_class_for_the_next_day(){ + + theActorCalled(name).attemptsTo( + BookClass.bookClass() + + ); + } + + @Then("he should have schedule his class successful") + public void he_should_have_schedule_his_class_successful(){ + theActorCalled(name).should( + seeThat(CheckSchedule.booked(), equalTo(true)) + ); + } +} diff --git a/src/test/java/starter/steps/MathWizSteps.java b/src/test/java/starter/steps/MathWizSteps.java deleted file mode 100644 index c50a11e..0000000 --- a/src/test/java/starter/steps/MathWizSteps.java +++ /dev/null @@ -1,26 +0,0 @@ -package starter.steps; - -import net.thucydides.core.annotations.Step; -import static org.assertj.core.api.Assertions.assertThat; - -public class MathWizSteps { - - String actor; - - Calculator calculator; - - @Step("#actor starts with {0}") - public void startsWith(int amount) { - calculator = new Calculator(amount); - } - - @Step("#actor adds {0}") - public void adds(int amount) { - calculator.add(amount); - } - - @Step("#actor should have {0}") - public void shouldHave(int expectedTotal) { - assertThat(calculator.getTotal()).isEqualTo(expectedTotal); - } -} diff --git a/src/test/resources/chromewebdriver/chromedriver.exe b/src/test/resources/chromewebdriver/chromedriver.exe new file mode 100644 index 0000000..52c06f0 Binary files /dev/null and b/src/test/resources/chromewebdriver/chromedriver.exe differ diff --git a/src/test/resources/chromewebdriver2v/chromedriver.exe b/src/test/resources/chromewebdriver2v/chromedriver.exe new file mode 100644 index 0000000..175a0b0 Binary files /dev/null and b/src/test/resources/chromewebdriver2v/chromedriver.exe differ diff --git a/src/test/resources/features/login/login.feature b/src/test/resources/features/login/login.feature new file mode 100644 index 0000000..49a9a4d --- /dev/null +++ b/src/test/resources/features/login/login.feature @@ -0,0 +1,6 @@ +Feature: Login into the english page + + Scenario: Successful schedule english class + Given Julian has an active english account + When he books their class for the next day + Then he should have schedule his class successful \ No newline at end of file diff --git a/src/test/resources/serenity.conf b/src/test/resources/serenity.conf new file mode 100644 index 0000000..666ff53 --- /dev/null +++ b/src/test/resources/serenity.conf @@ -0,0 +1,50 @@ +webdriver { + driver = chrome +} +headless.mode = false + +# +# Chrome options can be defined using the chrome.switches property +# +chrome.switches="""--start-maximized;--test-type;--no-sandbox;--ignore-certificate-errors; + --disable-popup-blocking;--disable-default-apps;--disable-extensions-file-access-check; + --incognito;--disable-infobars,--disable-gpu""" + +# +# Define drivers for different platforms. Serenity will automatically pick the correct driver for the current platform +# +drivers { + windows { + webdriver.chrome.driver = "src/test/resources/chromewebdriver2v/chromedriver.exe" + webdriver.gecko.driver = "src/test/resources/webdriver/windows/geckodriver.exe" + } + mac { + webdriver.chrome.driver = "src/test/resources/webdriver/mac/chromedriver" + webdriver.gecko.driver = "src/test/resources/webdriver/mac/geckodriver" + } + linux { + webdriver.chrome.driver = "src/test/resources/webdriver/linux/chromedriver" + webdriver.gecko.driver = "src/test/resources/webdriver/linux/geckodriver" + } +} + +# +# This section defines environment-specific configuration for different environments. +# You can define normal Serenity properties, such as webdriver.base.url, or custom ones +# You can find more details about this feature at https://johnfergusonsmart.com/environment-specific-configuration-in-serenity-bdd/ +# + +environments { + default { + webdriver.base.url = "https://smart.edu.co/estudiante" + } + dev { + webdriver.base.url = "https://smart.edu.co/estudiante" + } + staging { + webdriver.base.url = "https://smart.edu.co/estudiante" + } + prod { + webdriver.base.url = "https://smart.edu.co/estudiante" + } +} \ No newline at end of file