/* * Copyright 2016 The Project Buendia Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distrib- * uted under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, either express or implied. See the License for * specific language governing permissions and limitations under the License. */ package org.openmrs.projectbuendia.webservices.rest; import org.junit.Before; import org.junit.Test; import org.openmrs.Order; import org.openmrs.api.OrderService; import org.openmrs.api.context.Context; import org.openmrs.module.webservices.rest.SimpleObject; import org.openmrs.module.webservices.rest.web.v1_0.controller.MainResourceControllerTest; import org.openmrs.test.BaseModuleContextSensitiveTest; import org.openmrs.test.SkipBaseSetup; import org.springframework.mock.web.MockHttpServletRequest; import javax.annotation.Nullable; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * Tests for {@link OrderResource}. * * This test class is unusual in that it has two purposes: * - it incorporates some smoke tests for querying as a result of inheriting from * {@link MainResourceControllerTest}. We don't bother testing any further here; our main query * tests are in {@code HibernateProjectBuendiaDAOTest} and subclasses. * - Testing that updates, deletions and revisions work correctly. */ @SkipBaseSetup public class OrderResourceTest extends MainResourceControllerTest { private static final String BASE_DATASET = "org/openmrs/projectbuendia/webservices/rest/baseMetaDataSet.xml"; private static final String BASE_ORDER_DATASET = "org/openmrs/projectbuendia/webservices/rest/order-test-base-data.xml"; private static final String TEST_DATASET = "org/openmrs/projectbuendia/webservices/rest/single-order.xml"; private static final String BASE_URL = "/projectbuendia/orders"; private static final String ENCOUNTERS_URL = "/projectbuendia/encounters"; private static final long ONE_DAY_IN_MILLIS = 1000 * 60 * 60 * 24; private static final long ONE_WEEK_IN_MILLIS = ONE_DAY_IN_MILLIS * 7; private static final String SAMPLE_PATIENT_UUID = "5946f880-b197-400b-9caa-a3c661d23041"; private static final String SAMPLE_INSTRUCTIONS = "Paracetamol 1000mg 4x daily"; private static final long SAMPLE_START_DATE = 1420602264000L; private static final long SAMPLE_END_DATE = SAMPLE_START_DATE + ONE_WEEK_IN_MILLIS; private OrderService orderService; /** * {@link BaseModuleContextSensitiveTest} does this initialization, but also pre-loads the * database with a bunch of records. We don't want to load those records, * because we'd then have to augment them with `buendia_[type]_sync_map` records, which would * couple our test integrity to the records in OpenMRS' test data. For this reason, we disable * {@link BaseModuleContextSensitiveTest}'s setup by putting the {@link SkipBaseSetup} * annotation on the class, but then we've got to explicitly init the database and authenticate * ourselves. */ @Before public void setUp() throws Exception { orderService = Context.getOrderService(); if (useInMemoryDatabase()) { initializeInMemoryDatabase(); authenticate(); } executeDataSet(BASE_DATASET); executeDataSet(BASE_ORDER_DATASET); executeDataSet(TEST_DATASET); } @Override public String getURI() { return "projectbuendia/orders"; } @Override public String getUuid() { // From the dataset file. return "aaaaa"; } @Override public long getAllCount() { // From the dataset file. return 1; } @Test public void testOrderCreationWithAllDataPopulated() throws Exception { SimpleObject input = newOrderJson( SAMPLE_PATIENT_UUID, SAMPLE_INSTRUCTIONS, SAMPLE_START_DATE, SAMPLE_END_DATE); MockHttpServletRequest request = newPostRequest(BASE_URL, input); SimpleObject response = deserialize(handle(request)); String uuid = (String) response.get(OrderResource.UUID); // Check that fields are correctly set in response assertEquals(SAMPLE_PATIENT_UUID, response.get(OrderResource.PATIENT_UUID)); assertEquals(SAMPLE_INSTRUCTIONS, response.get(OrderResource.INSTRUCTIONS)); assertEquals(SAMPLE_START_DATE, response.get(OrderResource.START_MILLIS)); assertEquals(SAMPLE_END_DATE, response.get(OrderResource.STOP_MILLIS)); // Check that these fields match the object stored. Order stored = orderService.getOrderByUuid(uuid); assertEquals(SAMPLE_PATIENT_UUID, stored.getPatient().getUuid()); assertEquals(SAMPLE_INSTRUCTIONS, stored.getInstructions()); assertEquals(SAMPLE_START_DATE, stored.getScheduledDate().getTime()); assertEquals(SAMPLE_END_DATE, stored.getAutoExpireDate().getTime()); } @Test public void testOrderCreationWithoutPatientThrowsException() throws Exception { SimpleObject input = newOrderJson( null, SAMPLE_INSTRUCTIONS, SAMPLE_START_DATE, SAMPLE_END_DATE); MockHttpServletRequest request = newPostRequest(BASE_URL, input); try { handle(request); fail("Expected handling this request to throw an exception"); } catch (Exception ignored) { } } @Test public void testOrderCreationWithoutStartDateReturnsThrowsException() throws Exception { SimpleObject input = newOrderJson( SAMPLE_PATIENT_UUID, SAMPLE_INSTRUCTIONS, null, SAMPLE_END_DATE); MockHttpServletRequest request = newPostRequest(BASE_URL, input); try { handle(request); fail("Expected handling this request to throw an exception"); } catch (Exception ignored) { } } @Test public void testOrderCreationWithoutEndDateIsAccepted() throws Exception { SimpleObject input = newOrderJson( SAMPLE_PATIENT_UUID, SAMPLE_INSTRUCTIONS, SAMPLE_START_DATE, null); MockHttpServletRequest request = newPostRequest(BASE_URL, input); SimpleObject response = deserialize(handle(request)); String uuid = (String) response.get(OrderResource.UUID); // Check that fields are correctly set in response assertEquals(SAMPLE_PATIENT_UUID, response.get(OrderResource.PATIENT_UUID)); assertEquals(SAMPLE_INSTRUCTIONS, response.get(OrderResource.INSTRUCTIONS)); assertEquals(SAMPLE_START_DATE, response.get(OrderResource.START_MILLIS)); assertTrue("Response contains stop_millis, even if it's not set", response.containsKey(OrderResource.STOP_MILLIS)); assertNull(response.get(OrderResource.STOP_MILLIS)); // Check that these fields match the object stored. Order stored = orderService.getOrderByUuid(uuid); assertEquals(SAMPLE_PATIENT_UUID, stored.getPatient().getUuid()); assertEquals(SAMPLE_INSTRUCTIONS, stored.getInstructions()); assertEquals(SAMPLE_START_DATE, stored.getScheduledDate().getTime()); assertNull(stored.getAutoExpireDate()); } @Test public void testUpdateForOrderOlderThan24HrsIsARevision() throws Exception { String newInstructions = "Some instructions?"; Order baseOrder = createExpiredOrderOlderThan24Hrs(); SimpleObject newDetails = newOrderJson(null, newInstructions, null, null); MockHttpServletRequest request = newPostRequest(BASE_URL + "/" + baseOrder.getUuid(), newDetails); SimpleObject response = deserialize(handle(request)); String uuid = (String) response.get(OrderResource.UUID); // Check that it's returning the same UUID assertEquals(baseOrder.getUuid(), uuid); // Check that fields are correctly set in response assertEquals(SAMPLE_PATIENT_UUID, response.get(OrderResource.PATIENT_UUID)); assertEquals(newInstructions, response.get(OrderResource.INSTRUCTIONS)); assertEquals(SAMPLE_START_DATE, response.get(OrderResource.START_MILLIS)); assertEquals(SAMPLE_END_DATE, response.get(OrderResource.STOP_MILLIS)); // Check that the underlying order is a different one and has the correct values. Order stored = OrderResource.getLatestVersion(orderService.getOrderByUuid(uuid)); assertEquals(SAMPLE_PATIENT_UUID, stored.getPatient().getUuid()); assertEquals(newInstructions, stored.getInstructions()); assertEquals(SAMPLE_START_DATE, stored.getScheduledDate().getTime()); assertEquals(SAMPLE_END_DATE, stored.getAutoExpireDate().getTime()); } @Test public void testUpdateForExecutedOrderIsARevision() throws Exception { Order baseOrder = createOrderStartingNow(); executeOrder(baseOrder); long startTime = baseOrder.getScheduledDate().getTime(); long newEndTime = System.currentTimeMillis() + 2 * ONE_WEEK_IN_MILLIS; SimpleObject newDetails = newOrderJson(null, null, null, newEndTime); MockHttpServletRequest request = newPostRequest(BASE_URL + "/" + baseOrder.getUuid(), newDetails); SimpleObject response = deserialize(handle(request)); String uuid = (String) response.get(OrderResource.UUID); // The client should get the same UUID, but in storage, it should be a different order. assertEquals(baseOrder.getUuid(), uuid); // Check that fields are correctly set in response assertEquals(SAMPLE_PATIENT_UUID, response.get(OrderResource.PATIENT_UUID)); assertEquals(SAMPLE_INSTRUCTIONS, response.get(OrderResource.INSTRUCTIONS)); assertEquals(startTime, response.get(OrderResource.START_MILLIS)); assertEquals(newEndTime, response.get(OrderResource.STOP_MILLIS)); // Check that these fields match the object stored. Order stored = orderService.getRevisionOrder(orderService.getOrderByUuid(uuid)); assertEquals(SAMPLE_PATIENT_UUID, stored.getPatient().getUuid()); assertEquals(SAMPLE_INSTRUCTIONS, stored.getInstructions()); assertEquals(startTime, stored.getScheduledDate().getTime()); assertEquals(newEndTime, stored.getAutoExpireDate().getTime()); } @Test public void testDeleteForNewNonExecutedOrderVoids() throws Exception { Order order = createOrderStartingNow(); String uuid = order.getUuid(); MockHttpServletRequest request = newDeleteRequest(BASE_URL + "/" + uuid); handle(request); assertTrue("Order is voided", orderService.getOrderByUuid(uuid).isVoided()); } @Test public void testDeleteForExecutedOrderVoids() throws Exception { Order baseOrder = createOrderStartingNow(); executeOrder(baseOrder); String uuid = baseOrder.getUuid(); MockHttpServletRequest request = newDeleteRequest(BASE_URL + "/" + uuid); handle(request); OrderService service = orderService; Order order = service.getOrderByUuid(uuid); assertTrue("Order is voided", order.isVoided()); } @Test public void testDeleteForRevisedOrderVoidsAll() throws Exception { Order baseOrder = createOrderStartingNow(); String baseUuid = baseOrder.getUuid(); SimpleObject newDetails = newOrderJson(null, "New instructions!", null, null); MockHttpServletRequest request = newPostRequest(BASE_URL + "/" + baseUuid, newDetails); // Make the update. handle(request); request = newDeleteRequest(BASE_URL + "/" + baseUuid); handle(request); // Reload the base order from storage baseOrder = orderService.getOrderByUuid(baseUuid); assertTrue("Base order is voided", baseOrder.isVoided()); Order revisionOrder = OrderResource.getLatestVersion(baseOrder); assertNotNull("Expected a non-null revision order", revisionOrder); assertTrue("Revision order is voided", revisionOrder.isVoided()); } private Order createExpiredOrderOlderThan24Hrs() throws Exception { SimpleObject input = newOrderJson( SAMPLE_PATIENT_UUID, SAMPLE_INSTRUCTIONS, SAMPLE_START_DATE, SAMPLE_END_DATE); SimpleObject response = deserialize(handle(newPostRequest(BASE_URL, input))); String uuid = (String) response.get(OrderResource.UUID); return orderService.getOrderByUuid(uuid); } private Order createOrderStartingNow() throws Exception { long now = System.currentTimeMillis(); SimpleObject input = newOrderJson( SAMPLE_PATIENT_UUID, SAMPLE_INSTRUCTIONS, now, now + ONE_WEEK_IN_MILLIS); SimpleObject response = deserialize(handle(newPostRequest(BASE_URL, input))); String uuid = (String) response.get(OrderResource.UUID); return orderService.getOrderByUuid(uuid); } private void executeOrder(Order order) throws Exception { SimpleObject input = new SimpleObject() .add("uuid", order.getPatient().getUuid()) .add("order_uuids", new String[]{order.getUuid()}); handle(newPostRequest(ENCOUNTERS_URL, input)); } // Other test cases: // - Delete, more than 24 hrs old // - Delete, executed // DONE // - Update, more than 24 hrs old // - Update, executed // - Update, less than 24 hrs, not executed // - Delete less than 24 hrs, not executed // - Delete, order has expired private static SimpleObject newOrderJson( @Nullable String patientUuid, @Nullable String instructions, @Nullable Long startMillis, @Nullable Long stopMillis) { SimpleObject order = new SimpleObject(); if (patientUuid != null) { order.add(OrderResource.PATIENT_UUID, patientUuid); } if (instructions != null) { order.add(OrderResource.INSTRUCTIONS, instructions); } if (startMillis != null) { order.add(OrderResource.START_MILLIS, startMillis); } if (stopMillis != null) { order.add(OrderResource.STOP_MILLIS, stopMillis); } return order; } }