2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright © 2009 Regents of the University of California
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
15 * https://source.collectionspace.org/collection-space/LICENSE.txt
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
23 package org.collectionspace.services.client.test;
25 import java.util.List;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.Response;
30 import org.dom4j.Element;
31 import org.collectionspace.services.client.CollectionSpaceClient;
32 import org.collectionspace.services.client.IntakeClient;
33 import org.collectionspace.services.client.PayloadInputPart;
34 import org.collectionspace.services.client.PayloadOutputPart;
35 import org.collectionspace.services.client.PoxPayloadIn;
36 import org.collectionspace.services.client.PoxPayloadOut;
37 import org.collectionspace.services.common.api.GregorianCalendarDateTimeUtils;
38 import org.collectionspace.services.intake.EntryMethodList;
39 import org.collectionspace.services.intake.FieldCollectionEventNameList;
40 import org.collectionspace.services.intake.CurrentLocationGroup;
41 import org.collectionspace.services.intake.CurrentLocationGroupList;
42 import org.collectionspace.services.intake.IntakesCommon;
43 import org.collectionspace.services.jaxb.AbstractCommonList;
44 import org.testng.Assert;
45 import org.testng.annotations.Test;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 // FIXME: http://issues.collectionspace.org/browse/CSPACE-1685
51 * IntakeServiceTest, carries out tests against a
52 * deployed and running Intake Service.
54 * $LastChangedRevision$
57 public class IntakeServiceTest extends AbstractPoxServiceTestImpl<AbstractCommonList, IntakesCommon> {
60 private final String CLASS_NAME = IntakeServiceTest.class.getName();
61 private final Logger logger = LoggerFactory.getLogger(IntakeServiceTest.class);
62 private final static String CURRENT_DATE_UTC =
63 GregorianCalendarDateTimeUtils.currentDateUTC();
66 protected CollectionSpaceClient getClientInstance() throws Exception {
67 return new IntakeClient();
71 protected CollectionSpaceClient getClientInstance(String clientPropertiesFilename) throws Exception {
72 return new IntakeClient(clientPropertiesFilename);
76 protected String getServiceName() {
77 return IntakeClient.SERVICE_NAME;
80 // ---------------------------------------------------------------
81 // CRUD tests : READ tests
82 // ---------------------------------------------------------------
84 protected void compareReadInstances(IntakesCommon original, IntakesCommon fromRead) throws Exception {
85 // Verify the number and contents of values in repeatable fields,
86 // as created in the instance record used for testing.
87 List<String> entryMethods =
88 fromRead.getEntryMethods().getEntryMethod();
89 Assert.assertTrue(entryMethods.size() > 0);
90 Assert.assertNotNull(entryMethods.get(0));
92 List<String> fieldCollectionEventNames =
93 fromRead.getFieldCollectionEventNames().getFieldCollectionEventName();
94 Assert.assertTrue(fieldCollectionEventNames.size() > 0);
95 Assert.assertNotNull(fieldCollectionEventNames.get(0));
97 CurrentLocationGroupList currentLocationGroupList = fromRead.getCurrentLocationGroupList();
98 Assert.assertNotNull(currentLocationGroupList);
99 List<CurrentLocationGroup> currentLocationGroups = currentLocationGroupList.getCurrentLocationGroup();
100 Assert.assertNotNull(currentLocationGroups);
101 Assert.assertTrue(currentLocationGroups.size() > 0);
102 CurrentLocationGroup currentLocationGroup = currentLocationGroups.get(0);
103 Assert.assertNotNull(currentLocationGroup);
104 Assert.assertNotNull(currentLocationGroup.getCurrentLocationNote());
106 // Check the values of fields containing Unicode UTF-8 (non-Latin-1) characters.
107 if (logger.isDebugEnabled()) {
108 logger.debug("UTF-8 data sent=" + getUTF8DataFragment() + "\n"
109 + "UTF-8 data received=" + fromRead.getEntryNote());
111 Assert.assertEquals(fromRead.getEntryNote(), getUTF8DataFragment(),
112 "UTF-8 data retrieved '" + fromRead.getEntryNote()
113 + "' does not match expected data '" + getUTF8DataFragment());
117 public void delete(String testName) throws Exception {
118 // Do nothing because this test is not ready to delete the "knownResourceId".
119 // Instead, the method localDelete() will get called later in the dependency chain. The
120 // method localDelete() has a dependency on the test "verifyReadOnlyCoreFields". Once the "verifyReadOnlyCoreFields"
121 // test is run, the localDelete() test/method will get run. The localDelete() test/method in turn
122 // calls the inherited delete() test/method.
125 @Test(dataProvider = "testName", dependsOnMethods = {"CRUDTests", "verifyReadOnlyCoreFields"})
126 public void localDelete(String testName) throws Exception {
127 // Because of issues with TestNG not allowing @Test annotations on on override methods,
128 // and because we want the "updateWrongUser" to run before the "delete" test, we need
129 // this method. This method will call super.delete() after all the dependencies have been
131 super.delete(testName);
134 @Test(dataProvider = "testName", dependsOnMethods = {"CRUDTests"})
135 public void verifyReadOnlyCoreFields(String testName) throws Exception {
136 // TODO These should be in some core client utils
137 final String COLLECTIONSPACE_CORE_SCHEMA = "collectionspace_core";
138 final String COLLECTIONSPACE_CORE_TENANTID = "tenantId";
139 final String COLLECTIONSPACE_CORE_URI = "uri";
140 final String COLLECTIONSPACE_CORE_CREATED_AT = "createdAt";
141 final String COLLECTIONSPACE_CORE_UPDATED_AT = "updatedAt";
142 final String COLLECTIONSPACE_CORE_CREATED_BY = "createdBy";
143 final String COLLECTIONSPACE_CORE_UPDATED_BY = "updatedBy";
148 // Retrieve the contents of a resource to update.
149 IntakeClient client = new IntakeClient();
150 PoxPayloadIn input = null;
151 Response res = client.read(knownResourceId);
153 if (logger.isDebugEnabled()) {
154 logger.debug(testName + ": read status = " + res.getStatus());
156 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);
158 input = new PoxPayloadIn(res.readEntity(String.class));
163 PayloadInputPart payloadInputPart = input.getPart(COLLECTIONSPACE_CORE_SCHEMA);
164 Element coreAsElement = null;
165 if (payloadInputPart != null) {
166 coreAsElement = payloadInputPart.getElementBody();
168 Assert.assertNotNull(coreAsElement);
169 if (logger.isDebugEnabled()) {
170 logger.debug("Core part before update:");
171 logger.debug(coreAsElement.asXML());
174 // Update the read-only elements
175 Element tenantId = coreAsElement.element(COLLECTIONSPACE_CORE_TENANTID);
176 String originalTenantId = tenantId.getText();
177 tenantId.setText("foo");
178 Element uri = coreAsElement.element(COLLECTIONSPACE_CORE_URI);
179 String originalUri = uri.getText();
181 Element createdAt = coreAsElement.element(COLLECTIONSPACE_CORE_CREATED_AT);
182 String originalCreatedAt = createdAt.getText();
183 String now = GregorianCalendarDateTimeUtils.timestampUTC();
184 if(originalCreatedAt.equalsIgnoreCase(now) && logger.isWarnEnabled()) {
185 logger.warn("Cannot check createdAt read-only; too fast!");
187 createdAt.setText(now);
188 Element createdBy = coreAsElement.element(COLLECTIONSPACE_CORE_CREATED_BY);
189 String originalCreatedBy = createdBy.getText();
190 createdBy.setText("foo");
192 if (logger.isDebugEnabled()) {
193 logger.debug("Core part to be updated:");
194 logger.debug(coreAsElement.asXML());
197 // Create an output payload to send to the service, and add the common part
198 PoxPayloadOut output = new PoxPayloadOut(this.getServicePathComponent());
199 PayloadOutputPart corePart = output.addPart(COLLECTIONSPACE_CORE_SCHEMA, coreAsElement);
201 // Submit the request to the service and store the response.
202 res = client.update(knownResourceId, output);
204 int statusCode = res.getStatus();
205 // Check the status code of the response: does it match the expected response(s)?
206 if (logger.isDebugEnabled()) {
207 logger.debug(testName + ": status = " + statusCode);
209 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
210 invalidStatusCodeMessage(testRequestType, statusCode));
211 Assert.assertEquals(statusCode, testExpectedStatusCode);
213 input = new PoxPayloadIn(res.readEntity(String.class));
218 PayloadInputPart updatedCorePart = input.getPart(COLLECTIONSPACE_CORE_SCHEMA);
219 Element updatedCoreAsElement = null;
220 if (updatedCorePart != null) {
221 updatedCoreAsElement = updatedCorePart.getElementBody();
223 Assert.assertNotNull(updatedCoreAsElement);
225 tenantId = updatedCoreAsElement.element(COLLECTIONSPACE_CORE_TENANTID);
226 String updatedTenantId = tenantId.getText();
227 Assert.assertEquals(updatedTenantId, originalTenantId,
228 "CORE part TenantID was able to update!");
229 uri = updatedCoreAsElement.element(COLLECTIONSPACE_CORE_URI);
230 String updatedUri = uri.getText();
231 Assert.assertEquals(updatedUri, originalUri,
232 "CORE part URI was able to update!");
233 createdAt = updatedCoreAsElement.element(COLLECTIONSPACE_CORE_CREATED_AT);
234 String updatedCreatedAt = createdAt.getText();
235 Assert.assertEquals(updatedCreatedAt, originalCreatedAt,
236 "CORE part CreatedAt was able to update!");
237 createdBy = updatedCoreAsElement.element(COLLECTIONSPACE_CORE_CREATED_BY);
238 String updatedCreatedBy = createdBy.getText();
239 Assert.assertEquals(updatedCreatedBy, originalCreatedBy,
240 "CORE part CreatedBy was able to update!");
244 // ---------------------------------------------------------------
245 // Utility tests : tests of code used in tests above
246 // ---------------------------------------------------------------
249 * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
252 public String getServicePathComponent() {
253 return IntakeClient.SERVICE_PATH_COMPONENT;
257 * Creates the intake instance.
259 * @param identifier the identifier
260 * @return the multipart output
264 protected PoxPayloadOut createInstance(String identifier) throws Exception {
265 return createIntakeInstance(
266 "entryNumber-" + identifier,
268 "depositor-" + identifier);
272 * Creates the intake instance.
274 * @param entryNumber the entry number
275 * @param entryDate the entry date
276 * @param depositor the depositor
277 * @return the multipart output
280 private PoxPayloadOut createIntakeInstance(String entryNumber,
282 String depositor) throws Exception {
283 IntakesCommon intake = new IntakesCommon();
284 intake.setEntryNumber(entryNumber);
285 intake.setEntryDate(entryDate);
286 intake.setDepositor(depositor);
288 EntryMethodList entryMethodsList = new EntryMethodList();
289 List<String> entryMethods = entryMethodsList.getEntryMethod();
290 entryMethods.add("Left at doorstep");
291 entryMethods.add("Received via post");
292 intake.setEntryMethods(entryMethodsList);
294 FieldCollectionEventNameList eventNamesList = new FieldCollectionEventNameList();
295 List<String> eventNames = eventNamesList.getFieldCollectionEventName();
296 // FIXME Use properly formatted refNames for representative event names
297 // in this example test record. The following are mere placeholders.
298 eventNames.add("Field Collection Event Name-1");
299 eventNames.add("Field Collection Event Name-2");
300 intake.setFieldCollectionEventNames(eventNamesList);
302 CurrentLocationGroupList currentLocationGroupList = new CurrentLocationGroupList();
303 List<CurrentLocationGroup> currentLocationGroups = currentLocationGroupList.getCurrentLocationGroup();
304 CurrentLocationGroup currentLocationGroup = new CurrentLocationGroup();
305 currentLocationGroup.setCurrentLocation("upstairs");
306 currentLocationGroup.setCurrentLocationFitness("suitable");
307 currentLocationGroup.setCurrentLocationNote("A most suitable location.");
308 currentLocationGroups.add(currentLocationGroup);
309 intake.setCurrentLocationGroupList(currentLocationGroupList);
311 intake.setEntryNote(getUTF8DataFragment());
313 PoxPayloadOut multipart = new PoxPayloadOut(IntakeClient.SERVICE_PAYLOAD_NAME);
314 PayloadOutputPart commonPart =
315 multipart.addPart(intake, MediaType.APPLICATION_XML_TYPE);
316 commonPart.setLabel(new IntakeClient().getCommonPartName());
318 if (logger.isDebugEnabled()) {
319 logger.debug("to be created, intake common");
320 logger.debug(objectAsXmlString(intake, IntakesCommon.class));
327 protected PoxPayloadOut createInstance(String commonPartName,
328 String identifier) throws Exception {
329 return this.createInstance(identifier);
333 protected IntakesCommon updateInstance(IntakesCommon intakesCommon) {
334 IntakesCommon result = new IntakesCommon();
336 result.setEntryNumber("updated-" + intakesCommon.getEntryNumber());
337 result.setEntryNote(intakesCommon.getEntryNote());
339 CurrentLocationGroupList currentLocationGroupList = intakesCommon.getCurrentLocationGroupList();
340 Assert.assertNotNull(currentLocationGroupList);
342 List<CurrentLocationGroup> currentLocationGroups = currentLocationGroupList.getCurrentLocationGroup();
343 Assert.assertNotNull(currentLocationGroups);
344 Assert.assertTrue(currentLocationGroups.size() > 0);
346 CurrentLocationGroup currentLocationGroup = currentLocationGroups.get(0);
347 Assert.assertNotNull(currentLocationGroup);
349 String currentLocationNote = currentLocationGroup.getCurrentLocationNote();
350 Assert.assertNotNull(currentLocationNote);
352 String updatedCurrentLocationNote = "updated-" + currentLocationNote;
353 currentLocationGroups.get(0).setCurrentLocationNote(updatedCurrentLocationNote);
354 result.setCurrentLocationGroupList(currentLocationGroupList);
360 protected void compareUpdatedInstances(IntakesCommon original,
361 IntakesCommon updated) throws Exception {
362 Assert.assertEquals(updated.getEntryNumber(),
363 original.getEntryNumber(),
364 "Data in updated object did not match submitted data.");
366 CurrentLocationGroupList currentLocationGroupList = updated.getCurrentLocationGroupList();
367 Assert.assertNotNull(currentLocationGroupList);
368 List<CurrentLocationGroup> currentLocationGroups = currentLocationGroupList.getCurrentLocationGroup();
369 Assert.assertNotNull(currentLocationGroups);
370 Assert.assertTrue(currentLocationGroups.size() > 0);
371 Assert.assertNotNull(currentLocationGroups.get(0));
373 String updatedCurrentLocationNote = original.getCurrentLocationGroupList()
374 .getCurrentLocationGroup().get(0).getCurrentLocationNote();
375 Assert.assertEquals(updatedCurrentLocationNote,
376 currentLocationGroups.get(0).getCurrentLocationNote(),
377 "Data in updated object did not match submitted data.");
379 Assert.assertEquals(updated.getEntryNote(), original.getEntryNote(),
380 "Data in updated object did not match submitted data.");
384 if (logger.isDebugEnabled()) {
385 logger.debug("UTF-8 data sent=" + original.getEntryNote() + "\n"
386 + "UTF-8 data received=" + updated.getEntryNote());
388 Assert.assertTrue(updated.getEntryNote().contains(getUTF8DataFragment()),
389 "UTF-8 data retrieved '" + updated.getEntryNote()
390 + "' does not contain expected data '" + getUTF8DataFragment());
394 * For convenience and terseness, this test method is the base of the test execution dependency chain. Other test methods may
395 * refer to this method in their @Test annotation declarations.
398 @Test(dataProvider = "testName",
400 "org.collectionspace.services.client.test.AbstractServiceTestImpl.baseCRUDTests"})
401 public void CRUDTests(String testName) {
402 // Needed for TestNG dependency chain.