├── .gitignore
├── README.md
├── docker-compose.yml
├── docker-images-build.sh
├── docker
├── README.md
├── tomcat-users.xml
├── tomcat7-jdk8.dockerfile
└── ui-tests.dockerfile
├── pippo-demo.war
├── pom.xml
├── restart.sh
├── serenity.properties
├── src
└── main
│ ├── java
│ └── ro
│ │ └── fortsoft
│ │ └── pippo
│ │ └── demo
│ │ └── bdd
│ │ ├── config
│ │ ├── Locators.java
│ │ └── Messages.java
│ │ ├── cucumber
│ │ ├── ContactsStepDefs.java
│ │ ├── LoginStepDefs.java
│ │ └── hook
│ │ │ └── CucumberHooks.java
│ │ ├── pages
│ │ ├── ContactsPage.java
│ │ └── LoginPage.java
│ │ ├── runner
│ │ └── PippoCrudDemoRunner.java
│ │ └── serenity
│ │ ├── ContactsSteps.java
│ │ └── LoginSteps.java
│ └── resources
│ ├── features
│ ├── contacts
│ │ └── contacts.feature
│ └── login
│ │ └── login.feature
│ ├── locators.conf
│ ├── messages.conf
│ └── simplelogger.properties
├── start.sh
└── stop.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | out
3 | *.iml
4 | .idea
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BDD testing - Cucumber and Serenity setup running on docker containers
2 | BDD testing of [pippo](http://www.pippo.ro/) [demo angular-crud-app](https://github.com/decebals/pippo-demo/tree/master/pippo-demo-crudng) with [Cucumber](https://cucumber.io/docs/reference/jvm#java) and [Serenity](http://thucydides.info/docs/serenity-staging/)
3 |
4 | Sources for the blog posts [Using docker for orchestrating a reusable BDD web testing setup with Selenium grid - Part I](http://balamaci.ro/using-docker-and-docker-compose-for-orchestrating-a-full-bdd/)
5 | and [BDD web testing setup - Docker, Cucumber and Serenity - Part II](http://balamaci.ro/orchestrating-a-reusable-bdd-web-testing-setup-part-ii/)
6 |
7 | ## Prerequisites
8 | - Install Docker and [Docker-compose](http://docs.docker.com/compose/install/)
9 | - Clone this repository
10 | ````bash
11 | $ git clone git@github.com:balamaci/blog-ui-bdd-testing.git
12 | ````
13 | - Create the docker images locally
14 | There is a one time run of
15 | ````bash
16 | $ ./docker-images-build.sh
17 | ````
18 | which will create the docker images locally. Normally you'd have them pushed to a repository, but I wanted to show there are no "hidden tricks", or you can use them as example to build your own. So instead we use the script to build locally the required images.
19 |
20 | ## Code run
21 | To run the bdd tests anytime just do
22 | ````bash
23 | $ ./restart.sh
24 | ````
25 |
26 | which basically does **docker-compose run uitests mvn clean verify**
27 |
28 |
29 | This would execute the **Cucumber tests** and produce the **Serenity reports** which can be accessed at **./target/site/index.html**
30 |
31 |
32 | [](http://balamaci.ro/static/serenity/index.html)
33 |
34 |
35 |
36 | We included **pippo-demo.war** -the application we run our tests against- on the repo to have a single command to run the job. Normally you'd have it provided by another build job that would trigger the testing job.
37 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | tomcat:
2 | image: balamaci/tomcat7-jdk8
3 | ports:
4 | - 8080:8080
5 | volumes:
6 | - ./out/tomcat:/opt/tomcat/logs
7 |
8 | hub:
9 | image: selenium/hub:2.48.1
10 | expose:
11 | - 4444:4444
12 | links:
13 | - tomcat
14 |
15 | nodeff:
16 | image: selenium/node-firefox:2.48.1
17 | volumes:
18 | - ./out/ff/e2e/uploads:/e2e/uploads
19 | links:
20 | - hub
21 | - tomcat
22 |
23 | uitests:
24 | image: balamaci/ui-tests
25 | volumes:
26 | - .:/usr/src/app
27 | - ~/.m2:/root/.m2
28 | links:
29 | - tomcat
30 | - hub
31 | - nodeff
32 |
--------------------------------------------------------------------------------
/docker-images-build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cd docker
4 |
5 | docker build --rm -t balamaci/oracle-jdk8 -f oracle-jdk8.dockerfile .
6 |
7 | docker build --rm -t balamaci/tomcat7-jdk8 -f tomcat7-jdk8.dockerfile .
8 |
9 | docker build --rm -t balamaci/mvn3-jdk8 -f mvn3-jdk8.dockerfile .
10 |
11 | docker build --rm -t balamaci/ui-tests -f ui-tests.dockerfile .
--------------------------------------------------------------------------------
/docker/README.md:
--------------------------------------------------------------------------------
1 | # Docker file recipes
2 | Contains all the necesary dockerfiles which are required to run the project.
3 | They can be used as example to inspire to build your own images.
4 | Otherwise some of them might already be available on the docker repo.
5 |
6 | The script **docker-images-build.sh** can be used to build locally the container images.
7 |
--------------------------------------------------------------------------------
/docker/tomcat-users.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/docker/tomcat7-jdk8.dockerfile:
--------------------------------------------------------------------------------
1 | FROM maven:3.3.3-jdk-8
2 | ENV TOMCAT_VERSION 7.0.63
3 |
4 | VOLUME ["/var/log/tomcat7"]
5 |
6 | # Get and Unpack Tomcat
7 | RUN wget http://archive.apache.org/dist/tomcat/tomcat-7/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz -O /tmp/catalina.tar.gz && \
8 | tar xzf /tmp/catalina.tar.gz -C /opt && \
9 | ln -s /opt/apache-tomcat-${TOMCAT_VERSION}/ /opt/tomcat && \
10 | rm /tmp/catalina.tar.gz
11 |
12 | ADD tomcat-users.xml /opt/tomcat/conf/
13 | CMD CATALINA_BASE=/opt/tomcat CATALINA_HOME=/opt/tomcat /opt/tomcat/bin/catalina.sh run
14 | EXPOSE 8080
--------------------------------------------------------------------------------
/docker/ui-tests.dockerfile:
--------------------------------------------------------------------------------
1 | FROM maven:3.3.3-jdk-8
2 |
3 | VOLUME ["/usr/src/app"]
4 | WORKDIR /usr/src/app
5 |
--------------------------------------------------------------------------------
/pippo-demo.war:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/balamaci/blog-ui-bdd-testing/2860518acd37b8b5f30bd960c68824c471c44291/pippo-demo.war
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | 4.0.0
7 | ro.fortsoft.pippo.demo.bdd
8 | pippo-bdd
9 | jar
10 | 1.0-SNAPSHOT
11 | BDD testing of pippo demo with Cucumber and Serenity
12 |
13 |
14 | tomcat
15 | pippo
16 | pippo-demo.war
17 |
18 | 1.7.7
19 | 1.3.0
20 | 1.1.14
21 | 1.1.1
22 | 1.7.0
23 |
24 |
25 |
26 |
27 |
28 | com.typesafe
29 | config
30 | ${typesafe.config}
31 |
32 |
33 |
34 |
35 | org.slf4j
36 | slf4j-simple
37 | ${slf4j.version}
38 |
39 |
40 |
41 |
42 |
43 | net.serenity-bdd
44 | serenity-core
45 | ${serenity.core.version}
46 |
47 |
48 |
49 | net.serenity-bdd
50 | serenity-cucumber
51 | ${serenity.cucumber.version}
52 |
53 |
54 |
55 | org.assertj
56 | assertj-core
57 | ${assertj-core.version}
58 |
59 |
60 |
61 |
62 | src/main/java
63 |
64 |
65 |
66 | true
67 | org.apache.maven.plugins
68 | maven-compiler-plugin
69 | 3.1
70 |
71 | 1.8
72 | 1.8
73 | UTF-8
74 | true
75 | true
76 |
77 |
78 |
79 |
80 | org.codehaus.cargo
81 | cargo-maven2-plugin
82 | 1.4.11
83 |
84 |
85 | tomcat7x
86 | remote
87 |
88 |
89 | runtime
90 |
91 | ${tomcat.hostname}
92 | 8080
93 | admin
94 | admin
95 |
96 |
97 |
98 | remote
99 |
100 |
101 |
102 | war
103 | ${war.file.location}
104 |
105 | ${webapp.deploy.context}
106 |
107 |
108 |
109 |
110 |
111 |
112 | war-deploy
113 | pre-integration-test
114 |
115 | deploy
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | org.apache.maven.plugins
124 | maven-surefire-plugin
125 | 2.18
126 |
127 | true
128 |
129 |
130 |
131 | maven-failsafe-plugin
132 | 2.18
133 |
134 |
135 | **/runner/*.java
136 |
137 | true
138 |
139 |
140 |
141 |
142 | integration-test
143 | verify
144 |
145 |
146 |
147 |
148 |
149 | net.serenity-bdd.maven.plugins
150 | serenity-maven-plugin
151 | ${serenity.core.version}
152 |
153 |
154 | serenity-reports
155 | post-integration-test
156 |
157 | aggregate
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/restart.sh:
--------------------------------------------------------------------------------
1 | ./stop.sh
2 | ./start.sh
3 |
--------------------------------------------------------------------------------
/serenity.properties:
--------------------------------------------------------------------------------
1 | serenity.project.name = Pippo CRUD Demo Functional Tests
2 |
3 | webdriver.remote.driver = firefox
4 |
5 | webdriver.base.url=http://tomcat:8080/pippo/
6 | webdriver.remote.url = http://hub:4444/wd/hub
7 |
8 | # Only for firefox
9 | #webdriver.load.strategy = unstable
10 |
11 | webdriver.timeouts.implicitlywait = 5000
12 | webdriver.wait.for.timeout = 10000
13 |
14 | serenity.browser.width = 1280
15 | serenity.resized.image.width = 1024
16 | json.pretty.printing = true
17 | story.timeout.in.secs = 3600
18 | serenity.console.headings = normal
19 |
20 | serenity.step.delay = 500
21 | serenity.timeout = 10
22 |
23 | serenity.use.unique.browser = true
24 | serenity.take.screenshots = BEFORE_AND_AFTER_EACH_STEP
25 | serenity.requirements.dir = src/main/resources/features
26 | serenity.requirement.types = epic,story,feature
27 | serenity.dry.run = false
28 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/config/Locators.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.config;
2 |
3 | import com.typesafe.config.Config;
4 | import com.typesafe.config.ConfigFactory;
5 |
6 | /**
7 | * @author sbalamaci
8 | */
9 | public class Locators {
10 |
11 | private static Config locatorsConfig = ConfigFactory.load("locators");
12 |
13 | private Locators() {
14 | }
15 |
16 | public static String getValue(String key) {
17 | return locatorsConfig.getString(key);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/config/Messages.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.config;
2 |
3 | import com.typesafe.config.Config;
4 | import com.typesafe.config.ConfigFactory;
5 |
6 | /**
7 | * @author Serban Balamaci
8 | */
9 | public class Messages {
10 |
11 | private static Config messagesConfig = ConfigFactory.load("messages");
12 |
13 | private Messages() {
14 | }
15 |
16 | public static String getValue(String key) {
17 | return messagesConfig.getString(key);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/cucumber/ContactsStepDefs.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.cucumber;
2 |
3 | import cucumber.api.java.en.Given;
4 | import cucumber.api.java.en.Then;
5 | import cucumber.api.java.en.When;
6 | import net.thucydides.core.annotations.Steps;
7 | import ro.fortsoft.pippo.demo.bdd.serenity.ContactsSteps;
8 |
9 | /**
10 | * @author sbalamaci
11 | */
12 | public class ContactsStepDefs {
13 |
14 | @Steps
15 | private ContactsSteps contactsSteps;
16 |
17 | @Given("^(?:I try to access|I open) the 'Contacts' page$")
18 | public void navigate_contacts_page() {
19 | contactsSteps.openContactsPage();
20 | }
21 |
22 | @When("^I click on 'Add'$")
23 | public void click_on_add() {
24 | contactsSteps.clickOnAdd();
25 | }
26 |
27 | @Then("^I click 'Submit' button$")
28 | public void click_submit() {
29 | contactsSteps.clickOnSubmit();
30 | }
31 |
32 | @When("^I enter '(.*)' '(.*)' and '(.*)' in the Edit panel$")
33 | public void fill_contact_info(String name, String phone, String address) {
34 | contactsSteps.fillContactInfo(name, phone, address);
35 | }
36 |
37 | @Then("^I should see the 'Contacts' page$")
38 | public void is_contacts_page() {
39 | contactsSteps.isContactsPage();
40 | }
41 |
42 |
43 | @Then("^I should see '(.*)' in the list of contacts$")
44 | public void contact_name_is_present_in_contacts_table(String name) {
45 | contactsSteps.isContactWithNamePresentInList(name);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/cucumber/LoginStepDefs.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.cucumber;
2 |
3 | import cucumber.api.java.en.Given;
4 | import cucumber.api.java.en.Then;
5 | import cucumber.api.java.en.When;
6 | import net.thucydides.core.annotations.Steps;
7 | import ro.fortsoft.pippo.demo.bdd.serenity.ContactsSteps;
8 | import ro.fortsoft.pippo.demo.bdd.serenity.LoginSteps;
9 |
10 | /**
11 | * @author sbalamaci
12 | */
13 | public class LoginStepDefs {
14 |
15 | @Steps
16 | private LoginSteps loginSteps;
17 | private ContactsSteps contactsSteps;
18 |
19 |
20 | @When("^I login with user '(.*)' and with password '(.*)'$")
21 | public void login_user(String username, String password) {
22 | loginSteps.enterUsernameAndPassword(username, password);
23 | loginSteps.clickOnSubmit();
24 | }
25 |
26 | @Then("^I see the 'Login' page$")
27 | public void login_page_is_shown() {
28 | loginSteps.isLoginPage();
29 | }
30 |
31 | @Then("^I should see a failed login warning message with key '(.*)'$")
32 | public void failed_login_warn_message_is_shown(String key) {
33 | loginSteps.warnMessageWithKeyIsShown(key);
34 | }
35 |
36 |
37 | @Given("^I am logged in as admin$")
38 | public void login_admin_user() {
39 | loginSteps.openLoginPage();
40 | loginSteps.enterUsernameAndPassword("admin", "admin");
41 | loginSteps.clickOnSubmit();
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/cucumber/hook/CucumberHooks.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.cucumber.hook;
2 |
3 | import cucumber.api.java.Before;
4 | import net.thucydides.core.annotations.ManagedPages;
5 | import net.thucydides.core.pages.Pages;
6 |
7 | /**
8 | * @author sbalamaci
9 | */
10 | public class CucumberHooks {
11 |
12 | @ManagedPages
13 | private Pages pages;
14 |
15 | @Before
16 | public void openBrowser() {
17 | // Serenity.useFirefoxProfile(customFirefoxProfile());
18 | /*
19 | pages.getConfiguration().getEnvironmentVariables()
20 | .setProperty(ThucydidesSystemProperty.WEBDRIVER_BASE_URL.getPropertyName(),
21 | "http://tomcat:8080/pippo/");
22 | */
23 | pages.getDriver().manage().deleteAllCookies();
24 | pages.getDriver().manage().window().maximize();
25 | }
26 |
27 |
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/pages/ContactsPage.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.pages;
2 |
3 | import net.serenitybdd.core.pages.PageObject;
4 | import net.thucydides.core.annotations.DefaultUrl;
5 | import org.openqa.selenium.By;
6 | import org.openqa.selenium.WebElement;
7 | import ro.fortsoft.pippo.demo.bdd.config.Locators;
8 |
9 | /**
10 | * @author sbalamaci
11 | */
12 | @DefaultUrl("http://localhost/contacts")
13 | public class ContactsPage extends PageObject {
14 |
15 | public void clickOnAddContactLink() {
16 | WebElement lnkAdd = find(By.id(Locators.getValue("contacts.lnkAdd.id")));
17 | clickOn(lnkAdd);
18 | }
19 |
20 | public void fillContactInfo(String name, String phone, String address) {
21 | WebElement txtName = find(By.name(Locators.getValue("contacts.txtName.name")));
22 | WebElement txtPhone = find(By.name(Locators.getValue("contacts.txtPhone.name")));
23 | WebElement txtAddress = find(By.name(Locators.getValue("contacts.txtAddress.name")));
24 |
25 | typeInto(txtName, name);
26 | typeInto(txtPhone, phone);
27 | typeInto(txtAddress, address);
28 | }
29 |
30 | public void clickSubmit() {
31 | WebElement btnSubmit = find(By.id(Locators.getValue("contacts.btnSubmit.id")));
32 | clickOn(btnSubmit);
33 | }
34 |
35 | public String getContactsTableSource() {
36 | WebElement tblContacts = find(By.id(Locators.getValue("contacts.table.id")));
37 | return tblContacts.getText();
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/pages/LoginPage.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.pages;
2 |
3 | import net.serenitybdd.core.annotations.findby.By;
4 | import net.serenitybdd.core.pages.PageObject;
5 | import net.thucydides.core.annotations.DefaultUrl;
6 | import org.openqa.selenium.WebElement;
7 | import ro.fortsoft.pippo.demo.bdd.config.Locators;
8 |
9 | /**
10 | * @author sbalamaci
11 | */
12 | @DefaultUrl("http://localhost/login")
13 | public class LoginPage extends PageObject {
14 |
15 | public void enterUsernameAndPassword(String username, String password) {
16 | WebElement txtUsername = find(By.name(Locators.getValue("login.txtUsername.name")));
17 | WebElement txtPassword = find(By.name(Locators.getValue("login.txtPassword.name")));
18 |
19 | typeInto(txtUsername, username);
20 | typeInto(txtPassword, password);
21 | }
22 |
23 | public void clickOnSubmit() {
24 | WebElement btnSubmit = find(By.name(Locators.getValue("login.btnSubmit.name")));
25 | clickOn(btnSubmit);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/runner/PippoCrudDemoRunner.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.runner;
2 |
3 | import cucumber.api.CucumberOptions;
4 | import net.serenitybdd.cucumber.CucumberWithSerenity;
5 | import org.junit.runner.RunWith;
6 |
7 | /**
8 | * @author sbalamaci
9 | */
10 | @RunWith(CucumberWithSerenity.class)
11 | @CucumberOptions(
12 | format = { "pretty", "html:target/pippo", "json:target/cucumber.json" },
13 | features = {"src/main/resources/features/"},
14 | glue = "ro.fortsoft.pippo.demo.bdd.cucumber")
15 | public class PippoCrudDemoRunner {
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/serenity/ContactsSteps.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.serenity;
2 |
3 | import net.thucydides.core.steps.ScenarioSteps;
4 | import ro.fortsoft.pippo.demo.bdd.pages.ContactsPage;
5 |
6 | import static org.assertj.core.api.Assertions.assertThat;
7 |
8 | /**
9 | * @author sbalamaci
10 | */
11 | public class ContactsSteps extends ScenarioSteps {
12 |
13 | private ContactsPage contactsPage;
14 |
15 | public void openContactsPage() {
16 | contactsPage.open();
17 | }
18 |
19 | public void isContactsPage() {
20 | assertThat(getDriver().getTitle()).startsWith("Contacts");
21 | }
22 |
23 | public void clickOnAdd() {
24 | contactsPage.clickOnAddContactLink();
25 | }
26 |
27 | public void fillContactInfo(String name, String phone, String address) {
28 | contactsPage.fillContactInfo(name, phone, address);
29 | }
30 |
31 | public void clickOnSubmit() {
32 | contactsPage.clickSubmit();
33 | }
34 |
35 | public void isContactWithNamePresentInList(String name) {
36 | assertThat(contactsPage.getContactsTableSource()).contains(name);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/ro/fortsoft/pippo/demo/bdd/serenity/LoginSteps.java:
--------------------------------------------------------------------------------
1 | package ro.fortsoft.pippo.demo.bdd.serenity;
2 |
3 | import net.thucydides.core.annotations.Step;
4 | import net.thucydides.core.steps.ScenarioSteps;
5 | import ro.fortsoft.pippo.demo.bdd.config.Messages;
6 | import ro.fortsoft.pippo.demo.bdd.pages.LoginPage;
7 |
8 | import static org.assertj.core.api.Assertions.assertThat;
9 |
10 | /**
11 | * @author sbalamaci
12 | */
13 | public class LoginSteps extends ScenarioSteps {
14 |
15 | private LoginPage loginPage;
16 |
17 | @Step
18 | public void enterUsernameAndPassword(String username, String password) {
19 | loginPage.enterUsernameAndPassword(username, password);
20 | }
21 |
22 | @Step
23 | public void clickOnSubmit() {
24 | loginPage.clickOnSubmit();
25 | }
26 |
27 | @Step
28 | public void openLoginPage() {
29 | loginPage.open();
30 | }
31 |
32 | @Step
33 | public void isLoginPage() {
34 | assertThat(loginPage.getTitle()).startsWith("Login");
35 | }
36 |
37 | @Step
38 | public void warnMessageWithKeyIsShown(String key) {
39 | assertThat(loginPage.getDriver().getPageSource()).contains(Messages.getValue(key));
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/src/main/resources/features/contacts/contacts.feature:
--------------------------------------------------------------------------------
1 | @ui
2 | Feature: Create Contacts functionality
3 |
4 | Background:
5 | Given I am logged in as admin
6 | And I open the 'Contacts' page
7 |
8 | Scenario: I am warned when trying to create a new contact with a short phone number
9 | When I click on 'Add'
10 | And I enter 'TestUser' '+40723' and 'Some address' in the Edit panel
11 | Then I should see a warning that the phone number is too short
12 | And The 'Submit' button is disabled
13 |
14 | Scenario Outline: I can add a new contact
15 | When I click on 'Add'
16 | And I enter '' '' and '' in the Edit panel
17 | And I click 'Submit' button
18 | Then I should see '' in the list of contacts
19 |
20 | Examples:
21 | | name | address | phone |
22 | | Serban | Str. Some street nr. 2 | +4077235653 |
23 | | Decebal | Str. Burebista nr. 3 | +4077235655 |
24 |
25 |
--------------------------------------------------------------------------------
/src/main/resources/features/login/login.feature:
--------------------------------------------------------------------------------
1 | @ui
2 | Feature: Login functionality
3 | Unauthorized users first need to login into the application.
4 | Users who enter right credentials should be able to login into the application.
5 | Users who enter wrong credentials are shown an error message.
6 |
7 | Background:
8 | Given I try to access the 'Contacts' page
9 | And I see the 'Login' page
10 |
11 | Scenario: Entering valid credentials I am able to login and see 'Contacts' page
12 | When I login with user 'admin' and with password 'admin'
13 | Then I should see the 'Contacts' page
14 |
15 | Scenario: Entering invalid credentials I am warned that login has failed
16 | When I login with user 'hacker' and with password ''
17 | Then I should see a failed login warning message with key 'login.warnLoginFailed'
--------------------------------------------------------------------------------
/src/main/resources/locators.conf:
--------------------------------------------------------------------------------
1 | login {
2 | txtUsername.name=username
3 | txtPassword.name=password
4 | btnSubmit.name=login
5 | }
6 |
7 | contacts {
8 | txtName.name=name
9 | txtPhone.name=phone
10 | txtAddress.name=address
11 | lnkAdd.id=addContactButton
12 |
13 | btnSubmit.id=submit
14 | table.id=contacts
15 | }
--------------------------------------------------------------------------------
/src/main/resources/messages.conf:
--------------------------------------------------------------------------------
1 | login {
2 | warnLoginFailed=Authentication failed
3 | }
4 |
5 | contacts {
6 |
7 | }
--------------------------------------------------------------------------------
/src/main/resources/simplelogger.properties:
--------------------------------------------------------------------------------
1 | # SLF4J's SimpleLogger configuration file
2 | # Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err.
3 |
4 | # Default logging detail level for all instances of SimpleLogger.
5 | # Must be one of ("trace", "debug", "info", "warn", or "error").
6 | # If not specified, defaults to "info".
7 | org.slf4j.simpleLogger.defaultLogLevel=warn
8 |
9 | # Logging detail level for a SimpleLogger instance named "xxxxx".
10 | # Must be one of ("trace", "debug", "info", "warn", or "error").
11 | # If not specified, the default logging detail level is used.
12 | #org.slf4j.simpleLogger.log.xxxxx=
13 | org.slf4j.simpleLogger.log.ro.fortsoft.pippo.demo.bdd=info
14 |
15 | # Set to true if you want the current date and time to be included in output messages.
16 | # Default is false, and will output the number of milliseconds elapsed since startup.
17 | #org.slf4j.simpleLogger.showDateTime=false
18 | org.slf4j.simpleLogger.showDateTime=true
19 |
20 | # The date and time format to be used in the output messages.
21 | # The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.
22 | # If the format is not specified or is invalid, the default format is used.
23 | # The default format is yyyy-MM-dd HH:mm:ss:SSS Z.
24 | #org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z
25 | org.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss
26 |
27 | # Set to true if you want to output the current thread name.
28 | # Defaults to true.
29 | #org.slf4j.simpleLogger.showThreadName=true
30 |
31 | # Set to true if you want the Logger instance name to be included in output messages.
32 | # Defaults to true.
33 | #org.slf4j.simpleLogger.showLogName=true
34 |
35 | # Set to true if you want the last component of the name to be included in output messages.
36 | # Defaults to false.
37 | #org.slf4j.simpleLogger.showShortLogName=false
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | docker-compose run uitests mvn clean verify
2 |
--------------------------------------------------------------------------------
/stop.sh:
--------------------------------------------------------------------------------
1 | docker-compose stop
2 | docker-compose rm -f
3 |
--------------------------------------------------------------------------------