diff --git a/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java b/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java index 584ff5d..f1cefde 100644 --- a/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java +++ b/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java @@ -2,11 +2,8 @@ package com.github.prominence.carrepair; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -@EnableJpaRepositories("com.github.prominence.carrepair.repository") -@EntityScan("com.github.prominence.carrepair.model") +// @EnableJpaRepositories and @EntityScan annotations are not required as all classes are placed in the main application package or its sub package(s). @SpringBootApplication public class CarRepairApplication { @@ -15,5 +12,4 @@ public class CarRepairApplication { } } -// TODO: tests // TODO: big data \ No newline at end of file diff --git a/src/main/java/com/github/prominence/carrepair/controller/ClientController.java b/src/main/java/com/github/prominence/carrepair/controller/ClientController.java index 443c1e2..810c628 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/ClientController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/ClientController.java @@ -1,5 +1,6 @@ package com.github.prominence.carrepair.controller; +import com.github.prominence.carrepair.controller.exception.ResourceNotFoundException; import com.github.prominence.carrepair.model.domain.Client; import com.github.prominence.carrepair.model.dto.ClientDto; import com.github.prominence.carrepair.service.ClientService; @@ -57,7 +58,7 @@ public class ClientController { model.addAttribute("clientDto", clientService.convertToDto(clientOptional.get())); return "client/edit"; } else { - return "redirect:/client"; + throw new ResourceNotFoundException(); } } diff --git a/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java b/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java index 6ea8885..57f7f6b 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java @@ -1,5 +1,6 @@ package com.github.prominence.carrepair.controller; +import com.github.prominence.carrepair.controller.exception.ResourceNotFoundException; import com.github.prominence.carrepair.enums.OrderStatus; import com.github.prominence.carrepair.model.domain.Mechanic; import com.github.prominence.carrepair.model.dto.MechanicDto; @@ -58,7 +59,7 @@ public class MechanicController { model.addAttribute("mechanicDto", mechanicService.convertToDto(mechanicOptional.get())); return "mechanic/edit"; } else { - return "redirect:/mechanic"; + throw new ResourceNotFoundException(); } } diff --git a/src/main/java/com/github/prominence/carrepair/controller/OrderController.java b/src/main/java/com/github/prominence/carrepair/controller/OrderController.java index 1b22f77..ec3e2b6 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/OrderController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/OrderController.java @@ -1,5 +1,6 @@ package com.github.prominence.carrepair.controller; +import com.github.prominence.carrepair.controller.exception.ResourceNotFoundException; import com.github.prominence.carrepair.enums.OrderStatus; import com.github.prominence.carrepair.model.domain.Order; import com.github.prominence.carrepair.model.dto.OrderDto; @@ -63,7 +64,7 @@ public class OrderController { model.addAttribute("orderStatuses", OrderStatus.values()); return "order/edit"; } else { - return "redirect:/order"; + throw new ResourceNotFoundException(); } } diff --git a/src/main/java/com/github/prominence/carrepair/controller/exception/ResourceNotFoundException.java b/src/main/java/com/github/prominence/carrepair/controller/exception/ResourceNotFoundException.java new file mode 100644 index 0000000..c6c1462 --- /dev/null +++ b/src/main/java/com/github/prominence/carrepair/controller/exception/ResourceNotFoundException.java @@ -0,0 +1,8 @@ +package com.github.prominence.carrepair.controller.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.NOT_FOUND) +public class ResourceNotFoundException extends RuntimeException { +} \ No newline at end of file diff --git a/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java b/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java index 273e1c0..31aecfa 100644 --- a/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java +++ b/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java @@ -69,6 +69,8 @@ public class DemoDataPopulator { long mechanicsCount = mechanicService.getMechanicCount(); long clientsCount = clientService.getClientCount(); + if (mechanicsCount == 0 || clientsCount == 0) return args -> {}; + List demoOrderList = Stream.generate(() -> { Order order = new Order(); order.setOrderStatus(orderStatuses[RandomUtils.nextInt(0, 3)]); diff --git a/src/main/java/com/github/prominence/carrepair/service/MechanicService.java b/src/main/java/com/github/prominence/carrepair/service/MechanicService.java index 386bfc2..2d3dba5 100644 --- a/src/main/java/com/github/prominence/carrepair/service/MechanicService.java +++ b/src/main/java/com/github/prominence/carrepair/service/MechanicService.java @@ -1,5 +1,6 @@ package com.github.prominence.carrepair.service; +import com.github.prominence.carrepair.controller.exception.ResourceNotFoundException; import com.github.prominence.carrepair.enums.OrderStatus; import com.github.prominence.carrepair.model.domain.Mechanic; import com.github.prominence.carrepair.model.domain.Order; @@ -71,6 +72,7 @@ public class MechanicService { } public Map getOrderStatistics(Long mechanicId) { + if (!mechanicRepository.findById(mechanicId).isPresent()) throw new ResourceNotFoundException(); Map statistics = new HashMap<>(); statistics.put(OrderStatus.SCHEDULED, 0); statistics.put(OrderStatus.ACCEPTED, 0); diff --git a/src/test/java/com/github/prominence/carrepair/controller/ClientControllerIntegrationTest.java b/src/test/java/com/github/prominence/carrepair/controller/ClientControllerIntegrationTest.java new file mode 100644 index 0000000..bce37e6 --- /dev/null +++ b/src/test/java/com/github/prominence/carrepair/controller/ClientControllerIntegrationTest.java @@ -0,0 +1,199 @@ +package com.github.prominence.carrepair.controller; + +import com.github.prominence.carrepair.model.domain.Client; +import com.github.prominence.carrepair.service.ClientService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureTestDatabase +@AutoConfigureMockMvc +public class ClientControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ClientService clientService; + + @Test + public void whenRequestIndexPage_thenReturnFirstPageOfIndex() throws Exception { + // given + Client testClient = new Client("testFirstName", "testMiddleName", "testLastName", "testPhone"); + clientService.save(testClient); + + // expected + mockMvc.perform( + get("/client") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("clientList", "totalPages")). + andExpect(model().attribute("totalPages", 11)). // 100 demo clients + 1 from setup + andExpect(model().attribute("clientList", hasSize(10))). + andExpect(view().name("client/index")); + } + + @Test + public void whenRequestIndexLastPage_thenReturnLastPageOfIndex() throws Exception { + // given + Client testClient = new Client("testFirstName", "testMiddleName", "testLastName", "testPhone"); + clientService.save(testClient); + + // expected + mockMvc.perform( + get("/client").param("page", "10") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("clientList", "totalPages")). + andExpect(model().attribute("totalPages", 11)). // 100 demo clients + 1 from setup + andExpect(model().attribute("clientList", hasSize(lessThan(10)))). + andExpect(view().name("client/index")); + + } + + @Test + public void whenRequestCreateClientPage_thenReturnCreatePageWithEmptyDto() throws Exception { + mockMvc.perform( + get("/client/create") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("clientDto")). + andExpect(view().name("client/edit")); + } + + @Test + public void whenRequestEditWithoutId_thenReturnNotFount() throws Exception { + mockMvc.perform( + get("/client/edit") + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenRequestEditWithIncorrectId_thenRedirectToIndex() throws Exception { + mockMvc.perform( + get("/client/edit/{id}", -34) + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenRequestEditWithCorrectId_thenReturnEditPage() throws Exception { + mockMvc.perform( + get("/client/edit/{id}", 1) + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("clientDto")). + andExpect(view().name("client/edit")); + } + + @Test + public void whenSubmitCorrectClientFromEditPage_thenRedirectToIndex() throws Exception { + mockMvc.perform( + post("/client/update/{id}", 100). + param("id", "100"). + param("firstName", "changedTestFirstName"). + param("middleName", "changedTestMiddleName"). + param("lastName", "changedTestLastName"). + param("phone", "changedTestPhone") + ). + andDo(print()). + andExpect(status().is3xxRedirection()). + andExpect(redirectedUrl("/client")); + } + + @Test + public void whenSubmitIncorrectClientFromEditPage_thenStayOnPage() throws Exception { + mockMvc.perform( + post("/client/update/{id}", 100). + param("id", "100"). + param("firstName", ""). + param("middleName", "changedTestMiddleName"). + param("lastName", "changedTestLastName"). + param("phone", "changedTestPhone") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(view().name("client/edit")); + } + + @Test + public void whenSubmitCorrectClientFromCreatePage_thenRedirectToIndex() throws Exception { + mockMvc.perform( + post("/client/create"). + param("firstName", "changedTestFirstName"). + param("middleName", "changedTestMiddleName"). + param("lastName", "changedTestLastName"). + param("phone", "changedTestPhone") + ). + andDo(print()). + andExpect(status().is3xxRedirection()). + andExpect(redirectedUrl("/client")); + } + + @Test + public void whenSubmitIncorrectClientFromCreatePage_thenStayOnPage() throws Exception { + mockMvc.perform( + post("/client/create"). + param("firstName", ""). + param("middleName", "changedTestMiddleName"). + param("lastName", "changedTestLastName"). + param("phone", "changedTestPhone") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(view().name("client/edit")); + } + + @Test + public void whenDeleteCorrectClient_thenReturnOk() throws Exception { + // given + Client testClient = new Client("testFirstName", "testMiddleName", "testLastName", "testPhone"); + Long id = clientService.save(testClient).getId(); + + // expected + mockMvc.perform( + delete("/client/delete/{id}", id) + ). + andDo(print()). + andExpect(status().isOk()); + } + + @Test + public void whenDeleteIncorrectClient_thenReturnNotFount() throws Exception { + mockMvc.perform( + delete("/client/delete/{id}", -23) + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenDeleteWithoutId_thenReturnNotFound() throws Exception { + mockMvc.perform( + delete("/client/delete") + ). + andDo(print()). + andExpect(status().isNotFound()); + } +} diff --git a/src/test/java/com/github/prominence/carrepair/controller/HomeControllerUnitTest.java b/src/test/java/com/github/prominence/carrepair/controller/HomeControllerUnitTest.java new file mode 100644 index 0000000..d54c670 --- /dev/null +++ b/src/test/java/com/github/prominence/carrepair/controller/HomeControllerUnitTest.java @@ -0,0 +1,37 @@ +package com.github.prominence.carrepair.controller; + +import com.github.prominence.carrepair.controller.advice.GlobalInfoAdvice; +import com.github.prominence.carrepair.service.ClientService; +import com.github.prominence.carrepair.service.MechanicService; +import com.github.prominence.carrepair.service.OrderService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.MockBeans; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebMvcTest({HomeController.class, GlobalInfoAdvice.class}) +@MockBeans({@MockBean(ClientService.class), @MockBean(MechanicService.class), @MockBean(OrderService.class)}) +public class HomeControllerUnitTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenCallHomePage_thenReturnHomePage() throws Exception { + mockMvc.perform( + get("/") + ). + andDo(print()). + andExpect(status().isOk() + ); + } +} diff --git a/src/test/java/com/github/prominence/carrepair/controller/MechanicControllerIntegrationTest.java b/src/test/java/com/github/prominence/carrepair/controller/MechanicControllerIntegrationTest.java new file mode 100644 index 0000000..e51b964 --- /dev/null +++ b/src/test/java/com/github/prominence/carrepair/controller/MechanicControllerIntegrationTest.java @@ -0,0 +1,236 @@ +package com.github.prominence.carrepair.controller; + +import com.github.prominence.carrepair.enums.OrderStatus; +import com.github.prominence.carrepair.model.domain.Mechanic; +import com.github.prominence.carrepair.service.MechanicService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import java.math.BigDecimal; + +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.core.AllOf.allOf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureTestDatabase +@AutoConfigureMockMvc +public class MechanicControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private MechanicService mechanicService; + + @Test + public void whenRequestIndexPage_thenReturnFirstPageOfIndex() throws Exception { + // given + Mechanic testMechanic = new Mechanic("testFirstName", "testMiddleName", "testLastName", BigDecimal.ONE); + mechanicService.save(testMechanic); + + // expected + mockMvc.perform( + get("/mechanic") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("mechanicList", "totalPages")). + andExpect(model().attribute("totalPages", 11)). // 100 demo mechanics + 1 from setup + andExpect(model().attribute("mechanicList", hasSize(10))). + andExpect(view().name("mechanic/index")); + } + + @Test + public void whenRequestIndexLastPage_thenReturnLastPageOfIndex() throws Exception { + // given + Mechanic testMechanic = new Mechanic("testFirstName", "testMiddleName", "testLastName", BigDecimal.ONE); + mechanicService.save(testMechanic); + + // expected + mockMvc.perform( + get("/mechanic").param("page", "10") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("mechanicList", "totalPages")). + andExpect(model().attribute("totalPages", 11)). // 100 demo mechanics + 1 from setup + andExpect(model().attribute("mechanicList", hasSize(lessThan(10)))). + andExpect(view().name("mechanic/index")); + + } + + @Test + public void whenRequestCreateMechanicPage_thenReturnCreatePageWithEmptyDto() throws Exception { + mockMvc.perform( + get("/mechanic/create") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("mechanicDto")). + andExpect(view().name("mechanic/edit")); + } + + @Test + public void whenRequestEditWithoutId_thenReturnNotFount() throws Exception { + mockMvc.perform( + get("/mechanic/edit") + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenRequestEditWithIncorrectId_thenRedirectToIndex() throws Exception { + mockMvc.perform( + get("/mechanic/edit/{id}", -34) + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenRequestEditWithCorrectId_thenReturnEditPage() throws Exception { + mockMvc.perform( + get("/mechanic/edit/{id}", 1) + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("mechanicDto")). + andExpect(view().name("mechanic/edit")); + } + + @Test + public void whenSubmitCorrectMechanicFromEditPage_thenRedirectToIndex() throws Exception { + mockMvc.perform( + post("/mechanic/update/{id}", 100). + param("id", "100"). + param("firstName", "changedTestFirstName"). + param("middleName", "changedTestMiddleName"). + param("lastName", "changedTestLastName"). + param("hourlyPayment", BigDecimal.TEN.toString()) + ). + andDo(print()). + andExpect(status().is3xxRedirection()). + andExpect(redirectedUrl("/mechanic")); + } + + @Test + public void whenSubmitIncorrectMechanicFromEditPage_thenStayOnPage() throws Exception { + mockMvc.perform( + post("/mechanic/update/{id}", 100). + param("id", "100"). + param("firstName", ""). + param("middleName", "changedTestMiddleName"). + param("lastName", "changedTestLastName"). + param("hourlyPayment", BigDecimal.TEN.toString()) + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(view().name("mechanic/edit")); + } + + @Test + public void whenSubmitCorrectMechanicFromCreatePage_thenRedirectToIndex() throws Exception { + mockMvc.perform( + post("/mechanic/create"). + param("firstName", "changedTestFirstName"). + param("middleName", "changedTestMiddleName"). + param("lastName", "changedTestLastName"). + param("hourlyPayment", BigDecimal.TEN.toString()) + ). + andDo(print()). + andExpect(status().is3xxRedirection()). + andExpect(redirectedUrl("/mechanic")); + } + + @Test + public void whenSubmitIncorrectMechanicFromCreatePage_thenStayOnPage() throws Exception { + mockMvc.perform( + post("/mechanic/create"). + param("firstName", ""). + param("middleName", "changedTestMiddleName"). + param("lastName", "changedTestLastName"). + param("hourlyPayment", BigDecimal.TEN.toString()) + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(view().name("mechanic/edit")); + } + + @Test + public void whenDeleteCorrectMechanic_thenReturnOk() throws Exception { + // given + Mechanic testMechanic = new Mechanic("testFirstName", "testMiddleName", "testLastName", BigDecimal.ONE); + Long id = mechanicService.save(testMechanic).getId(); + + // expected + mockMvc.perform( + delete("/mechanic/delete/{id}", id) + ). + andDo(print()). + andExpect(status().isOk()); + } + + @Test + public void whenDeleteIncorrectMechanic_thenReturnNotFount() throws Exception { + mockMvc.perform( + delete("/mechanic/delete/{id}", -23) + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenDeleteWithoutId_thenReturnNotFound() throws Exception { + mockMvc.perform( + delete("/mechanic/delete") + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenRequestStatisticsPage_thenReturnStatistics() throws Exception { + mockMvc.perform( + get("/mechanic/statistics/{id}", 1) + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attribute("statistics", allOf( + hasKey(OrderStatus.SCHEDULED), + hasKey(OrderStatus.DONE), + hasKey(OrderStatus.ACCEPTED) + ))). + andExpect(view().name("mechanic/statistics")); + } + + @Test + public void whenRequestStatisticsPageForWrongMechanic_thenReturnNotFound() throws Exception{ + mockMvc.perform( + get("/mechanic/statistics/{id}", -123) + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenRequestStatisticsPageWithoutId_thenReturnNotFound() throws Exception { + mockMvc.perform( + get("/mechanic/statistics") + ). + andDo(print()). + andExpect(status().isNotFound()); + } +} diff --git a/src/test/java/com/github/prominence/carrepair/controller/OrderControllerIntegrationTest.java b/src/test/java/com/github/prominence/carrepair/controller/OrderControllerIntegrationTest.java new file mode 100644 index 0000000..1b368c9 --- /dev/null +++ b/src/test/java/com/github/prominence/carrepair/controller/OrderControllerIntegrationTest.java @@ -0,0 +1,230 @@ +package com.github.prominence.carrepair.controller; + +import com.github.prominence.carrepair.enums.OrderStatus; +import com.github.prominence.carrepair.model.domain.Client; +import com.github.prominence.carrepair.model.domain.Mechanic; +import com.github.prominence.carrepair.model.domain.Order; +import com.github.prominence.carrepair.service.ClientService; +import com.github.prominence.carrepair.service.MechanicService; +import com.github.prominence.carrepair.service.OrderService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.stream.Stream; + +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureTestDatabase +@AutoConfigureMockMvc +public class OrderControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private OrderService orderService; + + @Autowired + private ClientService clientService; + + @Autowired + private MechanicService mechanicService; + + @Test + public void whenRequestIndexPage_thenReturnFirstPageOfIndex() throws Exception { + // given + Order testOrder = getTestOrder(); + orderService.save(testOrder); + + // expected + mockMvc.perform( + get("/order") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("orderList", "totalPages")). + andExpect(model().attribute("totalPages", 1)). + andExpect(model().attribute("orderList", hasSize(greaterThanOrEqualTo(1)))). + andExpect(view().name("order/index")); + } + + @Test + public void whenRequestIndexSecondPage_thenReturnSecondPageOfIndex() throws Exception { + // given + Stream.generate(this::getTestOrder).limit(11).forEach(orderService::save); + + // expected + mockMvc.perform( + get("/order").param("page", "1") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("orderList", "totalPages")). + andExpect(model().attribute("totalPages", 2)). + andExpect(model().attribute("orderList", hasSize(lessThan(10)))). + andExpect(view().name("order/index")); + + } + + @Test + public void whenRequestCreateOrderPage_thenReturnCreatePageWithEmptyDto() throws Exception { + mockMvc.perform( + get("/order/create") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("orderDto")). + andExpect(view().name("order/edit")); + } + + @Test + public void whenRequestEditWithoutId_thenReturnNotFount() throws Exception { + mockMvc.perform( + get("/order/edit") + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenRequestEditWithIncorrectId_thenRedirectToIndex() throws Exception { + mockMvc.perform( + get("/order/edit/{id}", -34) + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenRequestEditWithCorrectId_thenReturnEditPage() throws Exception { + // given + Order testOrder = getTestOrder(); + Long id = orderService.save(testOrder).getId(); + + // expected + mockMvc.perform( + get("/order/edit/{id}", id) + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(model().attributeExists("orderDto")). + andExpect(view().name("order/edit")); + } + + @Test + public void whenSubmitCorrectOrderFromEditPage_thenRedirectToIndex() throws Exception { + mockMvc.perform( + post("/order/update/{id}", 100). + param("id", "100"). + param("description", "testDescription"). + param("clientId", "1"). + param("mechanicId", "1"). + param("createdOnDate", "1996-02-07 14:12:12"). + param("totalPrice", "123"). + param("orderStatus", "Scheduled") + ). + andDo(print()). + andExpect(status().is3xxRedirection()). + andExpect(redirectedUrl("/order")); + } + + @Test + public void whenSubmitIncorrectOrderFromEditPage_thenStayOnPage() throws Exception { + mockMvc.perform( + post("/order/update/{id}", 100). + param("id", "100"). + param("description", "testDescription"). + param("clientId", "1") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(view().name("order/edit")); + } + + @Test + public void whenSubmitCorrectOrderFromCreatePage_thenRedirectToIndex() throws Exception { + mockMvc.perform( + post("/order/create"). + param("id", "100"). + param("description", "testDescription"). + param("clientId", "1"). + param("mechanicId", "1"). + param("createdOnDate", "1996-02-07 14:12:12"). + param("totalPrice", "123"). + param("orderStatus", "Scheduled") + ). + andDo(print()). + andExpect(status().is3xxRedirection()). + andExpect(redirectedUrl("/order")); + } + + @Test + public void whenSubmitIncorrectOrderFromCreatePage_thenStayOnPage() throws Exception { + mockMvc.perform( + post("/order/create"). + param("id", "100"). + param("description", "testDescription"). + param("clientId", "1"). + param("totalPrice", "123"). + param("orderStatus", "Scheduled") + ). + andDo(print()). + andExpect(status().isOk()). + andExpect(view().name("order/edit")); + } + + @Test + public void whenDeleteCorrectOrder_thenReturnOk() throws Exception { + // given + Order testOrder = getTestOrder(); + Long id = orderService.save(testOrder).getId(); + + // expected + mockMvc.perform( + delete("/order/delete/{id}", id) + ). + andDo(print()). + andExpect(status().isOk()); + } + + @Test + public void whenDeleteIncorrectOrder_thenReturnNotFount() throws Exception { + mockMvc.perform( + delete("/order/delete/{id}", -23) + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + @Test + public void whenDeleteWithoutId_thenReturnNotFound() throws Exception { + mockMvc.perform( + delete("/order/delete") + ). + andDo(print()). + andExpect(status().isNotFound()); + } + + private Order getTestOrder() { + Client testClient = new Client("1", "1", "1", "1"); + clientService.save(testClient); + Mechanic testMechanic = new Mechanic("1", "1", "1", BigDecimal.ONE); + mechanicService.save(testMechanic); + return new Order("11", testClient, testMechanic, LocalDateTime.now(), null, BigDecimal.TEN, OrderStatus.SCHEDULED.toString()); + } +} diff --git a/src/test/java/com/github/prominence/carrepair/controller/advice/GlobalInfoAdviceUnitTest.java b/src/test/java/com/github/prominence/carrepair/controller/advice/GlobalInfoAdviceUnitTest.java new file mode 100644 index 0000000..c1a82a3 --- /dev/null +++ b/src/test/java/com/github/prominence/carrepair/controller/advice/GlobalInfoAdviceUnitTest.java @@ -0,0 +1,53 @@ +package com.github.prominence.carrepair.controller.advice; + +import com.github.prominence.carrepair.service.ClientService; +import com.github.prominence.carrepair.service.MechanicService; +import com.github.prominence.carrepair.service.OrderService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.ui.ExtendedModelMap; +import org.springframework.ui.Model; + +import java.util.Map; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(SpringRunner.class) +@WebMvcTest(GlobalInfoAdvice.class) +public class GlobalInfoAdviceUnitTest { + + @Autowired + private GlobalInfoAdvice globalInfoAdvice; + + @MockBean + private ClientService clientService; + + @MockBean + private MechanicService mechanicService; + + @MockBean + private OrderService orderService; + + @Test + public void whenAdviceIsFinished_thenModelIsFilled() { + // given + when(clientService.getClientCount()).thenReturn(5L); + when(mechanicService.getMechanicCount()).thenReturn(2L); + when(orderService.getOrderCount()).thenReturn(6L); + Model model = new ExtendedModelMap(); + + // when + globalInfoAdvice.addBadgeInfo(model); + + // then + final Map modelMap = model.asMap(); + assertThat(modelMap.get("clientsCount")).isEqualTo(5L); + assertThat(modelMap.get("mechanicsCount")).isEqualTo(2L); + assertThat(modelMap.get("ordersCount")).isEqualTo(6L); + } +} diff --git a/src/test/java/com/github/prominence/carrepair/controller/api/AutocompleteApiControllerIntegrationTest.java b/src/test/java/com/github/prominence/carrepair/controller/api/AutocompleteApiControllerIntegrationTest.java new file mode 100644 index 0000000..18bc327 --- /dev/null +++ b/src/test/java/com/github/prominence/carrepair/controller/api/AutocompleteApiControllerIntegrationTest.java @@ -0,0 +1,132 @@ +package com.github.prominence.carrepair.controller.api; + +import com.github.prominence.carrepair.model.domain.Client; +import com.github.prominence.carrepair.model.domain.Mechanic; +import com.github.prominence.carrepair.service.ClientService; +import com.github.prominence.carrepair.service.MechanicService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import java.math.BigDecimal; +import java.util.Arrays; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureTestDatabase +@AutoConfigureMockMvc +public class AutocompleteApiControllerIntegrationTest { + + private static final String CLIENT_URI = "/api/autocomplete/client"; + private static final String MECHANIC_URI = "/api/autocomplete/mechanic"; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ClientService clientService; + + @Autowired + private MechanicService mechanicService; + + @Before + public void setup() { + Arrays.asList( + new Client("testCase1", "1", "1", "1"), + new Client("1", "1", "1", "1"), + new Client("2", "2", "2", "2"), + new Client("3", "3", "3", "3"), + new Client("4", "4", "4", "4"), + new Client("5", "5", "5", "5"), + new Client("6", "6", "6", "6"), + new Client("7", "7", "7", "7"), + new Client("8", "8", "8", "8"), + new Client("9", "9", "9", "9") + ).forEach(clientService::save); + + Arrays.asList( + new Mechanic("testCase1", "1", "1", BigDecimal.ONE), + new Mechanic("1", "1", "1", BigDecimal.ONE), + new Mechanic("2", "2", "2", BigDecimal.ONE), + new Mechanic("3", "3", "3", BigDecimal.ONE), + new Mechanic("4", "4", "4", BigDecimal.ONE), + new Mechanic("5", "5", "5", BigDecimal.ONE), + new Mechanic("6", "6", "6", BigDecimal.ONE), + new Mechanic("7", "7", "7", BigDecimal.ONE), + new Mechanic("8", "8", "8", BigDecimal.ONE), + new Mechanic("9", "9", "9", BigDecimal.ONE) + ).forEach(mechanicService::save); + } + + @Test + public void whenWithoutQueryForClient_thenReturnBadRequestResponse() throws Exception { + mockMvc.perform( + get(CLIENT_URI) + ). + andDo(print()). + andExpect(status().isBadRequest()); + } + + @Test + public void whenWithQueryForClient_thenReturnResult() throws Exception { + mockMvc.perform( + get(CLIENT_URI).param("query", "testCase") + ). + andDo(print()). + andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)). + andExpect(status().isOk()); + } + + @Test + public void whenQueryNotExistingClient_thenReturnEmpty() throws Exception { + mockMvc.perform( + get(CLIENT_URI).param("query", "nonExistingClient") + ). + andDo(print()). + andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)). + andExpect(content().json("[]", true)). + andExpect(status().isOk()); + } + + @Test + public void whenWithoutQueryForMechanic_thenReturnBadRequestResponse() throws Exception { + mockMvc.perform( + get(MECHANIC_URI) + ). + andDo(print()). + andExpect(status().isBadRequest()); + } + + @Test + public void whenWithQueryForMechanic_thenReturnResult() throws Exception { + mockMvc.perform( + get(MECHANIC_URI).param("query", "testCase") + ). + andDo(print()). + andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)). + andExpect(status().isOk()); + } + + @Test + public void whenQueryNotExistingMechanic_thenReturnEmpty() throws Exception { + mockMvc.perform( + get(MECHANIC_URI).param("query", "nonExistingClient") + ). + andDo(print()). + andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)). + andExpect(content().json("[]", true)). + andExpect(status().isOk()); + } +}