From d08673ecb110603437096ec7a2dc38284ab30aae Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Thu, 9 Nov 2023 09:56:30 +0700 Subject: [PATCH] Prepare code template for workshop day 3 --- README.md | 4 +- docker-compose.yml | 10 +++ src/test/java/starter/CucumberTestSuite.java | 2 +- .../navigation/DuckDuckGoHomePage.java | 8 --- .../java/starter/navigation/NavigateTo.java | 7 +- .../navigation/SpringPetclinicHomePage.java | 8 +++ .../starter/search/LookForInformation.java | 16 ----- .../java/starter/search/SearchArticle.java | 7 -- src/test/java/starter/search/SearchForm.java | 8 --- .../PetTypeStepDefinitions.java | 69 +++++++++++++++++++ .../SearchStepDefinitions.java | 32 --------- .../SpecialtyStepDefinitions.java | 61 ++++++++++++++++ .../features/search/search_by_keyword.feature | 13 ---- .../veterinarian/manage_pet_types.feature | 16 +++++ .../veterinarian/manage_specialties.feature | 14 ++++ src/test/resources/junit-platform.properties | 2 +- 16 files changed, 186 insertions(+), 91 deletions(-) create mode 100644 docker-compose.yml delete mode 100644 src/test/java/starter/navigation/DuckDuckGoHomePage.java create mode 100644 src/test/java/starter/navigation/SpringPetclinicHomePage.java delete mode 100644 src/test/java/starter/search/LookForInformation.java delete mode 100644 src/test/java/starter/search/SearchArticle.java delete mode 100644 src/test/java/starter/search/SearchForm.java create mode 100644 src/test/java/starter/stepdefinitions/PetTypeStepDefinitions.java delete mode 100644 src/test/java/starter/stepdefinitions/SearchStepDefinitions.java create mode 100644 src/test/java/starter/stepdefinitions/SpecialtyStepDefinitions.java delete mode 100644 src/test/resources/features/search/search_by_keyword.feature create mode 100644 src/test/resources/features/veterinarian/manage_pet_types.feature create mode 100644 src/test/resources/features/veterinarian/manage_specialties.feature diff --git a/README.md b/README.md index 3d44df9..7b3ef26 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ src + java Test runners and supporting code + resources + features Feature files - + search Feature file subdirectories - search_by_keyword.feature + + veterinarian Feature file subdirectories + manage_specialties.feature ``` Serenity 2.2.13 introduced integration with [WebDriverManager](https://bonigarcia.dev/webdrivermanager/) to download webdriver binaries. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2aefcde --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +--- +services: + api: + image: docker.io/springcommunity/spring-petclinic-rest:3.0.2 + ports: + - "127.0.0.1:9966:9966" + app: + image: docker.io/addianto/spring-petclinic-angular:latest + ports: + - "127.0.0.1:80:8080" diff --git a/src/test/java/starter/CucumberTestSuite.java b/src/test/java/starter/CucumberTestSuite.java index cdac1f7..da9bb37 100644 --- a/src/test/java/starter/CucumberTestSuite.java +++ b/src/test/java/starter/CucumberTestSuite.java @@ -12,4 +12,4 @@ import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME; @SelectClasspathResource("/features") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "io.cucumber.core.plugin.SerenityReporterParallel,pretty,timeline:build/test-results/timeline") public class CucumberTestSuite { -} +} \ No newline at end of file diff --git a/src/test/java/starter/navigation/DuckDuckGoHomePage.java b/src/test/java/starter/navigation/DuckDuckGoHomePage.java deleted file mode 100644 index d54895b..0000000 --- a/src/test/java/starter/navigation/DuckDuckGoHomePage.java +++ /dev/null @@ -1,8 +0,0 @@ -package starter.navigation; - -import net.serenitybdd.annotations.DefaultUrl; -import net.thucydides.core.pages.PageObject; - -@DefaultUrl("https://duckduckgo.com") -public class DuckDuckGoHomePage extends PageObject { -} diff --git a/src/test/java/starter/navigation/NavigateTo.java b/src/test/java/starter/navigation/NavigateTo.java index 7292a40..ed2172b 100644 --- a/src/test/java/starter/navigation/NavigateTo.java +++ b/src/test/java/starter/navigation/NavigateTo.java @@ -5,8 +5,9 @@ import net.serenitybdd.screenplay.Task; import net.serenitybdd.screenplay.actions.Open; public class NavigateTo { - public static Performable theSearchHomePage() { - return Task.where("{0} opens the DuckDuckGo home page", - Open.browserOn().the(DuckDuckGoHomePage.class)); + + public static Performable theSpringPetclinicHomePage() { + return Task.where("{0} opens the Spring Petclinic home page", + Open.browserOn().the(SpringPetclinicHomePage.class)); } } diff --git a/src/test/java/starter/navigation/SpringPetclinicHomePage.java b/src/test/java/starter/navigation/SpringPetclinicHomePage.java new file mode 100644 index 0000000..de53d17 --- /dev/null +++ b/src/test/java/starter/navigation/SpringPetclinicHomePage.java @@ -0,0 +1,8 @@ +package starter.navigation; + +import net.serenitybdd.annotations.DefaultUrl; +import net.serenitybdd.core.pages.PageObject; + +@DefaultUrl("http://127.0.0.1") +public class SpringPetclinicHomePage extends PageObject { +} diff --git a/src/test/java/starter/search/LookForInformation.java b/src/test/java/starter/search/LookForInformation.java deleted file mode 100644 index d17fa05..0000000 --- a/src/test/java/starter/search/LookForInformation.java +++ /dev/null @@ -1,16 +0,0 @@ -package starter.search; - -import net.serenitybdd.screenplay.Performable; -import net.serenitybdd.screenplay.Task; -import net.serenitybdd.screenplay.actions.Enter; -import org.openqa.selenium.Keys; - -public class LookForInformation { - public static Performable about(String searchTerm) { - return Task.where("{0} searches for '" + searchTerm + "'", - Enter.theValue(searchTerm) - .into(SearchForm.SEARCH_FIELD) - .thenHit(Keys.ENTER) - ); - } -} diff --git a/src/test/java/starter/search/SearchArticle.java b/src/test/java/starter/search/SearchArticle.java deleted file mode 100644 index e510ffc..0000000 --- a/src/test/java/starter/search/SearchArticle.java +++ /dev/null @@ -1,7 +0,0 @@ -package starter.search; - -import net.serenitybdd.screenplay.targets.Target; - -public class SearchArticle { - public static final Target BODY = Target.the("article identifier").locatedBy("//article"); -} diff --git a/src/test/java/starter/search/SearchForm.java b/src/test/java/starter/search/SearchForm.java deleted file mode 100644 index 404636c..0000000 --- a/src/test/java/starter/search/SearchForm.java +++ /dev/null @@ -1,8 +0,0 @@ -package starter.search; - -import net.serenitybdd.screenplay.targets.Target; - -class SearchForm { - static Target SEARCH_FIELD = Target.the("search field").locatedBy("#searchbox_input"); - -} diff --git a/src/test/java/starter/stepdefinitions/PetTypeStepDefinitions.java b/src/test/java/starter/stepdefinitions/PetTypeStepDefinitions.java new file mode 100644 index 0000000..1fee08f --- /dev/null +++ b/src/test/java/starter/stepdefinitions/PetTypeStepDefinitions.java @@ -0,0 +1,69 @@ +package starter.stepdefinitions; + +import io.cucumber.datatable.DataTable; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import net.serenitybdd.core.pages.WebElementFacade; +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.actions.Click; +import net.serenitybdd.screenplay.actions.Enter; +import net.serenitybdd.screenplay.actions.HoverOverBy; +import net.serenitybdd.screenplay.actions.Open; +import net.serenitybdd.screenplay.ensure.Ensure; +import net.serenitybdd.screenplay.ui.Button; +import net.serenitybdd.screenplay.ui.InputField; +import net.serenitybdd.screenplay.ui.Link; +import org.openqa.selenium.Keys; +import starter.navigation.SpringPetclinicHomePage; + +import java.util.List; + +public class PetTypeStepDefinitions { + @Given("a system operator named {actor} is looking at the pet types page") + public void lookingAtPetTypesPage(Actor actor) { + actor.wasAbleTo( + Open.browserOn() + .the(SpringPetclinicHomePage.class), + // TODO: Refactor the two actions below into a new Performable class + HoverOverBy.over(Link.withText("Pet Types")), + Click.on(Link.withText("Pet Types")) + ); + } + + @And("{actor} found the following pet types exist:") + public void verifyingExistingPetTypes(Actor actor, DataTable table) { + List<String> existingPetTypes = InputField + .withNameOrId("pettype_name") + .resolveAllFor(actor) + .map(WebElementFacade::getValue); + + actor.wasAbleTo( + Ensure.that(existingPetTypes) + .containsElementsFrom(table.asList()) + ); + } + + @When("{actor} adds a new pet type named {string}") + public void addsNewPetType(Actor actor, String name) { + actor.attemptsTo( + // TODO: Refactor the click action below into a new Performable class + Click.on(Button.withText("Add")), + Enter.theValue(name) + .into(InputField.withNameOrId("name")) + .thenHit(Keys.ENTER) + ); + } + + @Then("{actor} should see the pet type {string} on the list of pet types") + public void shouldSeeThePetType(Actor actor, String name) { + actor.attemptsTo( + Ensure.thatAmongst(InputField.withNameOrId("pettype_name")) + .anyMatch(name + " should be on the list", + (field) -> field.getValue() + .equals(name) + ) + ); + } +} diff --git a/src/test/java/starter/stepdefinitions/SearchStepDefinitions.java b/src/test/java/starter/stepdefinitions/SearchStepDefinitions.java deleted file mode 100644 index cf2d19e..0000000 --- a/src/test/java/starter/stepdefinitions/SearchStepDefinitions.java +++ /dev/null @@ -1,32 +0,0 @@ -package starter.stepdefinitions; - -import io.cucumber.java.en.Given; -import io.cucumber.java.en.Then; -import io.cucumber.java.en.When; -import net.serenitybdd.screenplay.Actor; -import net.serenitybdd.screenplay.ensure.Ensure; -import net.serenitybdd.screenplay.questions.page.TheWebPage; -import starter.navigation.NavigateTo; -import starter.search.LookForInformation; - -public class SearchStepDefinitions { - - @Given("{actor} is researching things on the internet") - public void researchingThings(Actor actor) { - actor.wasAbleTo(NavigateTo.theSearchHomePage()); - } - - @When("{actor} looks up {string}") - public void searchesFor(Actor actor, String term) { - actor.attemptsTo( - LookForInformation.about(term) - ); - } - - @Then("{actor} should see information about {string}") - public void should_see_information_about(Actor actor, String term) { - actor.attemptsTo( - Ensure.that(TheWebPage.title()).containsIgnoringCase(term) - ); - } -} diff --git a/src/test/java/starter/stepdefinitions/SpecialtyStepDefinitions.java b/src/test/java/starter/stepdefinitions/SpecialtyStepDefinitions.java new file mode 100644 index 0000000..cd54eb5 --- /dev/null +++ b/src/test/java/starter/stepdefinitions/SpecialtyStepDefinitions.java @@ -0,0 +1,61 @@ +package starter.stepdefinitions; + +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.actions.*; +import net.serenitybdd.screenplay.ensure.Ensure; +import net.serenitybdd.screenplay.ui.Button; +import net.serenitybdd.screenplay.ui.InputField; +import net.serenitybdd.screenplay.ui.Link; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import starter.navigation.SpringPetclinicHomePage; + +public class SpecialtyStepDefinitions { + + @Given("a system operator named {actor} is looking at the specialties page") + public void lookingAtSpecialtiesPage(Actor actor) { + actor.wasAbleTo( + Open.browserOn() + .the(SpringPetclinicHomePage.class), + // TODO: Refactor the two actions below into a new Performable class + HoverOverBy.over(Link.withText("Specialties")), + Click.on(Link.withText("Specialties")) + ); + } + + @When("{actor} adds a new specialty called {string}") + public void addsNewSpecialty(Actor actor, String name) { + actor.attemptsTo( + // TODO: Refactor the Click action into a new Performable class + Click.on(Button.withText("Add")), + Enter.theValue(name) + .into(InputField.withNameOrId("name")) + .thenHit(Keys.ENTER) + ); + } + + @When("{actor} edits the first specialty to {string}") + public void editsFirstSpecialty(Actor actor, String name) { + actor.attemptsTo( + Click.on(Button.located(By.xpath("//table[@id='specialties']/tbody/tr[1]/td[2]/button[1]"))), + Clear.field(InputField.withNameOrId("name")), + Enter.theValue(name) + .into(InputField.withNameOrId("name")), + Click.on(Button.withText("Update")) + ); + } + + @Then("{actor} should see the specialty {string} on the list of specialties") + public void shouldSeeTheSpecialty(Actor actor, String name) { + actor.attemptsTo( + Ensure.thatAmongst(InputField.withNameOrId("spec_name")) + .anyMatch(name + " should be on the list", + (field) -> field.getValue() + .equals(name) + ) + ); + } +} diff --git a/src/test/resources/features/search/search_by_keyword.feature b/src/test/resources/features/search/search_by_keyword.feature deleted file mode 100644 index e6475de..0000000 --- a/src/test/resources/features/search/search_by_keyword.feature +++ /dev/null @@ -1,13 +0,0 @@ -Feature: Search by keyword - - @green - Scenario: Searching for 'green' - Given Sergey is researching things on the internet - When he looks up "green" - Then he should see information about "green" - - @red - Scenario: Searching for 'red' - Given Sergey is researching things on the internet - When he looks up "red" - Then he should see information about "red" diff --git a/src/test/resources/features/veterinarian/manage_pet_types.feature b/src/test/resources/features/veterinarian/manage_pet_types.feature new file mode 100644 index 0000000..1b87c49 --- /dev/null +++ b/src/test/resources/features/veterinarian/manage_pet_types.feature @@ -0,0 +1,16 @@ +Feature: Manage pet types + The veterinarian wants to be able to add, edit, and delete pet types. + + Scenario: Add new pet type + Given a system operator named "Jane" is looking at the pet types page + And she found the following pet types exist: + | cat | + | dog | + | lizard | + | snake | + | bird | + | hamster | + When she adds a new pet type named "turtle" + Then she should see the pet type "turtle" on the list of pet types + + # TODO: Add a scenario to "Edit the last pet type" \ No newline at end of file diff --git a/src/test/resources/features/veterinarian/manage_specialties.feature b/src/test/resources/features/veterinarian/manage_specialties.feature new file mode 100644 index 0000000..a5692d4 --- /dev/null +++ b/src/test/resources/features/veterinarian/manage_specialties.feature @@ -0,0 +1,14 @@ +Feature: Manage specialties + The veterinarian wants to be able to add, edit, and delete specialties. + + Scenario: Add new specialty + Given a system operator named "John" is looking at the specialties page + When he adds a new specialty called "cardiology" + Then he should see the specialty "cardiology" on the list of specialties + + Scenario: Edit the first specialty + Given a system operator named "John" is looking at the specialties page + When he edits the first specialty to "snake oil" + Then he should see the specialty "snake oil" on the list of specialties + + # TODO: Add a scenario to "Add new specialty and remove it immediately" \ No newline at end of file diff --git a/src/test/resources/junit-platform.properties b/src/test/resources/junit-platform.properties index c36f2bb..3105dc4 100644 --- a/src/test/resources/junit-platform.properties +++ b/src/test/resources/junit-platform.properties @@ -1,4 +1,4 @@ -cucumber.execution.parallel.enabled=true +cucumber.execution.parallel.enabled=false cucumber.execution.parallel.config.strategy=fixed cucumber.execution.parallel.config.fixed.parallelism=4 cucumber.execution.parallel.config.fixed.max-pool-size=4 -- GitLab