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..58be460a0 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 founndOwner = results.iterator().next(); + return "redirect:/owners/" + founndOwner.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 index ce1573a39..87bc4ac0a 100644 --- a/src/test/java/nl/utwente/bpsd/selenium/AddOwnerIT.java +++ b/src/test/java/nl/utwente/bpsd/selenium/AddOwnerIT.java @@ -6,7 +6,6 @@ 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 org.openqa.selenium.support.ui.WebDriverWait; import java.net.MalformedURLException; @@ -31,20 +30,23 @@ public class AddOwnerIT extends SeleniumBaseIT { fillTextField(By.name("city"), "Enschede"); fillTextField(By.name("telephone"), "0534890000"); driver.findElement(By.name("telephone")).submit(); - new WebDriverWait(driver, 5).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[text()='Owner Information']"))); - Assert.assertTrue(pageContainsText("Sophie Lathouwers")); + 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 - new WebDriverWait(driver, 5).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[text()='Pets and Visits']"))); - driver.findElements(By.className("btn")).get(1).click(); - new WebDriverWait(driver, 5).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[text()='New']"))); + //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(); - new WebDriverWait(driver, 5).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[text()='Pets and Visits']"))); - Assert.assertTrue(pageContainsText("Thumper")); + 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 index c36098cda..3a9d0a589 100644 --- a/src/test/java/nl/utwente/bpsd/selenium/AddVisitIT.java +++ b/src/test/java/nl/utwente/bpsd/selenium/AddVisitIT.java @@ -10,7 +10,7 @@ import java.net.MalformedURLException; import java.util.List; /** - * @author Martijn + * @author Sophie * @since 21-6-2017. */ public class AddVisitIT extends SeleniumBaseIT { @@ -20,22 +20,31 @@ public class AddVisitIT extends SeleniumBaseIT { @Test @Category(SeleniumBaseIT.class) - public void addOwnerTest() { - driver.findElement(By.name("lastName")).submit(); - - //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(); + public void editPetNameAndAddAVisit() { + driver.get(BASE_URL+"/owners/find"); - //Go to edit page of first pet - driver.findElement(By.xpath("//table//tr/td/table/tbody//a[text()='Edit Pet']")).click(); + driver.findElement(By.name("lastName")).submit(); + waitForPageToLoad(); - //Edit Name of pet - fillTextField(By.name("name"), "foobar"); - driver.findElement(By.name("name")).submit(); + //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(); - Assert.assertNotNull(driver.findElement(By.xpath("//table//tr/td/dl/dd/[contains(text(), 'foobar')]"))); + //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')]"))); + + //TODO add a visit + setTestFinished(); } } diff --git a/src/test/java/nl/utwente/bpsd/selenium/FailingIT.java b/src/test/java/nl/utwente/bpsd/selenium/FailingIT.java deleted file mode 100644 index 87a26e3ad..000000000 --- a/src/test/java/nl/utwente/bpsd/selenium/FailingIT.java +++ /dev/null @@ -1,26 +0,0 @@ -package nl.utwente.bpsd.selenium; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import java.net.MalformedURLException; - -/** - * @author Martijn - * @since 21-6-2017. - */ -public class FailingIT extends SeleniumBaseIT { - public FailingIT() throws MalformedURLException { - super(); - } - - @Test - @Category(SeleniumBaseIT.class) - @Ignore - public void failIT() { - Assert.fail(); - } - -} diff --git a/src/test/java/nl/utwente/bpsd/selenium/FindOwnerIT.java b/src/test/java/nl/utwente/bpsd/selenium/FindOwnerIT.java index ac52cde29..d86e348a8 100644 --- a/src/test/java/nl/utwente/bpsd/selenium/FindOwnerIT.java +++ b/src/test/java/nl/utwente/bpsd/selenium/FindOwnerIT.java @@ -25,7 +25,9 @@ public class FindOwnerIT extends SeleniumBaseIT { driver.get(BASE_URL+"/owners/find"); fillTextField(By.name("lastName"),"Coleman"); driver.findElement(By.name("lastName")).submit(); - new WebDriverWait(driver, 5).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[text()='Owner Information']"))); - Assert.assertTrue(driver.findElementsByXPath("//*[text()='Jean Coleman']").size() == 1); + 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 index 02ae4c59d..05a192cd0 100644 --- a/src/test/java/nl/utwente/bpsd/selenium/SeleniumBaseIT.java +++ b/src/test/java/nl/utwente/bpsd/selenium/SeleniumBaseIT.java @@ -1,43 +1,102 @@ package nl.utwente.bpsd.selenium; import org.junit.After; -import org.openqa.selenium.By; +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 RemoteWebDriver driver; + 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 RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), DesiredCapabilities.firefox()); + + 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){ + 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.findElementsByXPath("//*[text()='"+text+"']").size() == 1; + 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; + } + } } }