diff --git a/.travis.yml b/.travis.yml
index c0f28cfa4..351fd2b0c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,2 +1,33 @@
language: java
+sudo: false
+install: true
+
+services:
+ - docker
+
+addons:
+ sonarcloud:
+ organization: "bpsdproject"
+ token:
+ secure: "FKHLAA1VC6XvrJTDFXwh7IvHAgX+hHkzuGmiOJ9RvguTkP8yQTQqczQA0QFUaCKoOXLQf7n1Xadx60vKDxk1FQS4GxhvB1n9muvhjkLOXstpRjKEBL/t3CgVeIYPdf676lT/vED2yeFmTC0BcC82k2h8dNpBpr2c/iRsHriiyf8NOOM9XO6sbDfPPGYhTzkuBRhplVZ6723z5KaHDvSgjQmT/dlIZkY00fqyVPI20JZqvScbR0/8QjED8jWtnlZpzU02lIrpkcIJF2gS4OGkucE1GBvJtkAejm5V2g++mdj3B+ja4x2rZmLmAhOVV2PzRatMSrEyoSCRpjXMf39WaTlehaii2foWPvj+CTl4iO4ApdVluFufS5EuPknJ3/pOQVAilR0qad3NBokUGCnfGhAqo06AA0aeLb05A3nfhT/CeOPEklwpkWNHNG6B4XWkNUH54WemqvmDvUjPspSbFlU3RBwjVcacj4Dyuh4eo48E/+bYnoIhaAZiyh/SXqrIx9Wh0COxYv1tgcqJ/xbDtJf3CZdjGZfKCpC3OUCliRTHtKQrzxQxai4oTlTtGTWhxm81BIOStRY0IgkTGvMiymv91wcWN6Q937D4CsRGJ7O4ZKWeqPXCmntVVqEiWd5av2Lpnv7W2QnajkcNZ4UyGtH3mzo4OykKGc9EV9fcu64="
+
jdk: oraclejdk8
+
+install:
+ - docker-compose build
+
+before_script:
+ - docker-compose up -d
+
+script:
+ - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent test -Dskip.failsafe.tests sonar:sonar -Dsonar.pitest.mode=reuseReport
+ - docker exec springpetclinic_pet-clinic_1 mvn verify -Dskip.surefire.tests -q --batch-mode
+
+after_script:
+ - docker-compose stop
+ - docker-compose rm -f
+
+cache:
+ directories:
+ - '$HOME/.m2/repository'
+ - '$HOME/.sonar/cache'
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..1f2d91493
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,18 @@
+FROM maven:latest
+
+# Set the workdir
+WORKDIR /app
+
+# Copy the source to the container
+COPY . .
+
+# Build the project
+RUN mvn package -Dskip.failsafe.tests -q --batch-mode && \
+mvn org.pitest:pitest-maven:mutationCoverage -q --batch-mode
+
+# Copy and make the jar executable
+RUN sh -c 'mkdir dist/ && cp -a target/. dist/ && touch dist/spring-petclinic-*.jar'
+
+#Start the project
+ENV JAVA_OPTS=""
+ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar dist/spring-petclinic-*.jar" ]
diff --git a/docker-compose.yml b/docker-compose.yml
index 1631ec9fa..a3274a6d5 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,9 +1,23 @@
-mysql:
- image: mysql
- ports:
- - "3306:3306"
- environment:
- - MYSQL_ROOT_PASSWORD=root
- - MYSQL_DATABASE=test
- volumes:
- - "./conf.d:/etc/mysql/conf.d:ro"
\ No newline at end of file
+version: '2'
+services:
+ pet-clinic:
+ build: .
+ ports:
+ - "8080:8080"
+ links:
+ - selenium
+# - mysql:mysql
+# mysql:
+# image: mysql
+# ports:
+# - "3306:3306"
+# environment:
+# - MYSQL_ROOT_PASSWORD=root
+# - MYSQL_DATABASE=test
+# volumes:
+# - "./conf.d:/etc/mysql/conf.d:ro"
+ selenium:
+ image: selenium/standalone-firefox
+ shm_size: 2g
+ ports:
+ - "4444:4444"
diff --git a/pom.xml b/pom.xml
index ff677d097..c0f1dc7a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,229 +1,275 @@
- 4.0.0
- org.springframework.samples
- spring-petclinic
- 1.5.1
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ 4.0.0
+ org.springframework.samples.bpsd
+ spring-petclinic
+ 1.5.1
-
- org.springframework.boot
- spring-boot-starter-parent
- 1.5.1.RELEASE
-
- petclinic
-
-
-
-
- 1.8
- UTF-8
- UTF-8
-
-
- 3.3.6
- 1.11.4
- 2.2.4
- 1.8.0
-
- 3.0.2.RELEASE
-
- 2.7
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
- org.springframework.boot
- spring-boot-starter-cache
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-thymeleaf
-
-
- nz.net.ultraq.thymeleaf
- thymeleaf-layout-dialect
-
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
-
-
- org.hsqldb
- hsqldb
- runtime
-
-
- mysql
- mysql-connector-java
- runtime
-
-
-
-
- javax.cache
- cache-api
-
-
- org.ehcache
- ehcache
-
-
-
-
- org.webjars
- webjars-locator
-
-
- org.webjars
- jquery
- ${webjars-jquery.version}
-
-
- org.webjars
- jquery-ui
- ${webjars-jquery-ui.version}
-
-
- org.webjars
- bootstrap
- ${webjars-bootstrap.version}
-
-
-
-
- org.springframework.boot
- spring-boot-devtools
- runtime
-
-
-
-
-
-
+
org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
- build-info
-
-
-
- ${project.build.sourceEncoding}
- ${project.reporting.outputEncoding}
- ${maven.compiler.source}
- ${maven.compiler.target}
-
-
-
-
-
-
- org.codehaus.mojo
- cobertura-maven-plugin
- ${cobertura.version}
-
-
-
-
-
-
- clean
- check
-
-
-
-
+ spring-boot-starter-parent
+ 1.5.1.RELEASE
+
+ petclinic
-
-
- pl.project13.maven
- git-commit-id-plugin
-
-
-
- revision
-
-
-
-
- true
- yyyy-MM-dd'T'HH:mm:ssZ
- true
- ${project.build.outputDirectory}/git.properties
-
- false
-
-
+
-
- ro.isdc.wro4j
- wro4j-maven-plugin
- ${wro4j.version}
-
-
- generate-resources
-
- run
-
-
-
-
- ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory
- ${project.build.directory}/classes/static/resources/css
- ${basedir}/src/main/wro/wro.xml
- ${basedir}/src/main/wro/wro.properties
- ${basedir}/src/main/less
-
-
-
+
+ 1.8
+ UTF-8
+ UTF-8
+
+
+ 3.3.6
+ 1.11.4
+ 2.2.4
+ 1.8.0
+
+ 3.0.2.RELEASE
+
+ 2.7
+
+ 3.4.0
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ nz.net.ultraq.thymeleaf
+ thymeleaf-layout-dialect
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.hsqldb
+ hsqldb
+ runtime
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+
+
+ javax.cache
+ cache-api
+
+
+ org.ehcache
+ ehcache
+
+
+
+
+ org.webjars
+ webjars-locator
+
+
+ org.webjars
+ jquery
+ ${webjars-jquery.version}
+
+
+ org.webjars
+ jquery-ui
+ ${webjars-jquery-ui.version}
+
+
org.webjars
bootstrap
${webjars-bootstrap.version}
-
-
-
-
-
-
-
-
-
- org.codehaus.mojo
- cobertura-maven-plugin
- ${cobertura.version}
-
-
- html
-
-
-
-
-
-
+
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+
+
+
+
+ org.seleniumhq.selenium
+ selenium-java
+ ${selenium-java.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ ${skip.surefire.tests}
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ ${skip.failsafe.tests}
+
+
+
+ run-integration-tests
+ integration-test
+
+ integration-test
+ verify
+
+
+
+
+
+ org.pitest
+ pitest-maven
+ 1.2.0
+
+
+ XML
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+ build-info
+
+
+
+ ${project.build.sourceEncoding}
+ ${project.reporting.outputEncoding}
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
+
+
+
+
+
+ org.codehaus.mojo
+ cobertura-maven-plugin
+ ${cobertura.version}
+
+
+
+
+
+
+ clean
+ check
+
+
+
+
+
+
+
+ pl.project13.maven
+ git-commit-id-plugin
+
+
+
+ revision
+
+
+
+
+ true
+ yyyy-MM-dd'T'HH:mm:ssZ
+ true
+ ${project.build.outputDirectory}/git.properties
+
+ false
+
+
+
+
+ ro.isdc.wro4j
+ wro4j-maven-plugin
+ ${wro4j.version}
+
+
+ generate-resources
+
+ run
+
+
+
+
+ ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory
+ ${project.build.directory}/classes/static/resources/css
+ ${basedir}/src/main/wro/wro.xml
+ ${basedir}/src/main/wro/wro.properties
+ ${basedir}/src/main/less
+
+
+
+ org.webjars
+ bootstrap
+ ${webjars-bootstrap.version}
+
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ cobertura-maven-plugin
+ ${cobertura.version}
+
+
+ html
+
+
+
+
+
+
diff --git a/sonar-project.properties b/sonar-project.properties
index d84ed7c2d..7ca4b7b7c 100755
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -10,4 +10,4 @@ sonar.sources=src
sonar.language=java
# Encoding of the source files
-sonar.sourceEncoding=UTF-8
\ No newline at end of file
+sonar.sourceEncoding=UTF-8
diff --git a/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java b/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
index 224c326c7..5265770dc 100644
--- a/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
+++ b/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
@@ -21,14 +21,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* PetClinic Spring Boot Application.
- *
+ *
* @author Dave Syer
*
*/
@SpringBootApplication
public class PetClinicApplication {
- public static void main(String[] args) throws Exception {
+ public static void main(String[] args) {
SpringApplication.run(PetClinicApplication.class, args);
}
diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java
index f6fcae7ac..e471b5c8a 100644
--- a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java
@@ -126,13 +126,13 @@ public class Owner extends Person {
* @param name to test
* @return true if pet name is already in use
*/
- public Pet getPet(String name, boolean ignoreNew) {
- name = name.toLowerCase();
+ public Pet getPet(final String name, final boolean ignoreNew) {
+ String lowerCaseName = name.toLowerCase();
for (Pet pet : getPetsInternal()) {
if (!ignoreNew || !pet.isNew()) {
String compName = pet.getName();
compName = compName.toLowerCase();
- if (compName.equals(name)) {
+ if (compName.equals(lowerCaseName)) {
return pet;
}
}
diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java
index ef3169b70..5432398f6 100644
--- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java
+++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java
@@ -78,7 +78,7 @@ class OwnerController {
}
@RequestMapping(value = "/owners", method = RequestMethod.GET)
- public String processFindForm(Owner owner, BindingResult result, Map model) {
+ public String processFindForm(final Owner owner, final BindingResult result, final Map model) {
// allow parameterless GET request for /owners to return all records
if (owner.getLastName() == null) {
@@ -93,8 +93,8 @@ class OwnerController {
return "owners/findOwners";
} else if (results.size() == 1) {
// 1 owner found
- owner = results.iterator().next();
- return "redirect:/owners/" + owner.getId();
+ Owner foundOwner = results.iterator().next();
+ return "redirect:/owners/" + foundOwner.getId();
} else {
// multiple owners found
model.put("selections", results);
diff --git a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java
index a702cfc8f..5fe9a3294 100644
--- a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java
+++ b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java
@@ -31,8 +31,7 @@ class CrashController {
@RequestMapping(value = "/oups", method = RequestMethod.GET)
public String triggerException() {
- throw new RuntimeException(
- "Expected: controller used to showcase what " + "happens when an exception is thrown");
+ throw new ExampleException("Expected: controller used to showcase what happens when an exception is thrown");
}
}
diff --git a/src/main/java/org/springframework/samples/petclinic/system/ExampleException.java b/src/main/java/org/springframework/samples/petclinic/system/ExampleException.java
new file mode 100644
index 000000000..bcf5e2bdd
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/system/ExampleException.java
@@ -0,0 +1,15 @@
+package org.springframework.samples.petclinic.system;
+
+/**
+ * @author Martijn
+ * @since 21-6-2017.
+ */
+public class ExampleException extends RuntimeException {
+ public ExampleException(String message) {
+ super(ExampleException.class.getSimpleName() + ": " + message);
+ }
+
+ protected ExampleException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(ExampleException.class.getSimpleName() + ": " + message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java
index 8ddcca60a..7911aa702 100644
--- a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java
+++ b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java
@@ -31,11 +31,11 @@ import org.springframework.web.bind.annotation.ResponseBody;
@Controller
class VetController {
- private final VetRepository vets;
+ private final VetRepository vetRepository;
@Autowired
public VetController(VetRepository clinicService) {
- this.vets = clinicService;
+ this.vetRepository = clinicService;
}
@RequestMapping(value = { "/vets.html" })
@@ -43,7 +43,7 @@ class VetController {
// Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for Object-Xml mapping
Vets vets = new Vets();
- vets.getVetList().addAll(this.vets.findAll());
+ vets.getVetList().addAll(this.vetRepository.findAll());
model.put("vets", vets);
return "vets/vetList";
}
@@ -53,7 +53,7 @@ class VetController {
// Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for JSon/Object mapping
Vets vets = new Vets();
- vets.getVetList().addAll(this.vets.findAll());
+ vets.getVetList().addAll(this.vetRepository.findAll());
return vets;
}
diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java b/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java
index 20863ce76..15c4bf9ac 100644
--- a/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java
+++ b/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java
@@ -18,7 +18,6 @@ package org.springframework.samples.petclinic.vet;
import java.util.Collection;
import org.springframework.cache.annotation.Cacheable;
-import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository;
import org.springframework.transaction.annotation.Transactional;
@@ -40,7 +39,7 @@ public interface VetRepository extends Repository {
*/
@Transactional(readOnly = true)
@Cacheable("vets")
- Collection findAll() throws DataAccessException;
+ Collection findAll();
}
diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java
index f5b24c3fc..152fa560e 100644
--- a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java
+++ b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java
@@ -30,14 +30,14 @@ import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Vets {
- private List vets;
+ private List vetList;
@XmlElement
public List getVetList() {
- if (vets == null) {
- vets = new ArrayList<>();
+ if (vetList == null) {
+ vetList = new ArrayList<>();
}
- return vets;
+ return vetList;
}
}
diff --git a/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java b/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java
index c7853d170..122599886 100644
--- a/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java
+++ b/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java
@@ -17,7 +17,6 @@ package org.springframework.samples.petclinic.visit;
import java.util.List;
-import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.BaseEntity;
@@ -38,7 +37,7 @@ public interface VisitRepository extends Repository {
* @param visit the Visit
to save
* @see BaseEntity#isNew
*/
- void save(Visit visit) throws DataAccessException;
+ void save(Visit visit);
List findByPetId(Integer petId);
diff --git a/src/test/java/nl/utwente/bpsd/selenium/AddOwnerIT.java b/src/test/java/nl/utwente/bpsd/selenium/AddOwnerIT.java
new file mode 100644
index 000000000..87bc4ac0a
--- /dev/null
+++ b/src/test/java/nl/utwente/bpsd/selenium/AddOwnerIT.java
@@ -0,0 +1,52 @@
+package nl.utwente.bpsd.selenium;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.openqa.selenium.By;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.Select;
+
+import java.net.MalformedURLException;
+
+/**
+ * @author Martijn
+ * @since 21-6-2017.
+ */
+public class AddOwnerIT extends SeleniumBaseIT {
+ public AddOwnerIT() throws MalformedURLException {
+ super();
+ }
+
+ @Test
+ @Category(SeleniumBaseIT.class)
+ public void addOwnerIT() {
+ driver.get(BASE_URL+"/owners/new");
+
+ //Add an owner
+ fillTextField(By.name("firstName"), "Sophie");
+ fillTextField(By.name("lastName"), "Lathouwers");
+ fillTextField(By.name("address"), "Homeroad 12");
+ fillTextField(By.name("city"), "Enschede");
+ fillTextField(By.name("telephone"), "0534890000");
+ driver.findElement(By.name("telephone")).submit();
+ waitForPageToLoad();
+ waitFor(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[text()='Sophie Lathouwers']")));
+ Assert.assertTrue("Could not locate \"Sophie Lathouwers\" on the page. This is the html of the current page: "+getHTML(), pageContainsText("Sophie Lathouwers"));
+
+ //Add a pet
+ //The link text has \n thats why it cannot find it
+ waitFor(ExpectedConditions.presenceOfAllElementsLocatedBy(By.partialLinkText("Add")));
+ driver.findElement(By.partialLinkText("Add")).click();
+ waitForPageToLoad();
+ fillTextField(By.name("name"), "Thumper");
+ fillTextField(By.name("birthDate"), "1942/08/09");
+ new Select(driver.findElement(By.name("type"))).selectByValue("hamster");
+ driver.findElement(By.name("name")).submit();
+
+ waitForPageToLoad();
+ Assert.assertTrue("Could not locate \"Thumper\" on the page. This is the html of the current page: "+getHTML(),pageContainsText("Thumper"));
+ setTestFinished();
+ }
+
+}
diff --git a/src/test/java/nl/utwente/bpsd/selenium/AddVisitIT.java b/src/test/java/nl/utwente/bpsd/selenium/AddVisitIT.java
new file mode 100644
index 000000000..d9314803d
--- /dev/null
+++ b/src/test/java/nl/utwente/bpsd/selenium/AddVisitIT.java
@@ -0,0 +1,60 @@
+package nl.utwente.bpsd.selenium;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import java.net.MalformedURLException;
+import java.util.List;
+
+/**
+ * @author Sophie
+ * @since 21-6-2017.
+ */
+public class AddVisitIT extends SeleniumBaseIT {
+ public AddVisitIT() throws MalformedURLException {
+ super();
+ }
+
+ @Test
+ @Category(SeleniumBaseIT.class)
+ public void editPetNameAndAddAVisit() {
+ driver.get(BASE_URL+"/owners/find");
+
+ driver.findElement(By.name("lastName")).submit();
+ waitForPageToLoad();
+
+ //Go to first owner
+ WebElement table = driver.findElement(By.tagName("table"));
+ List cells = table.findElements(By.xpath(".//tr/td"));
+ cells.get(0).findElement(By.xpath("a")).click();
+ waitForPageToLoad();
+
+ //Go to edit page of first pet
+ driver.findElement(By.xpath("//table//tr/td/table/tbody//a[contains(text(),'Edit')]")).click();
+ waitForPageToLoad();
+
+ //Edit Name of pet
+ fillTextField(By.name("name"), "foobar");
+ driver.findElement(By.name("name")).submit();
+
+
+ waitForPageToLoad();
+ Assert.assertNotNull(driver.findElement(By.xpath("//table//tr/td/dl/dd[contains(text(), 'foobar')]")));
+
+ driver.findElement(By.xpath("//table//tr/td/table/tbody//a[contains(text(),'Add')]")).click();
+ waitForPageToLoad();
+
+
+ fillTextField(By.name("date"), "2017/12/12");
+ fillTextField(By.name("description"), "Foobar check for disease");
+ driver.findElement(By.name("date")).submit();
+ waitForPageToLoad();
+ Assert.assertNotNull(driver.findElement(By.xpath("//table//tr/td/table/tbody//td[contains(text(), '2017-12-12')]")));
+
+ setTestFinished();
+ }
+
+}
diff --git a/src/test/java/nl/utwente/bpsd/selenium/FindOwnerIT.java b/src/test/java/nl/utwente/bpsd/selenium/FindOwnerIT.java
new file mode 100644
index 000000000..d86e348a8
--- /dev/null
+++ b/src/test/java/nl/utwente/bpsd/selenium/FindOwnerIT.java
@@ -0,0 +1,33 @@
+package nl.utwente.bpsd.selenium;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.openqa.selenium.By;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.net.MalformedURLException;
+
+/**
+ *
+ * @author Martijn
+ * @since 21-6-2017.
+ */
+public class FindOwnerIT extends SeleniumBaseIT {
+ public FindOwnerIT() throws MalformedURLException {
+ super();
+ }
+
+ @Test
+ @Category(SeleniumBaseIT.class)
+ public void findOwnerIT() {
+ driver.get(BASE_URL+"/owners/find");
+ fillTextField(By.name("lastName"),"Coleman");
+ driver.findElement(By.name("lastName")).submit();
+ waitForPageToLoad();
+ Assert.assertTrue("Could not find \"Jean Coleman\" on the current page. This is the html of the current page: "+getHTML(),driver.findElements(By.xpath("//*[text()='Jean Coleman']")).size() == 1);
+ setTestFinished();
+ }
+
+}
diff --git a/src/test/java/nl/utwente/bpsd/selenium/SeleniumBaseIT.java b/src/test/java/nl/utwente/bpsd/selenium/SeleniumBaseIT.java
new file mode 100644
index 000000000..05a192cd0
--- /dev/null
+++ b/src/test/java/nl/utwente/bpsd/selenium/SeleniumBaseIT.java
@@ -0,0 +1,102 @@
+package nl.utwente.bpsd.selenium;
+
+import org.junit.After;
+import org.openqa.selenium.*;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.remote.Augmenter;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.remote.RemoteWebDriver;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Logger;
+
+/**
+ * @author Martijn
+ * @since 21-6-2017.
+ */
+public class SeleniumBaseIT {
+ protected final WebDriver driver;
+ private boolean testFinished = false;
+ public static final String BASE_URL = "http://pet-clinic:8080/";
+// public static final String BASE_URL = "http://localhost:8080/";
+
+ public SeleniumBaseIT() throws MalformedURLException {
+// System.setProperty("webdriver.chrome.driver","C:\\Users\\marti\\Downloads\\chromedriver_win32\\chromedriver.exe");
+// this.driver = new ChromeDriver();
+
+ this.driver = new Augmenter().augment(new RemoteWebDriver(new URL("http://selenium:4444/wd/hub"), DesiredCapabilities.firefox()));
+ driver.get(BASE_URL);
+ }
+
+ public void fillTextField(By by, String text) {
+ driver.findElement(by).clear();
+ driver.findElement(by).sendKeys(text);
+ }
+
+ protected void setTestFinished() {
+ testFinished = true;
+ }
+
+ @After
+ public void afterTest() {
+ if (!testFinished) {
+ if (driver instanceof TakesScreenshot) {
+ File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
+ Logger.getLogger(this.getClass().getName()).warning(screenshot.getAbsolutePath());
+ }
+ }
+ driver.close();
+ }
+
+
+ protected boolean pageContainsText(String text) {
+ return driver.findElements(By.xpath("//*[text()='" + text + "']")).size() == 1;
+ }
+
+ public String getHTML() {
+ return driver.findElement(By.xpath("//html")).getAttribute("innerHTML");
+ }
+
+ protected void waitForPageToLoad() {
+ waitFor(new FixedPeriod(333));
+ waitFor(new PageLoadedExpectedCondition());
+ }
+
+ protected void waitFor(ExpectedCondition> condition) {
+ new WebDriverWait(driver, 3).until(condition);
+ }
+
+ private class PageLoadedExpectedCondition implements ExpectedCondition {
+
+ @Override
+ public Boolean apply(WebDriver webDriver) {
+ if (webDriver instanceof JavascriptExecutor) {
+ return ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete");
+ }
+ throw new ClassCastException("This webdriver is not able to execute javascript.");
+ }
+ }
+
+ protected class FixedPeriod implements ExpectedCondition {
+ private final int time;
+
+ public FixedPeriod(int timeInMilliseconds) {
+ this.time = timeInMilliseconds;
+ }
+
+ @Override
+ public Boolean apply(WebDriver webDriver) {
+ try {
+ Thread.sleep(time);
+ return true;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ }
+}