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.text.Collator;
26 import java.util.ArrayList;
27 import java.util.Comparator;
28 import java.util.List;
29 import java.util.Locale;
30 import javax.ws.rs.core.MediaType;
31 import javax.ws.rs.core.Response;
33 import org.collectionspace.services.MovementJAXBSchema;
34 import org.collectionspace.services.client.CollectionSpaceClient;
35 import org.collectionspace.services.client.MovementClient;
36 import org.collectionspace.services.movement.MovementsCommon;
37 import org.collectionspace.services.movement.MovementsCommonList;
38 import org.collectionspace.services.jaxb.AbstractCommonList;
40 import org.jboss.resteasy.client.ClientResponse;
41 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
42 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
43 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
45 import org.testng.Assert;
46 import org.testng.annotations.AfterClass;
47 import org.testng.annotations.DataProvider;
48 import org.testng.annotations.Test;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
54 * MovementSortByTest, tests sorting of summary lists by fields
55 * of various datatypes.
57 * $LastChangedRevision: 2562 $
58 * $LastChangedDate: 2010-06-22 23:26:51 -0700 (Tue, 22 Jun 2010) $
60 public class MovementSortByTest extends BaseServiceTest {
62 private final String CLASS_NAME = MovementSortByTest.class.getName();
63 private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
65 // Instance variables specific to this test.
66 private final String DELIMITER_SCHEMA_AND_FIELD = ":";
67 private final String KEYWORD_DESCENDING_SEARCH = "DESC";
68 private final String SERVICE_PATH_COMPONENT = "movements";
69 private final String TEST_SPECIFIC_KEYWORD = "msotebstpfscn";
70 private List<String> movementIdsCreated = new ArrayList<String>();
71 private final String SORT_FIELD_SEPARATOR = ", ";
72 private final Locale LOCALE = Locale.US;
75 * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
78 protected CollectionSpaceClient getClientInstance() {
79 throw new UnsupportedOperationException(); //method not supported (or needed) in this test class
83 * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
86 protected AbstractCommonList getAbstractCommonList(
87 ClientResponse<AbstractCommonList> response) {
88 throw new UnsupportedOperationException(); //method not supported (or needed) in this test class
91 // ---------------------------------------------------------------
93 // ---------------------------------------------------------------
98 * Tests whether a list of records, sorted by a String field in
99 * ascending order, is returned in the expected order.
101 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
102 dependsOnMethods = {"createList"})
103 public void sortByStringFieldAscending(String testName) throws Exception {
105 if (logger.isDebugEnabled()) {
106 logger.debug(testBanner(testName, CLASS_NAME));
109 String sortFieldName = qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE);
110 if (logger.isDebugEnabled()) {
111 logger.debug("Sorting on field name=" + sortFieldName);
113 MovementsCommonList list = readSortedList(sortFieldName);
114 List<MovementsCommonList.MovementListItem> items =
115 list.getMovementListItem();
117 ArrayList<String> values = new ArrayList<String>();
118 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
120 for (MovementsCommonList.MovementListItem item : items) {
121 // Because movementNote is not currently a summary field
122 // (returned in summary list items), we will need to verify
123 // sort order by retrieving full records, using the
124 // IDs provided in the summary list items. amd then retriving
125 // the value of that field from each of those records.
126 MovementsCommon movement = read(item.getCsid());
127 values.add(i, movement.getMovementNote());
128 if (logger.isDebugEnabled()) {
129 logger.debug("list-item[" + i + "] movementNote=" + values.get(i));
131 // Verify that the value of the specified field in the current record
132 // is equal to or greater than its value in the previous record,
133 // using a locale-specific collator.
135 // (Note: when used with certain text, this test case could potentially
136 // reflect inconsistencies, if any, between Java's collator and the
137 // collator used for ordering by the database. To help avoid this,
138 // it might be useful to keep test strings fairly generic.)
139 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
140 Assert.assertTrue(localeSpecificCollator.compare(values.get(i), values.get(i - 1)) >= 0);
148 * Tests whether a list of records, obtained by a keyword search, and
149 * sorted by a String field in ascending order, is returned in the expected order.
151 * This verifies that summary list results from keyword searches, in
152 * addition to 'read list' requests, can be returned in sorted order.
154 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
155 dependsOnMethods = {"createList"})
156 public void sortKeywordSearchResultsByStringFieldAscending(String testName) throws Exception {
158 if (logger.isDebugEnabled()) {
159 logger.debug(testBanner(testName, CLASS_NAME));
162 String sortFieldName = qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE);
163 if (logger.isDebugEnabled()) {
164 logger.debug("Sorting on field name=" + sortFieldName);
166 MovementsCommonList list = keywordSearchSortedBy(TEST_SPECIFIC_KEYWORD, sortFieldName);
167 List<MovementsCommonList.MovementListItem> items =
168 list.getMovementListItem();
170 ArrayList<String> values = new ArrayList<String>();
171 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
173 for (MovementsCommonList.MovementListItem item : items) {
174 // Because movementNote is not currently a summary field
175 // (returned in summary list items), we will need to verify
176 // sort order by retrieving full records, using the
177 // IDs provided in the summary list items. amd then retriving
178 // the value of that field from each of those records.
179 MovementsCommon movement = read(item.getCsid());
180 values.add(i, movement.getMovementNote());
181 if (logger.isDebugEnabled()) {
182 logger.debug("list-item[" + i + "] movementNote=" + values.get(i));
184 // Verify that the value of the specified field in the current record
185 // is equal to or greater than its value in the previous record,
186 // using a locale-specific collator.
188 // (Note: when used with certain text, this test case could potentially
189 // reflect inconsistencies, if any, between Java's collator and the
190 // collator used for ordering by the database. To help avoid this,
191 // it might be useful to keep test strings fairly generic.)
192 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
193 Assert.assertTrue(localeSpecificCollator.compare(values.get(i), values.get(i - 1)) >= 0);
201 * Tests whether a list of records, sorted by a String field in
202 * descending order, is returned in the expected order.
204 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
205 dependsOnMethods = {"createList"})
206 public void sortByStringFieldDescending(String testName) throws Exception {
208 if (logger.isDebugEnabled()) {
209 logger.debug(testBanner(testName, CLASS_NAME));
212 String sortFieldName =
213 asDescendingSort(qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE));
214 if (logger.isDebugEnabled()) {
215 logger.debug("Sorting on field name=" + sortFieldName);
217 MovementsCommonList list = readSortedList(sortFieldName);
218 List<MovementsCommonList.MovementListItem> items =
219 list.getMovementListItem();
221 ArrayList<String> values = new ArrayList<String>();
222 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
224 for (MovementsCommonList.MovementListItem item : items) {
225 // Because movementNote is not currently a summary field
226 // (returned in summary list items), we will need to verify
227 // sort order by retrieving full records, using the
228 // IDs provided in the summary list items. amd then retriving
229 // the value of that field from each of those records.
230 MovementsCommon movement = read(item.getCsid());
231 values.add(i, movement.getMovementNote());
232 if (logger.isDebugEnabled()) {
233 logger.debug("list-item[" + i + "] movementNote=" + values.get(i));
235 // Verify that the value of the specified field in the current record
236 // is less than or equal to than its value in the previous record,
237 // using a locale-specific collator.
239 // (Note: when used with certain text, this test case could potentially
240 // reflect inconsistencies, if any, between Java's collator and the
241 // collator used for ordering by the database. To help avoid this,
242 // it might be useful to keep test strings fairly generic.)
243 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
244 Assert.assertTrue(localeSpecificCollator.compare(values.get(i), values.get(i - 1)) <= 0);
252 * Tests whether a list of records, sorted by a dateTime field in
253 * ascending order, is returned in the expected order.
255 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
256 dependsOnMethods = {"createList"})
257 public void sortByDateTimeFieldAscending(String testName) throws Exception {
259 if (logger.isDebugEnabled()) {
260 logger.debug(testBanner(testName, CLASS_NAME));
263 String sortFieldName = qualifySortFieldName(MovementJAXBSchema.LOCATION_DATE);
264 if (logger.isDebugEnabled()) {
265 logger.debug("Sorting on field name=" + sortFieldName);
267 MovementsCommonList list = readSortedList(sortFieldName);
268 List<MovementsCommonList.MovementListItem> items =
269 list.getMovementListItem();
271 ArrayList<String> values = new ArrayList<String>();
272 Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
274 for (MovementsCommonList.MovementListItem item : items) {
275 values.add(i, item.getLocationDate());
276 if (logger.isDebugEnabled()) {
277 logger.debug("list-item[" + i + "] locationDate=" + values.get(i));
279 // Verify that the value of the specified field in the current record
280 // is equal to or greater than its value in the previous record.
281 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
282 Assert.assertTrue(comparator.compare(values.get(i), values.get(i - 1)) >= 0);
289 * Tests whether a list of records, sorted by a dateTime field in
290 * descending order, is returned in the expected order.
292 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
293 dependsOnMethods = {"createList"})
294 public void sortByDateTimeFieldDescending(String testName) throws Exception {
296 if (logger.isDebugEnabled()) {
297 logger.debug(testBanner(testName, CLASS_NAME));
300 String sortFieldName =
301 asDescendingSort(qualifySortFieldName(MovementJAXBSchema.LOCATION_DATE));
302 if (logger.isDebugEnabled()) {
303 logger.debug("Sorting on field name=" + sortFieldName);
305 MovementsCommonList list = readSortedList(sortFieldName);
306 List<MovementsCommonList.MovementListItem> items =
307 list.getMovementListItem();
309 ArrayList<String> values = new ArrayList<String>();
310 Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
312 for (MovementsCommonList.MovementListItem item : items) {
313 values.add(i, item.getLocationDate());
314 if (logger.isDebugEnabled()) {
315 logger.debug("list-item[" + i + "] locationDate=" + values.get(i));
317 // Verify that the value of the specified field in the current record
318 // is less than or equal to its value in the previous record.
319 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
320 Assert.assertTrue(comparator.compare(values.get(i), values.get(i - 1)) <= 0);
327 * Tests whether a list of records, sorted by two different fields in
328 * ascending order, is returned in the expected order.
330 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
331 dependsOnMethods = {"createList"})
332 public void sortByTwoFieldsAscending(String testName) throws Exception {
334 if (logger.isDebugEnabled()) {
335 logger.debug(testBanner(testName, CLASS_NAME));
338 String firstSortFieldName = qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE);
339 String secondSortFieldName = qualifySortFieldName(MovementJAXBSchema.LOCATION_DATE);
340 if (logger.isDebugEnabled()) {
341 logger.debug("Sorting on field names=" + firstSortFieldName + " and " + secondSortFieldName);
343 String sortExpression = firstSortFieldName + SORT_FIELD_SEPARATOR + secondSortFieldName;
344 MovementsCommonList list = readSortedList(sortExpression);
345 List<MovementsCommonList.MovementListItem> items =
346 list.getMovementListItem();
348 ArrayList<String> firstFieldValues = new ArrayList<String>();
349 ArrayList<String> secondFieldValues = new ArrayList<String>();
350 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
351 Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
353 for (MovementsCommonList.MovementListItem item : items) {
354 // Because movementNote is not currently a summary field
355 // (returned in summary list items), we will need to verify
356 // sort order by retrieving full records, using the
357 // IDs provided in the summary list items. amd then retriving
358 // the value of that field from each of those records.
359 MovementsCommon movement = read(item.getCsid());
360 firstFieldValues.add(i, movement.getMovementNote());
361 secondFieldValues.add(i, movement.getLocationDate());
362 if (logger.isDebugEnabled()) {
363 logger.debug("list-item[" + i + "] movementNote=" + firstFieldValues.get(i));
364 logger.debug("list-item[" + i + "] locationDate=" + secondFieldValues.get(i));
366 // Verify that the value of the specified field in the current record
367 // is less than or greater than its value in the previous record.
368 if (i > 0 && firstFieldValues.get(i) != null && firstFieldValues.get(i - 1) != null) {
369 Assert.assertTrue(localeSpecificCollator.compare(firstFieldValues.get(i), firstFieldValues.get(i - 1)) >= 0);
370 // If the value of the first sort field in the current record is identical to
371 // its value in the previous record, verify that the value of the second sort
372 // field is equal to or greater than its value in the previous record,
373 // using a locale-specific collator.
374 if (localeSpecificCollator.compare(firstFieldValues.get(i), firstFieldValues.get(i - 1)) == 0) {
375 if (i > 0 && secondFieldValues.get(i) != null && secondFieldValues.get(i - 1) != null) {
376 Assert.assertTrue(comparator.compare(secondFieldValues.get(i), secondFieldValues.get(i - 1)) >= 0);
385 * Tests whether a list of records, sorted by one different fields in
386 * descending order and a second field in ascending order, is returned in the expected order.
388 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
389 dependsOnMethods = {"createList"})
390 public void sortByOneFieldAscendingOneFieldsDescending(String testName) throws Exception {
392 if (logger.isDebugEnabled()) {
393 logger.debug(testBanner(testName, CLASS_NAME));
396 String firstSortFieldName =
397 asDescendingSort(qualifySortFieldName(MovementJAXBSchema.LOCATION_DATE));
398 String secondSortFieldName = qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE);
399 if (logger.isDebugEnabled()) {
400 logger.debug("Sorting on field names=" + firstSortFieldName + " and " + secondSortFieldName);
402 String sortExpression = firstSortFieldName + SORT_FIELD_SEPARATOR + secondSortFieldName;
403 MovementsCommonList list = readSortedList(sortExpression);
404 List<MovementsCommonList.MovementListItem> items =
405 list.getMovementListItem();
407 ArrayList<String> firstFieldValues = new ArrayList<String>();
408 ArrayList<String> secondFieldValues = new ArrayList<String>();
409 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
410 Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
412 for (MovementsCommonList.MovementListItem item : items) {
413 // Because movementNote is not currently a summary field
414 // (returned in summary list items), we will need to verify
415 // sort order by retrieving full records, using the
416 // IDs provided in the summary list items. amd then retriving
417 // the value of that field from each of those records.
418 MovementsCommon movement = read(item.getCsid());
419 firstFieldValues.add(i, movement.getLocationDate());
420 secondFieldValues.add(i, movement.getMovementNote());
421 if (logger.isDebugEnabled()) {
422 logger.debug("list-item[" + i + "] locationDate=" + firstFieldValues.get(i));
423 logger.debug("list-item[" + i + "] movementNote=" + secondFieldValues.get(i));
425 // Verify that the value of the specified field in the current record
426 // is less than or equal to than its value in the previous record.
427 if (i > 0 && firstFieldValues.get(i) != null && firstFieldValues.get(i - 1) != null) {
428 Assert.assertTrue(comparator.compare(firstFieldValues.get(i), firstFieldValues.get(i - 1)) <= 0);
429 // If the value of the first sort field in the current record is identical to
430 // its value in the previous record, verify that the value of the second sort
431 // field is equal to or greater than its value in the previous record,
432 // using a locale-specific collator.
433 if (comparator.compare(firstFieldValues.get(i), firstFieldValues.get(i - 1)) == 0) {
434 if (i > 0 && secondFieldValues.get(i) != null && secondFieldValues.get(i - 1) != null) {
435 Assert.assertTrue(localeSpecificCollator.compare(secondFieldValues.get(i), secondFieldValues.get(i - 1)) >= 0);
445 * Tests whether a request to sort by an empty field name is handled
446 * as expected: the query parameter is simply ignored, and a list
447 * of records is returned, unsorted, with a success result.
449 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
450 public void sortWithEmptySortFieldName(String testName) throws Exception {
452 if (logger.isDebugEnabled()) {
453 logger.debug(testBanner(testName, CLASS_NAME));
455 testSetup(STATUS_OK, ServiceRequestType.READ);
457 // Submit the request to the service and store the response.
458 MovementClient client = new MovementClient();
459 final String EMPTY_SORT_FIELD_NAME = "";
460 ClientResponse<MovementsCommonList> res =
461 client.readListSortedBy(EMPTY_SORT_FIELD_NAME);
462 int statusCode = res.getStatus();
464 // Check the status code of the response: does it match
465 // the expected response(s)?
466 if (logger.isDebugEnabled()) {
467 logger.debug(testName + ": status = " + statusCode);
469 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
470 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
471 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
478 * Tests whether a request to sort by an unqualified field name is
479 * handled as expected. The field name provided in this test is valid,
480 * but has not been qualified by being prefixed by a schema name and delimiter.
482 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
483 public void sortWithUnqualifiedFieldName(String testName) throws Exception {
485 if (logger.isDebugEnabled()) {
486 logger.debug(testBanner(testName, CLASS_NAME));
488 // FIXME: Ultimately, this should return a BAD_REQUEST status.
489 testSetup(STATUS_INTERNAL_SERVER_ERROR, ServiceRequestType.READ);
491 // Submit the request to the service and store the response.
492 MovementClient client = new MovementClient();
493 ClientResponse<MovementsCommonList> res =
494 client.readListSortedBy(MovementJAXBSchema.LOCATION_DATE);
495 int statusCode = res.getStatus();
497 // Check the status code of the response: does it match
498 // the expected response(s)?
499 if (logger.isDebugEnabled()) {
500 logger.debug(testName + ": status = " + statusCode);
502 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
503 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
504 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
509 * Tests whether a request to sort by an invalid identifier for the
510 * sort order (ascending or descending) is handled as expected.
512 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
513 public void sortWithInvalidSortOrderIdentifier(String testName) throws Exception {
515 if (logger.isDebugEnabled()) {
516 logger.debug(testBanner(testName, CLASS_NAME));
518 // FIXME: Ultimately, this should return a BAD_REQUEST status.
519 testSetup(STATUS_INTERNAL_SERVER_ERROR, ServiceRequestType.READ);
521 // Submit the request to the service and store the response.
522 MovementClient client = new MovementClient();
523 final String INVALID_SORT_ORDER_IDENTIFIER = "NO_DIRECTION";
524 ClientResponse<MovementsCommonList> res =
525 client.readListSortedBy(MovementJAXBSchema.LOCATION_DATE
526 + " " + INVALID_SORT_ORDER_IDENTIFIER);
527 int statusCode = res.getStatus();
529 // Check the status code of the response: does it match
530 // the expected response(s)?
531 if (logger.isDebugEnabled()) {
532 logger.debug(testName + ": status = " + statusCode);
534 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
535 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
536 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
541 * Tests whether a request to sort by a malformed field name is
542 * handled as expected.
545 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class)
546 public void sortWithMalformedFieldName(String testName) throws Exception {
548 // FIXME: Implement this stub method.
550 // FIXME: Consider splitting this test into various tests, with
551 // different malformed field name formats that might confuse parsers
552 // and/or validation code.
554 // FIXME: Consider fixing DocumentFilter.setSortOrder() to return
555 // an error response to this test case, then revise this test case
556 // to expect that response.
561 // ---------------------------------------------------------------
562 // Cleanup of resources created during testing
563 // ---------------------------------------------------------------
565 * Deletes all resources created by tests, after all tests have been run.
567 * This cleanup method will always be run, even if one or more tests fail.
568 * For this reason, it attempts to remove all resources created
569 * at any point during testing, even if some of those resources
570 * may be expected to be deleted by certain tests.
572 @AfterClass(alwaysRun = true)
573 public void cleanUp() {
574 String noTest = System.getProperty("noTestCleanup");
575 if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
576 if (logger.isDebugEnabled()) {
577 logger.debug("Skipping Cleanup phase ...");
581 if (logger.isDebugEnabled()) {
582 logger.debug("Cleaning up temporary resources created for testing ...");
584 // Delete all Movement resource(s) created during this test.
585 MovementClient movementClient = new MovementClient();
586 for (String resourceId : movementIdsCreated) {
587 // Note: Any non-success responses are ignored and not reported.
588 movementClient.delete(resourceId);
592 // ---------------------------------------------------------------
593 // Utility methods used by tests above
594 // ---------------------------------------------------------------
597 public String getServicePathComponent() {
598 return SERVICE_PATH_COMPONENT;
601 private String getCommonSchemaName() {
602 // FIXME: While this convention - appending a suffix to the name of
603 // the service's first unique URL path component - works, it would
604 // be preferable to get the common schema name from configuration.
606 // Such configuration is provided for example, on the services side, in
607 // org.collectionspace.services.common.context.AbstractServiceContextImpl
608 return getServicePathComponent() + "_" + "common";
611 public String qualifySortFieldName(String fieldName) {
612 return getCommonSchemaName() + DELIMITER_SCHEMA_AND_FIELD + fieldName;
615 public String asDescendingSort(String qualifiedFieldName) {
616 return qualifiedFieldName + " " + KEYWORD_DESCENDING_SEARCH;
620 * A data provider that provides a set of unsorted values, which are
621 * to be used in populating (seeding) values in test records.
623 * Data elements provided for each test record consist of:
624 * * An integer, reflecting expected sort order.
625 * * US English text, to populate the value of a free text (String) field.
626 * * An ISO 8601 timestamp, to populate the value of a calendar date (dateTime) field.
628 @DataProvider(name = "unsortedValues")
629 public Object[][] unsortedValues() {
630 // Add a test record-specific string so we have the option of
631 // constraining tests to only test records, in list or search results.
632 final String TEST_RECORD_SPECIFIC_STRING = CLASS_NAME + " " + TEST_SPECIFIC_KEYWORD;
633 return new Object[][]{
634 {1, "Aardvark and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2009-01-29T00:00:05Z"},
635 {10, "Zounds! " + TEST_RECORD_SPECIFIC_STRING, "2010-08-31T00:00:00Z"},
636 {3, "Aardvark and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2010-08-30T00:00:00Z"},
637 {7, "Bat fling off wall. " + TEST_RECORD_SPECIFIC_STRING, "2010-08-30T00:00:00Z"},
638 {4, "Aardvarks and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2009-01-29T08:00:00Z"},
639 {5, "Aardvarks and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"},
640 {2, "Aardvark and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"},
641 {9, "Zounds! " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"}, // Identical to next record
642 {8, "Zounds! " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"},
643 {6, "Bat flies off ball. " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"}
648 * Create multiple test records, initially in unsorted order,
649 * using values for various fields obtained from the data provider.
651 @Test(dataProvider = "unsortedValues")
652 public void createList(int expectedSortOrder, String movementNote,
653 String locationDate) throws Exception {
655 String testName = "createList";
656 if (logger.isDebugEnabled()) {
657 logger.debug(testBanner(testName, CLASS_NAME));
659 testSetup(STATUS_CREATED, ServiceRequestType.CREATE);
661 // Iterates through the sets of values returned by the data provider,
662 // and creates a corresponding test record for each set of values.
663 create(movementNote, locationDate);
666 private void create(String movementNote, String locationDate) throws Exception {
668 String testName = "create";
669 testSetup(STATUS_CREATED, ServiceRequestType.CREATE);
671 // Submit the request to the service and store the response.
672 MovementClient client = new MovementClient();
673 MultipartOutput multipart = createMovementInstance(createIdentifier(),
674 movementNote, locationDate);
675 ClientResponse<Response> res = client.create(multipart);
676 int statusCode = res.getStatus();
678 // Check the status code of the response: does it match
679 // the expected response(s)?
682 // Does it fall within the set of valid status codes?
683 // Does it exactly match the expected status code?
684 if (logger.isDebugEnabled()) {
685 logger.debug(testName + ": status = " + statusCode);
687 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
688 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
689 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
691 // Store the IDs from every resource created by tests,
692 // so they can be deleted after tests have been run.
693 movementIdsCreated.add(extractId(res));
696 private MovementsCommon read(String csid) throws Exception {
698 String testName = "read";
699 testSetup(STATUS_OK, ServiceRequestType.READ);
701 // Submit the request to the service and store the response.
702 MovementClient client = new MovementClient();
703 ClientResponse<MultipartInput> res = client.read(csid);
704 int statusCode = res.getStatus();
706 // Check the status code of the response: does it match
707 // the expected response(s)?
708 if (logger.isDebugEnabled()) {
709 logger.debug(testName + ": status = " + statusCode);
711 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
712 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
713 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
715 // Extract and return the common part of the record.
716 MultipartInput input = (MultipartInput) res.getEntity();
717 MovementsCommon movement = (MovementsCommon) extractPart(input,
718 client.getCommonPartName(), MovementsCommon.class);
723 private MultipartOutput createMovementInstance(
724 String movementReferenceNumber,
726 String locationDate) {
727 MovementsCommon movement = new MovementsCommon();
728 movement.setMovementReferenceNumber(movementReferenceNumber);
729 movement.setMovementNote(movementNote);
730 movement.setLocationDate(locationDate);
731 MultipartOutput multipart = new MultipartOutput();
732 OutputPart commonPart =
733 multipart.addPart(movement, MediaType.APPLICATION_XML_TYPE);
734 commonPart.getHeaders().add("label", new MovementClient().getCommonPartName());
736 if (logger.isDebugEnabled()) {
737 logger.debug("to be created, movement common");
738 logger.debug(objectAsXmlString(movement, MovementsCommon.class));
744 private MovementsCommonList readSortedList(String sortFieldName) throws Exception {
746 String testName = "readSortedList";
747 testSetup(STATUS_OK, ServiceRequestType.READ);
749 // Submit the request to the service and store the response.
750 MovementClient client = new MovementClient();
752 ClientResponse<MovementsCommonList> res =
753 client.readListSortedBy(sortFieldName);
754 MovementsCommonList list = res.getEntity();
755 int statusCode = res.getStatus();
757 // Check the status code of the response: does it match
758 // the expected response(s)?
759 if (logger.isDebugEnabled()) {
760 logger.debug(testName + ": status = " + statusCode);
762 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
763 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
764 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
770 private MovementsCommonList keywordSearchSortedBy(String keywords,
771 String sortFieldName) throws Exception {
773 String testName = "keywordSearchSortedBy";
774 testSetup(STATUS_OK, ServiceRequestType.READ);
776 // Submit the request to the service and store the response.
777 MovementClient client = new MovementClient();
779 ClientResponse<MovementsCommonList> res =
780 client.keywordSearchSortedBy(keywords, sortFieldName);
781 MovementsCommonList list = res.getEntity();
782 int statusCode = res.getStatus();
784 // Check the status code of the response: does it match
785 // the expected response(s)?
786 if (logger.isDebugEnabled()) {
787 logger.debug(testName + ": status = " + statusCode);
789 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
790 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
791 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);