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 (c)) 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.HashMap;
26 import java.util.List;
29 import org.collectionspace.services.TaxonJAXBSchema;
30 import org.collectionspace.services.client.AbstractCommonListUtils;
31 import org.collectionspace.services.client.AuthorityClient;
32 import org.collectionspace.services.client.CollectionSpaceClient;
33 import org.collectionspace.services.client.PayloadOutputPart;
34 import org.collectionspace.services.client.PoxPayloadIn;
35 import org.collectionspace.services.client.PoxPayloadOut;
36 import org.collectionspace.services.client.TaxonomyAuthorityClient;
37 import org.collectionspace.services.client.TaxonomyAuthorityClientUtils;
38 import org.collectionspace.services.client.TaxonomyAuthorityProxy;
39 import org.collectionspace.services.jaxb.AbstractCommonList;
40 import org.collectionspace.services.taxonomy.TaxonAuthorGroup;
41 import org.collectionspace.services.taxonomy.TaxonAuthorGroupList;
42 import org.collectionspace.services.taxonomy.TaxonCitationList;
43 import org.collectionspace.services.taxonomy.TaxonomyauthorityCommon;
44 import org.collectionspace.services.taxonomy.TaxonCommon;
46 import javax.ws.rs.core.Response;
47 import org.jboss.resteasy.client.ClientResponse;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 import org.testng.Assert;
53 import org.testng.annotations.AfterClass;
54 import org.testng.annotations.Test;
57 * TaxonomyAuthorityServiceTest, carries out tests against a
58 * deployed and running TaxonomyAuthority Service.
60 * $LastChangedRevision$
63 public class TaxonomyAuthorityServiceTest extends AbstractAuthorityServiceTest<TaxonomyauthorityCommon, TaxonCommon> {
66 private final String CLASS_NAME = TaxonomyAuthorityServiceTest.class.getName();
67 private final Logger logger = LoggerFactory.getLogger(TaxonomyAuthorityServiceTest.class);
68 private final String REFNAME = "refName";
69 private final String DISPLAYNAME = "displayName";
71 final String TEST_SHORTID = "CentauruspleurexanthemusGreen1832";
72 final String TEST_TERM_STATUS = "accepted";
73 final String TEST_TAXON_FULL_NAME = "Centaurus pleurexanthemus Green 1832";
74 // TODO Re-implement the Taxon Rank field so as to provide an orderable
75 // ranking value, as well as a display name.
76 final String TEST_TAXON_RANK = "species";
77 final String TEST_TAXON_AUTHOR = "J. Green";
78 final String TEST_TAXON_AUTHOR_TYPE = "ascribed";
79 final String TEST_TAXON_CITATION = "A Monograph of the Trilobites of North America";
80 final String TEST_TAXON_CURRENCY = "current";
81 final String TEST_TAXON_YEAR = "1832";
82 final String TEST_TAXONOMIC_STATUS = "valid";
83 final String TEST_TAXON_IS_NAMED_HYBRID = "false";
84 final TaxonAuthorGroupList NULL_TAXON_AUTHOR_GROUP_LIST = null;
85 final TaxonCitationList NULL_TAXON_CITATION_LIST = null;
87 private String knownResourceShortIdentifer = null;
88 private String knownTaxonomyTypeRefName = null;
91 public String getServicePathComponent() {
92 return TaxonomyAuthorityClient.SERVICE_PATH_COMPONENT;
96 protected String getServiceName() {
97 return TaxonomyAuthorityClient.SERVICE_NAME;
100 public String getItemServicePathComponent() {
101 return AuthorityClient.ITEMS;
105 * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
108 protected CollectionSpaceClient<AbstractCommonList, PoxPayloadOut, String, TaxonomyAuthorityProxy> getClientInstance() {
109 return new TaxonomyAuthorityClient();
113 * Creates the item in authority.
115 * @param vcsid the vcsid
116 * @param authRefName the auth ref name
119 private String createItemInAuthority(String vcsid, String authRefName) {
121 final String testName = "createItemInAuthority(" + vcsid + "," + authRefName + ")";
122 if (logger.isDebugEnabled()) {
123 logger.debug(getTestBanner(testName, CLASS_NAME));
126 // Submit the request to the service and store the response.
127 TaxonomyAuthorityClient client = new TaxonomyAuthorityClient();
128 Map<String, String> taxonMap = new HashMap<String, String>();
130 // Fields present in all authority records.
131 taxonMap.put(TaxonJAXBSchema.SHORT_IDENTIFIER, TEST_SHORTID);
132 // TODO Make term status be controlled vocab.
133 taxonMap.put(TaxonJAXBSchema.TERM_STATUS, TEST_TERM_STATUS);
135 // Fields specific to this specific authority record type.
136 taxonMap.put(TaxonJAXBSchema.NAME, TEST_TAXON_FULL_NAME);
137 taxonMap.put(TaxonJAXBSchema.TAXON_RANK, TEST_TAXON_RANK);
138 taxonMap.put(TaxonJAXBSchema.TAXON_CURRENCY, TEST_TAXON_CURRENCY);
139 taxonMap.put(TaxonJAXBSchema.TAXON_YEAR, TEST_TAXON_YEAR);
140 taxonMap.put(TaxonJAXBSchema.TAXONOMIC_STATUS, TEST_TAXONOMIC_STATUS);
141 taxonMap.put(TaxonJAXBSchema.TAXON_IS_NAMED_HYBRID, TEST_TAXON_IS_NAMED_HYBRID);
143 TaxonCitationList taxonCitationList = new TaxonCitationList();
144 List<String> taxonCitations = taxonCitationList.getTaxonCitation();
145 taxonCitations.add(TEST_TAXON_CITATION);
147 TaxonAuthorGroupList taxonAuthorGroupList = new TaxonAuthorGroupList();
148 List<TaxonAuthorGroup> taxonAuthorGroups = taxonAuthorGroupList.getTaxonAuthorGroup();
149 TaxonAuthorGroup taxonAuthorGroup = new TaxonAuthorGroup();
150 taxonAuthorGroup.setTaxonAuthor(TEST_TAXON_AUTHOR);
151 taxonAuthorGroup.setTaxonAuthorType(TEST_TAXON_AUTHOR_TYPE);
152 taxonAuthorGroups.add(taxonAuthorGroup);
154 // FIXME: Add additional fields in the Taxon record here,
155 // including at least one each of:
156 // * a Boolean field (when implemented)
157 // * an authref field (when implemented)
159 String newID = TaxonomyAuthorityClientUtils.createItemInAuthority(vcsid,
160 authRefName, taxonMap, taxonAuthorGroupList, taxonCitationList, client);
162 // Store the ID returned from the first item resource created
163 // for additional tests below.
164 if (knownItemResourceId == null) {
165 setKnownItemResource(newID, TEST_SHORTID);
166 if (logger.isDebugEnabled()) {
167 logger.debug(testName + ": knownItemResourceId=" + newID + " inAuthority=" + vcsid);
171 // Store the IDs from any item resources created
172 // by tests, along with the IDs of their parents, so these items
173 // can be deleted after all tests have been run.
174 allResourceItemIdsCreated.put(newID, vcsid);
180 * Verify item display name.
182 * @param testName the test name
183 * @throws Exception the exception
185 @Test(dataProvider = "testName",
186 dependsOnMethods = {"readItem", "updateItem"})
187 public void verifyItemDisplayName(String testName) throws Exception {
189 // First read in our known resource
192 TaxonomyAuthorityClient client = new TaxonomyAuthorityClient();
193 ClientResponse<String> res = client.readItem(knownResourceId, knownItemResourceId);
194 TaxonCommon taxon = null;
196 assertStatusCode(res, testName);
197 // Check whether taxon has expected displayName.
198 PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
199 taxon = (TaxonCommon) extractPart(input,
200 client.getItemCommonPartName(), TaxonCommon.class);
201 Assert.assertNotNull(taxon);
204 res.releaseConnection();
208 // Now setup for an update
210 String displayName = taxon.getDisplayName();
211 // Make sure displayName matches computed form
212 String expectedDisplayName =
213 TaxonomyAuthorityClientUtils.prepareDefaultDisplayName(TEST_TAXON_FULL_NAME);
214 Assert.assertNotNull(displayName, "Display name was null. Expected it to be: " + expectedDisplayName);
215 // Update the shortName and verify the computed name is updated.
217 taxon.setDisplayNameComputed(true);
218 taxon.setTaxonFullName("updated-" + TEST_TAXON_FULL_NAME);
219 expectedDisplayName =
220 TaxonomyAuthorityClientUtils.prepareDefaultDisplayName("updated-" + TEST_TAXON_FULL_NAME);
222 // Create the update payload.
223 PoxPayloadOut output = new PoxPayloadOut(TaxonomyAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
224 PayloadOutputPart commonPart = output.addPart(client.getItemCommonPartName(), taxon);
227 res = client.updateItem(knownResourceId, knownItemResourceId, output);
228 TaxonCommon updatedTaxon = null;
230 assertStatusCode(res, testName);
231 // Retrieve the updated resource and verify that its contents exist.
232 PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
234 (TaxonCommon) extractPart(input,
235 client.getItemCommonPartName(), TaxonCommon.class);
236 Assert.assertNotNull(updatedTaxon);
239 res.releaseConnection();
242 // Verify that the updated resource received the correct data.
243 Assert.assertEquals(updatedTaxon.getTaxonFullName(), taxon.getTaxonFullName(),
244 "Updated ForeName in Taxonomy did not match submitted data.");
245 // Verify that the updated resource computes the right displayName.
246 Assert.assertEquals(updatedTaxon.getDisplayName(), expectedDisplayName,
247 "Updated ForeName in Taxonomy not reflected in computed DisplayName.");
249 // Now Update the displayName, not computed and verify the computed name is overriden.
251 taxon.setDisplayNameComputed(false);
252 expectedDisplayName = "TestName";
253 taxon.setDisplayName(expectedDisplayName);
255 // Submit the updated resource to the service and store the response.
256 output = new PoxPayloadOut(TaxonomyAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
257 commonPart = output.addPart(client.getItemCommonPartName(), taxon);
258 setupUpdate(); // setup expected status code for result
259 res = client.updateItem(knownResourceId, knownItemResourceId, output);
261 assertStatusCode(res, testName);
262 // Retrieve the updated resource and verify that its contents exist.
263 PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
265 (TaxonCommon) extractPart(input,
266 client.getItemCommonPartName(), TaxonCommon.class);
267 Assert.assertNotNull(updatedTaxon);
270 res.releaseConnection();
273 // Verify that the updated resource received the correct data.
274 Assert.assertEquals(updatedTaxon.isDisplayNameComputed(), false,
275 "Updated displayNameComputed in Taxonomy did not match submitted data.");
276 // Verify that the updated resource computes the right displayName.
277 Assert.assertEquals(updatedTaxon.getDisplayName(),
279 "Updated DisplayName (not computed) in Taxonomy not stored.");
283 * Verify illegal item display name.
285 * @param testName the test name
286 * @throws Exception the exception
288 @Test(dataProvider = "testName",
289 dependsOnMethods = {"verifyItemDisplayName"})
290 public void verifyIllegalItemDisplayName(String testName) throws Exception {
292 // First read in our known resource.
295 TaxonomyAuthorityClient client = new TaxonomyAuthorityClient();
296 ClientResponse<String> res = client.readItem(knownResourceId, knownItemResourceId);
297 TaxonCommon taxon = null;
299 assertStatusCode(res, testName);
300 // Check whether Taxonomy has expected displayName.
301 PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
302 taxon = (TaxonCommon) extractPart(input,
303 client.getItemCommonPartName(), TaxonCommon.class);
304 Assert.assertNotNull(taxon);
307 res.releaseConnection();
311 // Try to Update with computed false and no displayName
313 taxon.setDisplayNameComputed(false);
314 taxon.setDisplayName(null);
316 PoxPayloadOut output = new PoxPayloadOut(TaxonomyAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
317 PayloadOutputPart commonPart = output.addPart(client.getItemCommonPartName(), taxon);
318 setupUpdateWithInvalidBody(); // we expect a failure here
319 res = client.updateItem(knownResourceId, knownItemResourceId, output);
321 assertStatusCode(res, testName);
323 res.releaseConnection();
330 @Test(dataProvider = "testName", groups = {"readList"},
331 dependsOnMethods = {"readList"})
332 public void readItemList(String testName) {
333 readItemList(knownAuthorityWithItems, null);
337 * Read item list by authority name.
339 @Test(dataProvider = "testName", groups = {"readList"},
340 dependsOnMethods = {"readItemList"})
341 public void readItemListByAuthorityName(String testName) {
342 readItemList(null, READITEMS_SHORT_IDENTIFIER);
348 * @param vcsid the vcsid
349 * @param name the name
351 private void readItemList(String vcsid, String shortId) {
352 String testName = "readItemList";
357 // Submit the request to the service and store the response.
358 TaxonomyAuthorityClient client = new TaxonomyAuthorityClient();
359 ClientResponse<AbstractCommonList> res = null;
361 res = client.readItemList(vcsid, null, null);
362 } else if (shortId != null) {
363 res = client.readItemListForNamedAuthority(shortId, null, null);
365 Assert.fail("readItemList passed null csid and name!");
368 assertStatusCode(res, testName);
369 AbstractCommonList list = res.getEntity();
370 int statusCode = res.getStatus();
372 // Check the status code of the response: does it match
373 // the expected response(s)?
374 if (logger.isDebugEnabled()) {
375 logger.debug(testName + ": status = " + statusCode);
377 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
378 invalidStatusCodeMessage(testRequestType, statusCode));
379 Assert.assertEquals(statusCode, testExpectedStatusCode);
381 List<AbstractCommonList.ListItem> items =
383 int nItemsReturned = items.size();
384 // There will be 'nItemsToCreateInList'
385 // items created by the createItemList test,
386 // all associated with the same parent resource.
387 int nExpectedItems = nItemsToCreateInList;
388 if (logger.isDebugEnabled()) {
389 logger.debug(testName + ": Expected "
390 + nExpectedItems + " items; got: " + nItemsReturned);
392 Assert.assertEquals(nItemsReturned, nExpectedItems);
394 for (AbstractCommonList.ListItem item : items) {
396 AbstractCommonListUtils.ListItemGetElementValue(item, REFNAME);
397 Assert.assertTrue((null != value), "Item refName is null!");
399 AbstractCommonListUtils.ListItemGetElementValue(item, DISPLAYNAME);
400 Assert.assertTrue((null != value), "Item displayName is null!");
402 if(logger.isTraceEnabled()){
403 AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger, testName);
406 res.releaseConnection();
411 public void delete(String testName) throws Exception {
412 // Do nothing. See localDelete(). This ensure proper test order.
415 @Test(dataProvider = "testName", dependsOnMethods = {"localDeleteItem"})
416 public void localDelete(String testName) throws Exception {
417 super.delete(testName);
421 public void deleteItem(String testName) throws Exception {
422 // Do nothing. We need to wait until after the test "localDelete" gets run. When it does,
423 // its dependencies will get run first and then we can call the base class' delete method.
426 @Test(dataProvider = "testName", groups = {"delete"},
427 dependsOnMethods = {"verifyIllegalItemDisplayName"})
428 public void localDeleteItem(String testName) throws Exception {
429 super.deleteItem(testName);
432 // ---------------------------------------------------------------
433 // Cleanup of resources created during testing
434 // ---------------------------------------------------------------
436 * Deletes all resources created by tests, after all tests have been run.
438 * This cleanup method will always be run, even if one or more tests fail.
439 * For this reason, it attempts to remove all resources created
440 * at any point during testing, even if some of those resources
441 * may be expected to be deleted by certain tests.
443 @AfterClass(alwaysRun = true)
444 public void cleanUp() {
445 String noTest = System.getProperty("noTestCleanup");
446 if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
447 if (logger.isDebugEnabled()) {
448 logger.debug("Skipping Cleanup phase ...");
452 if (logger.isDebugEnabled()) {
453 logger.debug("Cleaning up temporary resources created for testing ...");
455 String parentResourceId;
456 String itemResourceId;
457 // Clean up contact resources.
458 TaxonomyAuthorityClient client = new TaxonomyAuthorityClient();
459 parentResourceId = knownResourceId;
460 // Clean up item resources.
461 for (Map.Entry<String, String> entry : allResourceItemIdsCreated.entrySet()) {
462 itemResourceId = entry.getKey();
463 parentResourceId = entry.getValue();
464 // Note: Any non-success responses from the delete operation
465 // below are ignored and not reported.
466 ClientResponse<Response> res =
467 client.deleteItem(parentResourceId, itemResourceId);
468 res.releaseConnection();
470 // Clean up parent resources.
471 for (String resourceId : allResourceIdsCreated) {
472 // Note: Any non-success responses from the delete operation
473 // below are ignored and not reported.
474 ClientResponse<Response> res = client.delete(resourceId);
475 res.releaseConnection();
479 // ---------------------------------------------------------------
480 // Utility methods used by tests above
481 // ---------------------------------------------------------------
483 * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
486 * Returns the root URL for the item service.
488 * This URL consists of a base URL for all services, followed by
489 * a path component for the owning parent, followed by the
490 * path component for the items.
492 * @param parentResourceIdentifier An identifier (such as a UUID) for the
493 * parent authority resource of the relevant item resource.
495 * @return The root URL for the item service.
497 protected String getItemServiceRootURL(String parentResourceIdentifier) {
498 return getResourceURL(parentResourceIdentifier) + "/" + getItemServicePathComponent();
502 * Returns the URL of a specific item resource managed by a service, and
503 * designated by an identifier (such as a universally unique ID, or UUID).
505 * @param parentResourceIdentifier An identifier (such as a UUID) for the
506 * parent authority resource of the relevant item resource.
508 * @param itemResourceIdentifier An identifier (such as a UUID) for an
511 * @return The URL of a specific item resource managed by a service.
513 protected String getItemResourceURL(String parentResourceIdentifier, String itemResourceIdentifier) {
514 return getItemServiceRootURL(parentResourceIdentifier) + "/" + itemResourceIdentifier;
518 public void authorityTests(String testName) {
519 // TODO Auto-generated method stub
523 // Taxonomy authority specific instances
527 protected PoxPayloadOut createInstance(String commonPartName,
529 String shortId = identifier;
530 String displayName = "displayName-" + shortId;
532 TaxonomyAuthorityClientUtils.createTaxonomyAuthRefName(shortId, null);
533 PoxPayloadOut multipart =
534 TaxonomyAuthorityClientUtils.createTaxonomyAuthorityInstance(
535 displayName, shortId, commonPartName);
540 protected PoxPayloadOut createNonExistenceInstance(String commonPartName, String identifier) {
541 String displayName = "displayName-NON_EXISTENT_ID";
542 PoxPayloadOut result = TaxonomyAuthorityClientUtils.createTaxonomyAuthorityInstance(
543 displayName, "nonEx", commonPartName);
548 protected TaxonomyauthorityCommon updateInstance(
549 TaxonomyauthorityCommon taxonomyAuthority) {
550 TaxonomyauthorityCommon result = new TaxonomyauthorityCommon();
552 result.setDisplayName("updated-" + taxonomyAuthority.getDisplayName());
553 result.setVocabType("updated-" + taxonomyAuthority.getVocabType());
559 protected void compareUpdatedInstances(TaxonomyauthorityCommon original,
560 TaxonomyauthorityCommon updated) throws Exception {
561 // Verify that the updated resource received the correct data.
562 Assert.assertEquals(updated.getDisplayName(),
563 original.getDisplayName(),
564 "Display name in updated object did not match submitted data.");
568 // Authority item specific overrides
572 protected String createItemInAuthority(String authorityId) {
573 return createItemInAuthority(authorityId, null /*refname*/);
577 protected TaxonCommon updateItemInstance(TaxonCommon authorityItem) {
578 TaxonCommon result = new TaxonCommon();
580 result.setDisplayName("updated-" + authorityItem.getTaxonFullName());
581 result.setTaxonFullName("updated-" + authorityItem.getTaxonFullName());
587 protected void compareUpdatedItemInstances(TaxonCommon original,
588 TaxonCommon updated) throws Exception {
589 Assert.assertEquals(updated.getTaxonFullName(), original.getTaxonFullName(),
590 "Taxon full name in updated Taxon did not match submitted data.");
594 protected void verifyReadItemInstance(TaxonCommon item) throws Exception {
595 Assert.assertNotNull(item.getTaxonFullName(), "Field value is unexpectedly null.");
596 Assert.assertEquals(item.getTaxonFullName(), TEST_TAXON_FULL_NAME,
597 "Field value " + item.getTaxonFullName()
598 + "does not match expected value " + TEST_TAXON_FULL_NAME);
602 protected PoxPayloadOut createNonExistenceItemInstance(
603 String commonPartName, String identifier) {
604 Map<String, String> nonexMap = new HashMap<String, String>();
605 nonexMap.put(TaxonJAXBSchema.NAME, TEST_TAXON_FULL_NAME);
606 nonexMap.put(TaxonJAXBSchema.SHORT_IDENTIFIER, "nonEx");
607 nonexMap.put(TaxonJAXBSchema.TERM_STATUS, TEST_TERM_STATUS);
608 // PoxPayloadOut multipart =
609 // TaxonomyAuthorityClientUtils.createTaxonInstance(
610 // TaxonomyAuthorityClientUtils.createTaxonomyRefName(knownResourceRefName, "nonEx", "Non Existent"),
611 // nonexMap, NULL_TAXON_AUTHOR_GROUP_LIST, NULL_TAXON_CITATION_LIST,
612 // client.getItemCommonPartName());
613 final String EMPTY_REFNAME = "";
614 PoxPayloadOut result =
615 TaxonomyAuthorityClientUtils.createTaxonInstance(EMPTY_REFNAME,
616 nonexMap, NULL_TAXON_AUTHOR_GROUP_LIST, NULL_TAXON_CITATION_LIST,