From 1b0185400a706cbe2d45ce7e9c67e634cb0f341d Mon Sep 17 00:00:00 2001 From: Ahmed Wael Date: Mon, 19 May 2025 01:05:56 +0300 Subject: [PATCH] added e2e test --- .idea/compiler.xml | 1 + pom.xml | 6 + .../Controllers/AssignerController.java | 2 +- .../Controllers/ManagerController.java | 2 +- .../Controllers/PackagedOrdersController.java | 2 +- .../Controllers/PackagerController.java | 2 +- .../Controllers/StockController.java | 2 +- .../warehouse/Models/AssignedOrders.java | 39 +--- .../com/podzilla/warehouse/Models/Stock.java | 2 + .../Services/AssignedOrdersService.java | 14 +- .../warehouse/WarehouseApplicationTests.java | 12 -- .../podzilla/warehouse/e2e/E2eTestBase.java | 37 ++++ .../podzilla/warehouse/e2e/E2eTestUtils.java | 136 ++++++++++++ .../warehouse/e2e/ManagerE2eTest.java | 202 ++++++++++++++++++ 14 files changed, 397 insertions(+), 62 deletions(-) delete mode 100644 src/test/java/com/podzilla/warehouse/WarehouseApplicationTests.java create mode 100644 src/test/java/com/podzilla/warehouse/e2e/E2eTestBase.java create mode 100644 src/test/java/com/podzilla/warehouse/e2e/E2eTestUtils.java create mode 100644 src/test/java/com/podzilla/warehouse/e2e/ManagerE2eTest.java diff --git a/.idea/compiler.xml b/.idea/compiler.xml index f1e20ad..c640c94 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -18,6 +18,7 @@ + diff --git a/pom.xml b/pom.xml index 4bd2e18..5d3b046 100644 --- a/pom.xml +++ b/pom.xml @@ -133,6 +133,12 @@ podzilla-utils-lib v1.1.12 + + org.junit.jupiter + junit-jupiter + 5.10.2 + test + diff --git a/src/main/java/com/podzilla/warehouse/Controllers/AssignerController.java b/src/main/java/com/podzilla/warehouse/Controllers/AssignerController.java index f5dbfbf..769a0f2 100644 --- a/src/main/java/com/podzilla/warehouse/Controllers/AssignerController.java +++ b/src/main/java/com/podzilla/warehouse/Controllers/AssignerController.java @@ -15,7 +15,7 @@ @Slf4j @RestController -@RequestMapping("/assign") +@RequestMapping("/api/assign") public class AssignerController { @Autowired diff --git a/src/main/java/com/podzilla/warehouse/Controllers/ManagerController.java b/src/main/java/com/podzilla/warehouse/Controllers/ManagerController.java index 81ba2a7..4d70c9c 100644 --- a/src/main/java/com/podzilla/warehouse/Controllers/ManagerController.java +++ b/src/main/java/com/podzilla/warehouse/Controllers/ManagerController.java @@ -13,7 +13,7 @@ @Slf4j @RestController -@RequestMapping("warehouse/manager") +@RequestMapping("api/manager") public class ManagerController { @Autowired private ManagerService managerService; diff --git a/src/main/java/com/podzilla/warehouse/Controllers/PackagedOrdersController.java b/src/main/java/com/podzilla/warehouse/Controllers/PackagedOrdersController.java index d8d7d03..f6a5c66 100644 --- a/src/main/java/com/podzilla/warehouse/Controllers/PackagedOrdersController.java +++ b/src/main/java/com/podzilla/warehouse/Controllers/PackagedOrdersController.java @@ -14,7 +14,7 @@ import java.util.UUID; @RestController -@RequestMapping("warehouse/package") +@RequestMapping("api/package") @Validated public class PackagedOrdersController { diff --git a/src/main/java/com/podzilla/warehouse/Controllers/PackagerController.java b/src/main/java/com/podzilla/warehouse/Controllers/PackagerController.java index bf898a8..dba15fc 100644 --- a/src/main/java/com/podzilla/warehouse/Controllers/PackagerController.java +++ b/src/main/java/com/podzilla/warehouse/Controllers/PackagerController.java @@ -15,7 +15,7 @@ @Slf4j @RestController -@RequestMapping("warehouse/packagers") +@RequestMapping("api/packagers") public class PackagerController { private final PackagerService packagerService; diff --git a/src/main/java/com/podzilla/warehouse/Controllers/StockController.java b/src/main/java/com/podzilla/warehouse/Controllers/StockController.java index f9945fa..51c9b47 100644 --- a/src/main/java/com/podzilla/warehouse/Controllers/StockController.java +++ b/src/main/java/com/podzilla/warehouse/Controllers/StockController.java @@ -16,7 +16,7 @@ @Slf4j @RestController -@RequestMapping("/stock") +@RequestMapping("/api/stock") public class StockController { @Autowired diff --git a/src/main/java/com/podzilla/warehouse/Models/AssignedOrders.java b/src/main/java/com/podzilla/warehouse/Models/AssignedOrders.java index 148a7fa..43082c0 100644 --- a/src/main/java/com/podzilla/warehouse/Models/AssignedOrders.java +++ b/src/main/java/com/podzilla/warehouse/Models/AssignedOrders.java @@ -32,52 +32,17 @@ public class AssignedOrders { @CreationTimestamp private LocalDateTime assignedAt; - @Column(nullable = false) - @OneToMany(mappedBy = "packagedOrder") - private List items; - - @Column(nullable = false) - private DeliveryAddress deliveryAddress; - @Column(nullable = false) - private BigDecimal totalAmount; - @Column(nullable = false) - private double orderLatitude; - @Column(nullable = false) - private double orderLongitude; - @Column(nullable = false) - private String signature; - @Column(nullable = false) - private ConfirmationType confirmationType; - - public AssignedOrders(UUID orderId, UUID assignerId, UUID courierId, List items, - DeliveryAddress deliveryAddress, BigDecimal totalAmount, double orderLatitude, - double orderLongitude, String signature, ConfirmationType confirmationType) { + public AssignedOrders(UUID orderId, UUID assignerId, UUID courierId) { this.orderId = orderId; this.assignerId = assignerId; this.courierId = courierId; this.assignedAt = LocalDateTime.now(); - this.items = items; - this.deliveryAddress = deliveryAddress; - this.totalAmount = totalAmount; - this.orderLatitude = orderLatitude; - this.orderLongitude = orderLongitude; - this.signature = signature; - this.confirmationType = confirmationType; } - public AssignedOrders(UUID orderId, UUID assignerId, UUID courierId, LocalDateTime assignedAt, - List items, DeliveryAddress deliveryAddress, BigDecimal totalAmount, - double orderLatitude, double orderLongitude, String signature, ConfirmationType confirmationType) { + public AssignedOrders(UUID orderId, UUID assignerId, UUID courierId, LocalDateTime assignedAt) { this.orderId = orderId; this.assignerId = assignerId; this.courierId = courierId; this.assignedAt = assignedAt; - this.items = items; - this.deliveryAddress = deliveryAddress; - this.totalAmount = totalAmount; - this.orderLatitude = orderLatitude; - this.orderLongitude = orderLongitude; - this.signature = signature; - this.confirmationType = confirmationType; } } diff --git a/src/main/java/com/podzilla/warehouse/Models/Stock.java b/src/main/java/com/podzilla/warehouse/Models/Stock.java index a3c0331..81abb5b 100644 --- a/src/main/java/com/podzilla/warehouse/Models/Stock.java +++ b/src/main/java/com/podzilla/warehouse/Models/Stock.java @@ -34,9 +34,11 @@ public class Stock { @Column(nullable = false) private String category; + @ManyToOne @JoinColumn(name = "order_id", nullable = true) private PackagedOrders packagedOrder; + @CreationTimestamp @Column(updatable = false) private LocalDateTime createdAt; diff --git a/src/main/java/com/podzilla/warehouse/Services/AssignedOrdersService.java b/src/main/java/com/podzilla/warehouse/Services/AssignedOrdersService.java index 44a3d3b..5eb4fbd 100644 --- a/src/main/java/com/podzilla/warehouse/Services/AssignedOrdersService.java +++ b/src/main/java/com/podzilla/warehouse/Services/AssignedOrdersService.java @@ -48,20 +48,18 @@ public Optional> findByAssignerIdIsNull() { @CachePut(key = "'orderId:' + #orderId") public AssignedOrders assignOrder(UUID orderId, UUID assignerId, UUID courierId) { PackagedOrders packagedOrder = packagedOrdersRepository.findOneByOrderId(orderId).get(); - AssignedOrders assignment = new AssignedOrders(orderId, assignerId, courierId, packagedOrder.getItems(), - packagedOrder.getDeliveryAddress(), packagedOrder.getTotalAmount(), packagedOrder.getOrderLatitude(), - packagedOrder.getOrderLongitude(), packagedOrder.getSignature(), packagedOrder.getConfirmationType()); + AssignedOrders assignment = new AssignedOrders(orderId, assignerId, courierId); assignedOrdersRepository.save(assignment); OrderAssignedToCourierEvent event = EventFactory.createOrderAssignedToCourierEvent( orderId, courierId, - assignment.getTotalAmount(), - assignment.getOrderLatitude(), - assignment.getOrderLongitude(), - assignment.getSignature(), - assignment.getConfirmationType() + packagedOrder.getTotalAmount(), + packagedOrder.getOrderLatitude(), + packagedOrder.getOrderLongitude(), + packagedOrder.getSignature(), + packagedOrder.getConfirmationType() ); eventPublisher.publishEvent(EventsConstants.ORDER_ASSIGNED_TO_COURIER, event); diff --git a/src/test/java/com/podzilla/warehouse/WarehouseApplicationTests.java b/src/test/java/com/podzilla/warehouse/WarehouseApplicationTests.java deleted file mode 100644 index dc0376a..0000000 --- a/src/test/java/com/podzilla/warehouse/WarehouseApplicationTests.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.podzilla.warehouse; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class WarehouseApplicationTests { - -// @Test -// void contextLoads() { -// } -} diff --git a/src/test/java/com/podzilla/warehouse/e2e/E2eTestBase.java b/src/test/java/com/podzilla/warehouse/e2e/E2eTestBase.java new file mode 100644 index 0000000..473b844 --- /dev/null +++ b/src/test/java/com/podzilla/warehouse/e2e/E2eTestBase.java @@ -0,0 +1,37 @@ +package com.podzilla.warehouse.e2e; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.web.client.RestTemplate; + +/** + * Base class for E2E tests that interact with a running instance of the application. + * This assumes the application is running on localhost:8080 with context path /api. + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public abstract class E2eTestBase { + + protected static final String BASE_URL = "http://localhost:8080/api"; + protected RestTemplate restTemplate; + + @BeforeAll + public void setup() { + RestTemplateBuilder builder = new RestTemplateBuilder(); + restTemplate = builder + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) + .build(); + + // Verify the application is running + try { + restTemplate.getForEntity("http://localhost:8080//actuator/health", String.class); + } catch (Exception e) { + System.err.println("WARNING: The application does not appear to be running at " + BASE_URL); + System.err.println("Make sure to start the application using Docker before running these tests."); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/podzilla/warehouse/e2e/E2eTestUtils.java b/src/test/java/com/podzilla/warehouse/e2e/E2eTestUtils.java new file mode 100644 index 0000000..4597b14 --- /dev/null +++ b/src/test/java/com/podzilla/warehouse/e2e/E2eTestUtils.java @@ -0,0 +1,136 @@ +package com.podzilla.warehouse.e2e; + +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +/** + * Utility class for E2E tests with helper methods for common operations. + */ +public class E2eTestUtils { + + /** + * Performs a GET request to the specified endpoint. + * + * @param restTemplate The RestTemplate to use + * @param baseUrl The base URL of the API + * @param endpoint The endpoint to call (without the base URL) + * @param responseType The expected response type + * @return The response entity + */ + public static ResponseEntity get(RestTemplate restTemplate, String baseUrl, String endpoint, Class responseType) { + String url = baseUrl + endpoint; + return restTemplate.getForEntity(url, responseType); + } + + /** + * Performs a GET request to the specified endpoint with a parameterized type reference. + * + * @param restTemplate The RestTemplate to use + * @param baseUrl The base URL of the API + * @param endpoint The endpoint to call (without the base URL) + * @param typeReference The parameterized type reference for the response + * @return The response entity + */ + public static ResponseEntity get(RestTemplate restTemplate, String baseUrl, String endpoint, ParameterizedTypeReference typeReference) { + String url = baseUrl + endpoint; + return restTemplate.exchange(url, HttpMethod.GET, null, typeReference); + } + + /** + * Performs a POST request to the specified endpoint with the given request body. + * + * @param restTemplate The RestTemplate to use + * @param baseUrl The base URL of the API + * @param endpoint The endpoint to call (without the base URL) + * @param requestBody The request body + * @param responseType The expected response type + * @return The response entity + */ + public static ResponseEntity post(RestTemplate restTemplate, String baseUrl, String endpoint, Object requestBody, Class responseType) { + String url = baseUrl + endpoint; + return restTemplate.postForEntity(url, requestBody, responseType); + } + + /** + * Performs a POST request to the specified endpoint with the given request body and a parameterized type reference. + * + * @param restTemplate The RestTemplate to use + * @param baseUrl The base URL of the API + * @param endpoint The endpoint to call (without the base URL) + * @param requestBody The request body + * @param typeReference The parameterized type reference for the response + * @return The response entity + */ + public static ResponseEntity post(RestTemplate restTemplate, String baseUrl, String endpoint, Object requestBody, ParameterizedTypeReference typeReference) { + String url = baseUrl + endpoint; + HttpEntity requestEntity = new HttpEntity<>(requestBody); + return restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeReference); + } + + /** + * Performs a PUT request to the specified endpoint with the given request body. + * + * @param restTemplate The RestTemplate to use + * @param baseUrl The base URL of the API + * @param endpoint The endpoint to call (without the base URL) + * @param requestBody The request body + * @param responseType The expected response type + * @return The response entity + */ + public static ResponseEntity put(RestTemplate restTemplate, String baseUrl, String endpoint, Object requestBody, Class responseType) { + String url = baseUrl + endpoint; + HttpEntity requestEntity = new HttpEntity<>(requestBody); + return restTemplate.exchange(url, HttpMethod.PUT, requestEntity, responseType); + } + + /** + * Performs a PUT request to the specified endpoint with the given request body and a parameterized type reference. + * + * @param restTemplate The RestTemplate to use + * @param baseUrl The base URL of the API + * @param endpoint The endpoint to call (without the base URL) + * @param requestBody The request body + * @param typeReference The parameterized type reference for the response + * @return The response entity + */ + public static ResponseEntity put(RestTemplate restTemplate, String baseUrl, String endpoint, Object requestBody, ParameterizedTypeReference typeReference) { + String url = baseUrl + endpoint; + HttpEntity requestEntity = new HttpEntity<>(requestBody); + return restTemplate.exchange(url, HttpMethod.PUT, requestEntity, typeReference); + } + + /** + * Performs a DELETE request to the specified endpoint. + * + * @param restTemplate The RestTemplate to use + * @param baseUrl The base URL of the API + * @param endpoint The endpoint to call (without the base URL) + * @param responseType The expected response type + * @return The response entity + */ + public static ResponseEntity delete(RestTemplate restTemplate, String baseUrl, String endpoint, Class responseType) { + String url = baseUrl + endpoint; + HttpEntity requestEntity = new HttpEntity<>(null); + return restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, responseType); + } + + /** + * Performs a DELETE request to the specified endpoint with a parameterized type reference. + * + * @param restTemplate The RestTemplate to use + * @param baseUrl The base URL of the API + * @param endpoint The endpoint to call (without the base URL) + * @param typeReference The parameterized type reference for the response + * @return The response entity + */ + public static ResponseEntity delete(RestTemplate restTemplate, String baseUrl, String endpoint, ParameterizedTypeReference typeReference) { + String url = baseUrl + endpoint; + HttpEntity requestEntity = new HttpEntity<>(null); + return restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, typeReference); + } +} diff --git a/src/test/java/com/podzilla/warehouse/e2e/ManagerE2eTest.java b/src/test/java/com/podzilla/warehouse/e2e/ManagerE2eTest.java new file mode 100644 index 0000000..ddbfc5e --- /dev/null +++ b/src/test/java/com/podzilla/warehouse/e2e/ManagerE2eTest.java @@ -0,0 +1,202 @@ +package com.podzilla.warehouse.e2e; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * E2E tests for the Manager API. + * These tests interact with a running instance of the application. + * Make sure the application is running on localhost:8080 before running these tests. + */ +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class ManagerE2eTest extends E2eTestBase { + + private static UUID createdManagerId; + private static final String MANAGER_ENDPOINT = "/manager"; + + @Test + @Order(1) + public void testCreateManager() { + // Prepare test data + Map managerData = new HashMap<>(); + managerData.put("name", "E2E Test Manager"); + managerData.put("email", "e2e-test-manager@example.com"); + managerData.put("department", "E2E Testing"); + managerData.put("phoneNumber", "123-456-7890"); + + // Send request + ResponseEntity> response = E2eTestUtils.post( + restTemplate, + BASE_URL, + MANAGER_ENDPOINT + "/create", + managerData, + new ParameterizedTypeReference>() {} + ); + + // Verify response + assertEquals(HttpStatus.CREATED, response.getStatusCode()); + assertNotNull(response.getBody()); + + Map manager = response.getBody(); + assertNotNull(manager.get("id")); + assertEquals("E2E Test Manager", manager.get("name")); + assertEquals("e2e-test-manager@example.com", manager.get("email")); + assertEquals("E2E Testing", manager.get("department")); + assertEquals("123-456-7890", manager.get("phoneNumber")); + + // Save the ID for later tests + createdManagerId = UUID.fromString(manager.get("id").toString()); + } + + @Test + @Order(2) + public void testGetManagerById() { + // Send request + ResponseEntity> response = E2eTestUtils.get( + restTemplate, + BASE_URL, + MANAGER_ENDPOINT + "/" + createdManagerId, + new ParameterizedTypeReference>() {} + ); + + // Verify response + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + + Map manager = response.getBody(); + assertEquals(createdManagerId.toString(), manager.get("id").toString()); + assertEquals("E2E Test Manager", manager.get("name")); + assertEquals("e2e-test-manager@example.com", manager.get("email")); + assertEquals("E2E Testing", manager.get("department")); + } + + @Test + @Order(3) + public void testGetAllManagers() { + // Send request + ResponseEntity>> response = E2eTestUtils.get( + restTemplate, + BASE_URL, + MANAGER_ENDPOINT + "/all", + new ParameterizedTypeReference>>() {} + ); + + // Verify response + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + assertFalse(response.getBody().isEmpty()); + } + + @Test + @Order(4) + public void testUpdateManager() { + // Prepare test data + Map managerData = new HashMap<>(); + managerData.put("id", createdManagerId.toString()); + managerData.put("name", "Updated E2E Test Manager"); + managerData.put("email", "updated-e2e-test-manager@example.com"); + managerData.put("department", "Updated E2E Testing"); + managerData.put("phoneNumber", "987-654-3210"); + managerData.put("active", true); + + // Send request + ResponseEntity> response = E2eTestUtils.put( + restTemplate, + BASE_URL, + MANAGER_ENDPOINT + "/update/" + createdManagerId, + managerData, + new ParameterizedTypeReference>() {} + ); + + // Verify response + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + + Map manager = response.getBody(); + assertEquals(createdManagerId.toString(), manager.get("id").toString()); + assertEquals("Updated E2E Test Manager", manager.get("name")); + assertEquals("updated-e2e-test-manager@example.com", manager.get("email")); + assertEquals("Updated E2E Testing", manager.get("department")); + assertEquals("987-654-3210", manager.get("phoneNumber")); + } + + @Test + @Order(5) + public void testDeactivateManager() { + // Send request + ResponseEntity> response = E2eTestUtils.put( + restTemplate, + BASE_URL, + MANAGER_ENDPOINT + "/deactivate/" + createdManagerId, + null, + new ParameterizedTypeReference>() {} + ); + + // Verify response + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + + Map manager = response.getBody(); + assertEquals(createdManagerId.toString(), manager.get("id").toString()); + assertEquals(false, manager.get("active")); + } + + @Test + @Order(6) + public void testActivateManager() { + // Send request + ResponseEntity> response = E2eTestUtils.put( + restTemplate, + BASE_URL, + MANAGER_ENDPOINT + "/activate/" + createdManagerId, + null, + new ParameterizedTypeReference>() {} + ); + + // Verify response + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + + Map manager = response.getBody(); + assertEquals(createdManagerId.toString(), manager.get("id").toString()); + assertEquals(true, manager.get("active")); + } + + @Test + @Order(7) + public void testDeleteManager() { + // Send request + ResponseEntity> response = E2eTestUtils.delete( + restTemplate, + BASE_URL, + MANAGER_ENDPOINT + "/delete/" + createdManagerId, + new ParameterizedTypeReference>() {} + ); + + // Verify response + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + assertEquals("Manager successfully deleted", response.getBody().get("message")); + + // Verify the manager is deleted + ResponseEntity> getResponse = E2eTestUtils.get( + restTemplate, + BASE_URL, + MANAGER_ENDPOINT + "/" + createdManagerId, + new ParameterizedTypeReference>() {} + ); + assertEquals(HttpStatus.NOT_FOUND, getResponse.getStatusCode()); + } +}