-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added ability to add or update pet. closes #56
- Loading branch information
1 parent
65dd52c
commit 079f440
Showing
7 changed files
with
323 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
pet-clinic-web/src/main/java/spring/framework/petclinic/formatters/PetTypeFormatter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package spring.framework.petclinic.formatters; | ||
|
||
import org.springframework.format.Formatter; | ||
import org.springframework.stereotype.Component; | ||
import spring.framework.petclinic.model.PetType; | ||
import spring.framework.petclinic.services.PetTypeService; | ||
|
||
import java.text.ParseException; | ||
import java.util.Collection; | ||
import java.util.Locale; | ||
|
||
@Component | ||
public class PetTypeFormatter implements Formatter<PetType> { | ||
|
||
PetTypeService petTypeService; | ||
|
||
public PetTypeFormatter(PetTypeService petTypeService) { | ||
this.petTypeService = petTypeService; | ||
} | ||
|
||
@Override | ||
public String print(PetType petType, Locale locale) { | ||
return petType.getName(); | ||
} | ||
|
||
@Override | ||
public PetType parse(String text, Locale locale) throws ParseException { | ||
Collection<PetType> findPetTypes = petTypeService.findAll(); | ||
for (PetType type : findPetTypes) { | ||
if (type.getName().equals(text)) { | ||
return type; | ||
} | ||
} | ||
throw new ParseException("type not found: " + text, 0); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
pet-clinic-web/src/main/resources/templates/pets/createOrUpdatePetForm.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<html xmlns:th="https://www.thymeleaf.org" | ||
th:replace="~{fragments/layout :: layout (~{::body},'owners')}"> | ||
|
||
<body> | ||
|
||
<h2> | ||
<th:block th:if="${pet['new']}">New</th:block> | ||
Pet | ||
</h2> | ||
<form th:object="${pet}" class="form-horizontal" method="post"> | ||
<input type="hidden" name="id" th:value="*{id}"/> | ||
<div class="form-group has-feedback"> | ||
<div class="form-group"> | ||
<label class="col-sm-2 control-label">Owner</label> | ||
<div class="col-sm-10"> | ||
<span th:text="${pet.owner?.firstName + ' ' + pet.owner?.lastName}"/> | ||
</div> | ||
</div> | ||
<input | ||
th:replace="~{fragments/inputField :: input ('Name', 'name', 'text')}"/> | ||
<input | ||
th:replace="~{fragments/inputField :: input ('Birth Date', 'birthDate', 'date')}"/> | ||
<input | ||
th:replace="~{fragments/selectField :: select ('Type', 'petType', ${types})}"/> | ||
</div> | ||
<div class="form-group"> | ||
<div class="col-sm-offset-2 col-sm-10"> | ||
<button | ||
th:with="text=${pet['new']} ? 'Add Pet' : 'Update Pet'" | ||
class="btn btn-default" type="submit" th:text="${text}">Add | ||
Pet | ||
</button> | ||
</div> | ||
</div> | ||
</form> | ||
|
||
</body> | ||
|
||
</html> |
61 changes: 61 additions & 0 deletions
61
pet-clinic-web/src/main/resources/templates/pets/createOrUpdateVisitForm.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<html xmlns:th="https://www.thymeleaf.org" | ||
th:replace="~{fragments/layout :: layout (~{::body},'owners')}"> | ||
|
||
<body> | ||
|
||
<h2> | ||
<th:block th:if="${visit['new']}">New</th:block> | ||
Visit | ||
</h2> | ||
|
||
<b>Pet</b> | ||
<table class="table table-striped"> | ||
<thead> | ||
<tr> | ||
<th>Name</th> | ||
<th>Birth Date</th> | ||
<th>Type</th> | ||
<th>Owner</th> | ||
</tr> | ||
</thead> | ||
<tr> | ||
<td th:text="${pet.name}"></td> | ||
<td | ||
th:text="${#temporals.format(pet.birthDate, 'yyyy-MM-dd')}"></td> | ||
<td th:text="${pet.type}"></td> | ||
<td | ||
th:text="${pet.owner?.firstName + ' ' + pet.owner?.lastName}"></td> | ||
</tr> | ||
</table> | ||
|
||
<form th:object="${visit}" class="form-horizontal" method="post"> | ||
<div class="form-group has-feedback"> | ||
<input | ||
th:replace="~{fragments/inputField :: input ('Date', 'date', 'date')}"/> | ||
<input | ||
th:replace="~{fragments/inputField :: input ('Description', 'description', 'text')}"/> | ||
</div> | ||
|
||
<div class="form-group"> | ||
<div class="col-sm-offset-2 col-sm-10"> | ||
<input type="hidden" name="petId" th:value="${pet.id}"/> | ||
<button class="btn btn-default" type="submit">Add Visit</button> | ||
</div> | ||
</div> | ||
</form> | ||
|
||
<br/> | ||
<b>Previous Visits</b> | ||
<table class="table table-striped"> | ||
<tr> | ||
<th>Date</th> | ||
<th>Description</th> | ||
</tr> | ||
<tr th:if="${!visit['new']}" th:each="visit : ${pet.visits}"> | ||
<td th:text="${#temporals.format(visit.date, 'yyyy-MM-dd')}"></td> | ||
<td th:text=" ${visit.description}"></td> | ||
</tr> | ||
</table> | ||
|
||
</body> | ||
</html> |
112 changes: 112 additions & 0 deletions
112
pet-clinic-web/src/test/java/spring/framework/petclinic/controllers/PetControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package spring.framework.petclinic.controllers; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
import spring.framework.petclinic.model.Owner; | ||
import spring.framework.petclinic.model.Pet; | ||
import spring.framework.petclinic.model.PetType; | ||
import spring.framework.petclinic.services.OwnerService; | ||
import spring.framework.petclinic.services.PetService; | ||
import spring.framework.petclinic.services.PetTypeService; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.ArgumentMatchers.anyLong; | ||
import static org.mockito.Mockito.verify; | ||
import static org.mockito.Mockito.when; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class PetTypeTest { | ||
|
||
@Mock | ||
PetService petService; | ||
|
||
@Mock | ||
OwnerService ownerService; | ||
|
||
@Mock | ||
PetTypeService petTypeService; | ||
|
||
@InjectMocks | ||
PetController petController; | ||
|
||
MockMvc mockMvc; | ||
Owner owner; | ||
Set<PetType> petTypes; | ||
|
||
|
||
@BeforeEach | ||
void setUp() { | ||
owner = Owner.builder().id(1L).build(); | ||
|
||
petTypes = new HashSet<>(); | ||
petTypes.add(PetType.builder().id(1L).name("Dog").build()); | ||
petTypes.add(PetType.builder().id(2L).name("Cat").build()); | ||
|
||
mockMvc = MockMvcBuilders.standaloneSetup(petController).build(); | ||
} | ||
|
||
@Test | ||
void initCreationForm() throws Exception { | ||
when(ownerService.findById(anyLong())).thenReturn(owner); | ||
when(petTypeService.findAll()).thenReturn(petTypes); | ||
|
||
mockMvc.perform(get("/owners/1/pets/new")) | ||
.andExpect(status().isOk()) | ||
.andExpect(model().attributeExists("owner")) | ||
.andExpect(model().attributeExists("pet")) | ||
.andExpect(view().name("pets/createOrUpdatePetForm")); | ||
} | ||
|
||
@Test | ||
void processCreationForm() throws Exception { | ||
when(ownerService.findById(anyLong())).thenReturn(owner); | ||
when(petTypeService.findAll()).thenReturn(petTypes); | ||
|
||
mockMvc.perform(post("/owners/1/pets/new")) | ||
.andExpect(status().is3xxRedirection()) | ||
.andExpect(view().name("redirect:/owners/1")); | ||
|
||
verify(petService).save(any()); | ||
} | ||
|
||
@Test | ||
void initUpdateForm() throws Exception { | ||
Pet pet = new Pet(); | ||
pet.setId(2L); | ||
|
||
when(ownerService.findById(anyLong())).thenReturn(owner); | ||
when(petTypeService.findAll()).thenReturn(petTypes); | ||
when(petService.findById(anyLong())).thenReturn(pet); | ||
|
||
mockMvc.perform(get("/owners/1/pets/2/edit")) | ||
.andExpect(status().isOk()) | ||
.andExpect(model().attributeExists("owner")) | ||
.andExpect(model().attributeExists("pet")) | ||
.andExpect(view().name("pets/createOrUpdatePetForm")); | ||
} | ||
|
||
@Test | ||
void processUpdateForm() throws Exception { | ||
when(ownerService.findById(anyLong())).thenReturn(owner); | ||
when(petTypeService.findAll()).thenReturn(petTypes); | ||
|
||
mockMvc.perform(post("/owners/1/pets/2/edit")) | ||
.andExpect(status().is3xxRedirection()) | ||
.andExpect(view().name("redirect:/owners/1")); | ||
|
||
verify(petService).save(any()); | ||
} | ||
|
||
} |