diff --git a/omod/src/main/java/org/openmrs/module/queue/web/Legacy1xRestController.java b/omod/src/main/java/org/openmrs/module/queue/web/Legacy1xRestController.java index b1fa7f7..1c29561 100644 --- a/omod/src/main/java/org/openmrs/module/queue/web/Legacy1xRestController.java +++ b/omod/src/main/java/org/openmrs/module/queue/web/Legacy1xRestController.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; @@ -199,27 +200,44 @@ public Object getQueueMetrics(HttpServletRequest request) { @ResponseBody public Object assignTicketToServicePoint(HttpServletRequest request) throws Exception { String requestBody = IOUtils.toString(request.getReader()); - if (requestBody != null) { - ObjectMapper mapper = new ObjectMapper(); - JsonNode actualObj = mapper.readTree(requestBody); - - if (!actualObj.has("ticketNumber")) { - String msg = "No ticketNumber passed, skipping ticket assignment"; - return new ResponseEntity(msg, new HttpHeaders(), HttpStatus.OK); - } - - String servicePointName = actualObj.get("servicePointName").textValue(); - String ticketNumber = actualObj.get("ticketNumber").textValue(); - String status = actualObj.get("status").textValue(); - - if (servicePointName.isEmpty() || ticketNumber.isEmpty() || status.isEmpty()) { - return new ResponseEntity("One of the required fields is empty", new HttpHeaders(), BAD_REQUEST); - } - - QueueTicketAssignments.updateTicketAssignment(servicePointName, ticketNumber, status); - return new ResponseEntity("Ticket successfully assigned!", new HttpHeaders(), HttpStatus.OK); + if (requestBody == null || requestBody.isBlank()) { + return new ResponseEntity("The request could not be interpreted", new HttpHeaders(), BAD_REQUEST); + } + ObjectMapper mapper = new ObjectMapper(); + JsonNode actualObj; + try { + actualObj = mapper.readTree(requestBody); + } + catch (JsonProcessingException e) { + return new ResponseEntity("The request could not be interpreted", new HttpHeaders(), BAD_REQUEST); } - return new ResponseEntity("The request could not be interpreted", new HttpHeaders(), BAD_REQUEST); + + if (!actualObj.has("ticketNumber")) { + String msg = "No ticketNumber passed, skipping ticket assignment"; + return new ResponseEntity(msg, new HttpHeaders(), HttpStatus.OK); + } + + JsonNode servicePointNameNode = actualObj.path("servicePointName"); + JsonNode ticketNumberNode = actualObj.path("ticketNumber"); + JsonNode statusNode = actualObj.path("status"); + + if (servicePointNameNode.isMissingNode() || servicePointNameNode.isNull() || !servicePointNameNode.isTextual() + || ticketNumberNode.isMissingNode() || ticketNumberNode.isNull() || !ticketNumberNode.isTextual() + || statusNode.isMissingNode() || statusNode.isNull() || !statusNode.isTextual()) { + return new ResponseEntity("One of the required fields is missing or is not a string", new HttpHeaders(), + BAD_REQUEST); + } + + String servicePointName = servicePointNameNode.textValue(); + String ticketNumber = ticketNumberNode.textValue(); + String status = statusNode.textValue(); + + if (servicePointName.isEmpty() || ticketNumber.isEmpty() || status.isEmpty()) { + return new ResponseEntity("One of the required fields is empty", new HttpHeaders(), BAD_REQUEST); + } + + QueueTicketAssignments.updateTicketAssignment(servicePointName, ticketNumber, status); + return new ResponseEntity("Ticket successfully assigned!", new HttpHeaders(), HttpStatus.OK); } @RequestMapping(method = GET, value = "/rest/" + RestConstants.VERSION_1 + "/queueutil/active-tickets") diff --git a/omod/src/test/java/org/openmrs/module/queue/web/Legacy1xRestControllerAssignTicketTest.java b/omod/src/test/java/org/openmrs/module/queue/web/Legacy1xRestControllerAssignTicketTest.java new file mode 100644 index 0000000..c0c1b21 --- /dev/null +++ b/omod/src/test/java/org/openmrs/module/queue/web/Legacy1xRestControllerAssignTicketTest.java @@ -0,0 +1,112 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.queue.web; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.OK; + +import javax.servlet.http.HttpServletRequest; + +import java.io.BufferedReader; +import java.io.StringReader; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openmrs.module.queue.api.QueueServicesWrapper; +import org.springframework.http.ResponseEntity; + +@ExtendWith(MockitoExtension.class) +public class Legacy1xRestControllerAssignTicketTest { + + private Legacy1xRestController controller; + + @Mock + private QueueServicesWrapper services; + + @BeforeEach + public void setUp() { + controller = new Legacy1xRestController(services); + } + + private HttpServletRequest mockRequestWithBody(String body) throws Exception { + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getReader()).thenReturn(new BufferedReader(new StringReader(body))); + return request; + } + + @Test + public void assignTicket_shouldReturn400WhenBodyIsEmpty() throws Exception { + HttpServletRequest request = mockRequestWithBody(""); + ResponseEntity response = (ResponseEntity) controller.assignTicketToServicePoint(request); + assertThat(response.getStatusCode(), equalTo(BAD_REQUEST)); + } + + @Test + public void assignTicket_shouldReturn400WhenBodyIsInvalidJson() throws Exception { + HttpServletRequest request = mockRequestWithBody("not-json{{{"); + ResponseEntity response = (ResponseEntity) controller.assignTicketToServicePoint(request); + assertThat(response.getStatusCode(), equalTo(BAD_REQUEST)); + } + + @Test + public void assignTicket_shouldReturnOkWhenTicketNumberIsMissing() throws Exception { + // When ticketNumber is absent, the endpoint intentionally skips assignment and returns 200 + HttpServletRequest request = mockRequestWithBody("{\"servicePointName\":\"Room1\",\"status\":\"pending\"}"); + ResponseEntity response = (ResponseEntity) controller.assignTicketToServicePoint(request); + assertThat(response.getStatusCode(), equalTo(OK)); + } + + @Test + public void assignTicket_shouldReturn400WhenServicePointNameIsMissing() throws Exception { + HttpServletRequest request = mockRequestWithBody( + "{\"ticketNumber\":\"T001\",\"status\":\"pending\"}"); + ResponseEntity response = (ResponseEntity) controller.assignTicketToServicePoint(request); + assertThat(response.getStatusCode(), equalTo(BAD_REQUEST)); + } + + @Test + public void assignTicket_shouldReturn400WhenStatusIsNull() throws Exception { + HttpServletRequest request = mockRequestWithBody( + "{\"servicePointName\":\"Room1\",\"ticketNumber\":\"T001\",\"status\":null}"); + ResponseEntity response = (ResponseEntity) controller.assignTicketToServicePoint(request); + assertThat(response.getStatusCode(), equalTo(BAD_REQUEST)); + } + + @Test + public void assignTicket_shouldReturn400WhenServicePointNameIsNonStringType() throws Exception { + HttpServletRequest request = mockRequestWithBody( + "{\"servicePointName\":123,\"ticketNumber\":\"T001\",\"status\":\"pending\"}"); + ResponseEntity response = (ResponseEntity) controller.assignTicketToServicePoint(request); + assertThat(response.getStatusCode(), equalTo(BAD_REQUEST)); + } + + @Test + public void assignTicket_shouldReturn400WhenStatusIsEmpty() throws Exception { + HttpServletRequest request = mockRequestWithBody( + "{\"servicePointName\":\"Room1\",\"ticketNumber\":\"T001\",\"status\":\"\"}"); + ResponseEntity response = (ResponseEntity) controller.assignTicketToServicePoint(request); + assertThat(response.getStatusCode(), equalTo(BAD_REQUEST)); + } + + @Test + public void assignTicket_shouldReturn200WhenAllFieldsAreValid() throws Exception { + HttpServletRequest request = mockRequestWithBody( + "{\"servicePointName\":\"Room1\",\"ticketNumber\":\"T001\",\"status\":\"pending\"}"); + ResponseEntity response = (ResponseEntity) controller.assignTicketToServicePoint(request); + assertThat(response.getStatusCode(), equalTo(OK)); + } +}