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.client.PayloadInputPart;
37 import org.collectionspace.services.client.PayloadOutputPart;
38 import org.collectionspace.services.client.PoxPayloadIn;
39 import org.collectionspace.services.client.PoxPayloadOut;
40 import org.collectionspace.services.movement.MovementsCommon;
41 import org.collectionspace.services.movement.MovementsCommonList;
42 import org.collectionspace.services.jaxb.AbstractCommonList;
44 import org.jboss.resteasy.client.ClientResponse;
46 import org.testng.Assert;
47 import org.testng.annotations.AfterClass;
48 import org.testng.annotations.DataProvider;
49 import org.testng.annotations.Test;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
55 * MovementSortByTest, tests sorting of summary lists by fields
56 * of various datatypes.
58 * $LastChangedRevision: 2562 $
59 * $LastChangedDate: 2010-06-22 23:26:51 -0700 (Tue, 22 Jun 2010) $
61 public class MovementSortByTest extends BaseServiceTest {
63 private final String CLASS_NAME = MovementSortByTest.class.getName();
64 private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
65 final String SERVICE_NAME = "movements";
67 // Instance variables specific to this test.
68 private final String DELIMITER_SCHEMA_AND_FIELD = ":";
69 private final String KEYWORD_DESCENDING_SEARCH = "DESC";
70 private final String SERVICE_PATH_COMPONENT = "movements";
71 private final String TEST_SPECIFIC_KEYWORD = "msotebstpfscn";
72 private List<String> movementIdsCreated = new ArrayList<String>();
73 private final String SORT_FIELD_SEPARATOR = ", ";
74 private final Locale LOCALE = Locale.US;
77 * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
80 protected CollectionSpaceClient getClientInstance() {
81 throw new UnsupportedOperationException(); //method not supported (or needed) in this test class
85 * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
88 protected AbstractCommonList getAbstractCommonList(
89 ClientResponse<AbstractCommonList> response) {
90 throw new UnsupportedOperationException(); //method not supported (or needed) in this test class
93 // ---------------------------------------------------------------
95 // ---------------------------------------------------------------
100 * Tests whether a list of records, sorted by a String field in
101 * ascending order, is returned in the expected order.
103 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
104 dependsOnMethods = {"createList"})
105 public void sortByStringFieldAscending(String testName) throws Exception {
107 if (logger.isDebugEnabled()) {
108 logger.debug(testBanner(testName, CLASS_NAME));
111 String sortFieldName = qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE);
112 if (logger.isDebugEnabled()) {
113 logger.debug("Sorting on field name=" + sortFieldName);
115 MovementsCommonList list = readSortedList(sortFieldName);
116 List<MovementsCommonList.MovementListItem> items =
117 list.getMovementListItem();
119 ArrayList<String> values = new ArrayList<String>();
120 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
122 for (MovementsCommonList.MovementListItem item : items) {
123 // Because movementNote is not currently a summary field
124 // (returned in summary list items), we will need to verify
125 // sort order by retrieving full records, using the
126 // IDs provided in the summary list items. amd then retriving
127 // the value of that field from each of those records.
128 MovementsCommon movement = read(item.getCsid());
129 values.add(i, movement.getMovementNote());
130 if (logger.isDebugEnabled()) {
131 logger.debug("list-item[" + i + "] movementNote=" + values.get(i));
133 // Verify that the value of the specified field in the current record
134 // is equal to or greater than its value in the previous record,
135 // using a locale-specific collator.
137 // (Note: when used with certain text, this test case could potentially
138 // reflect inconsistencies, if any, between Java's collator and the
139 // collator used for ordering by the database. To help avoid this,
140 // it might be useful to keep test strings fairly generic.)
141 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
142 Assert.assertTrue(localeSpecificCollator.compare(values.get(i), values.get(i - 1)) >= 0);
150 * Tests whether a list of records, obtained by a keyword search, and
151 * sorted by a String field in ascending order, is returned in the expected order.
153 * This verifies that summary list results from keyword searches, in
154 * addition to 'read list' requests, can be returned in sorted order.
156 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
157 dependsOnMethods = {"createList"})
158 public void sortKeywordSearchResultsByStringFieldAscending(String testName) throws Exception {
160 if (logger.isDebugEnabled()) {
161 logger.debug(testBanner(testName, CLASS_NAME));
164 String sortFieldName = qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE);
165 if (logger.isDebugEnabled()) {
166 logger.debug("Sorting on field name=" + sortFieldName);
168 MovementsCommonList list = keywordSearchSortedBy(TEST_SPECIFIC_KEYWORD, sortFieldName);
169 List<MovementsCommonList.MovementListItem> items =
170 list.getMovementListItem();
172 ArrayList<String> values = new ArrayList<String>();
173 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
175 for (MovementsCommonList.MovementListItem item : items) {
176 // Because movementNote is not currently a summary field
177 // (returned in summary list items), we will need to verify
178 // sort order by retrieving full records, using the
179 // IDs provided in the summary list items. amd then retriving
180 // the value of that field from each of those records.
181 MovementsCommon movement = read(item.getCsid());
182 values.add(i, movement.getMovementNote());
183 if (logger.isDebugEnabled()) {
184 logger.debug("list-item[" + i + "] movementNote=" + values.get(i));
186 // Verify that the value of the specified field in the current record
187 // is equal to or greater than its value in the previous record,
188 // using a locale-specific collator.
190 // (Note: when used with certain text, this test case could potentially
191 // reflect inconsistencies, if any, between Java's collator and the
192 // collator used for ordering by the database. To help avoid this,
193 // it might be useful to keep test strings fairly generic.)
194 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
195 Assert.assertTrue(localeSpecificCollator.compare(values.get(i), values.get(i - 1)) >= 0);
203 * Tests whether a list of records, sorted by a String field in
204 * descending order, is returned in the expected order.
206 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
207 dependsOnMethods = {"createList"})
208 public void sortByStringFieldDescending(String testName) throws Exception {
210 if (logger.isDebugEnabled()) {
211 logger.debug(testBanner(testName, CLASS_NAME));
214 String sortFieldName =
215 asDescendingSort(qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE));
216 if (logger.isDebugEnabled()) {
217 logger.debug("Sorting on field name=" + sortFieldName);
219 MovementsCommonList list = readSortedList(sortFieldName);
220 List<MovementsCommonList.MovementListItem> items =
221 list.getMovementListItem();
223 ArrayList<String> values = new ArrayList<String>();
224 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
226 for (MovementsCommonList.MovementListItem item : items) {
227 // Because movementNote is not currently a summary field
228 // (returned in summary list items), we will need to verify
229 // sort order by retrieving full records, using the
230 // IDs provided in the summary list items. amd then retriving
231 // the value of that field from each of those records.
232 MovementsCommon movement = read(item.getCsid());
233 values.add(i, movement.getMovementNote());
234 if (logger.isDebugEnabled()) {
235 logger.debug("list-item[" + i + "] movementNote=" + values.get(i));
237 // Verify that the value of the specified field in the current record
238 // is less than or equal to than its value in the previous record,
239 // using a locale-specific collator.
241 // (Note: when used with certain text, this test case could potentially
242 // reflect inconsistencies, if any, between Java's collator and the
243 // collator used for ordering by the database. To help avoid this,
244 // it might be useful to keep test strings fairly generic.)
245 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
246 Assert.assertTrue(localeSpecificCollator.compare(values.get(i), values.get(i - 1)) <= 0);
254 * Tests whether a list of records, sorted by a dateTime field in
255 * ascending order, is returned in the expected order.
257 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
258 dependsOnMethods = {"createList"})
259 public void sortByDateTimeFieldAscending(String testName) throws Exception {
261 if (logger.isDebugEnabled()) {
262 logger.debug(testBanner(testName, CLASS_NAME));
265 String sortFieldName = qualifySortFieldName(MovementJAXBSchema.LOCATION_DATE);
266 if (logger.isDebugEnabled()) {
267 logger.debug("Sorting on field name=" + sortFieldName);
269 MovementsCommonList list = readSortedList(sortFieldName);
270 List<MovementsCommonList.MovementListItem> items =
271 list.getMovementListItem();
273 ArrayList<String> values = new ArrayList<String>();
274 Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
276 for (MovementsCommonList.MovementListItem item : items) {
277 values.add(i, item.getLocationDate());
278 if (logger.isDebugEnabled()) {
279 logger.debug("list-item[" + i + "] locationDate=" + values.get(i));
281 // Verify that the value of the specified field in the current record
282 // is equal to or greater than its value in the previous record.
283 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
284 Assert.assertTrue(comparator.compare(values.get(i), values.get(i - 1)) >= 0);
291 * Tests whether a list of records, sorted by a dateTime field in
292 * descending order, is returned in the expected order.
294 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
295 dependsOnMethods = {"createList"})
296 public void sortByDateTimeFieldDescending(String testName) throws Exception {
298 if (logger.isDebugEnabled()) {
299 logger.debug(testBanner(testName, CLASS_NAME));
302 String sortFieldName =
303 asDescendingSort(qualifySortFieldName(MovementJAXBSchema.LOCATION_DATE));
304 if (logger.isDebugEnabled()) {
305 logger.debug("Sorting on field name=" + sortFieldName);
307 MovementsCommonList list = readSortedList(sortFieldName);
308 List<MovementsCommonList.MovementListItem> items =
309 list.getMovementListItem();
311 ArrayList<String> values = new ArrayList<String>();
312 Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
314 for (MovementsCommonList.MovementListItem item : items) {
315 values.add(i, item.getLocationDate());
316 if (logger.isDebugEnabled()) {
317 logger.debug("list-item[" + i + "] locationDate=" + values.get(i));
319 // Verify that the value of the specified field in the current record
320 // is less than or equal to its value in the previous record.
321 if (i > 0 && values.get(i) != null && values.get(i - 1) != null) {
322 Assert.assertTrue(comparator.compare(values.get(i), values.get(i - 1)) <= 0);
329 * Tests whether a list of records, sorted by two different fields in
330 * ascending order, is returned in the expected order.
332 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
333 dependsOnMethods = {"createList"})
334 public void sortByTwoFieldsAscending(String testName) throws Exception {
336 if (logger.isDebugEnabled()) {
337 logger.debug(testBanner(testName, CLASS_NAME));
340 String firstSortFieldName = qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE);
341 String secondSortFieldName = qualifySortFieldName(MovementJAXBSchema.LOCATION_DATE);
342 if (logger.isDebugEnabled()) {
343 logger.debug("Sorting on field names=" + firstSortFieldName + " and " + secondSortFieldName);
345 String sortExpression = firstSortFieldName + SORT_FIELD_SEPARATOR + secondSortFieldName;
346 MovementsCommonList list = readSortedList(sortExpression);
347 List<MovementsCommonList.MovementListItem> items =
348 list.getMovementListItem();
350 ArrayList<String> firstFieldValues = new ArrayList<String>();
351 ArrayList<String> secondFieldValues = new ArrayList<String>();
352 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
353 Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
355 for (MovementsCommonList.MovementListItem item : items) {
356 // Because movementNote is not currently a summary field
357 // (returned in summary list items), we will need to verify
358 // sort order by retrieving full records, using the
359 // IDs provided in the summary list items. amd then retriving
360 // the value of that field from each of those records.
361 MovementsCommon movement = read(item.getCsid());
362 firstFieldValues.add(i, movement.getMovementNote());
363 secondFieldValues.add(i, movement.getLocationDate());
364 if (logger.isDebugEnabled()) {
365 logger.debug("list-item[" + i + "] movementNote=" + firstFieldValues.get(i));
366 logger.debug("list-item[" + i + "] locationDate=" + secondFieldValues.get(i));
368 // Verify that the value of the specified field in the current record
369 // is less than or greater than its value in the previous record.
370 if (i > 0 && firstFieldValues.get(i) != null && firstFieldValues.get(i - 1) != null) {
371 Assert.assertTrue(localeSpecificCollator.compare(firstFieldValues.get(i), firstFieldValues.get(i - 1)) >= 0);
372 // If the value of the first sort field in the current record is identical to
373 // its value in the previous record, verify that the value of the second sort
374 // field is equal to or greater than its value in the previous record,
375 // using a locale-specific collator.
376 if (localeSpecificCollator.compare(firstFieldValues.get(i), firstFieldValues.get(i - 1)) == 0) {
377 if (i > 0 && secondFieldValues.get(i) != null && secondFieldValues.get(i - 1) != null) {
378 Assert.assertTrue(comparator.compare(secondFieldValues.get(i), secondFieldValues.get(i - 1)) >= 0);
387 * Tests whether a list of records, sorted by one different fields in
388 * descending order and a second field in ascending order, is returned in the expected order.
390 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
391 dependsOnMethods = {"createList"})
392 public void sortByOneFieldAscendingOneFieldsDescending(String testName) throws Exception {
394 if (logger.isDebugEnabled()) {
395 logger.debug(testBanner(testName, CLASS_NAME));
398 String firstSortFieldName =
399 asDescendingSort(qualifySortFieldName(MovementJAXBSchema.LOCATION_DATE));
400 String secondSortFieldName = qualifySortFieldName(MovementJAXBSchema.MOVEMENT_NOTE);
401 if (logger.isDebugEnabled()) {
402 logger.debug("Sorting on field names=" + firstSortFieldName + " and " + secondSortFieldName);
404 String sortExpression = firstSortFieldName + SORT_FIELD_SEPARATOR + secondSortFieldName;
405 MovementsCommonList list = readSortedList(sortExpression);
406 List<MovementsCommonList.MovementListItem> items =
407 list.getMovementListItem();
409 ArrayList<String> firstFieldValues = new ArrayList<String>();
410 ArrayList<String> secondFieldValues = new ArrayList<String>();
411 Collator localeSpecificCollator = Collator.getInstance(LOCALE);
412 Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
414 for (MovementsCommonList.MovementListItem item : items) {
415 // Because movementNote is not currently a summary field
416 // (returned in summary list items), we will need to verify
417 // sort order by retrieving full records, using the
418 // IDs provided in the summary list items. amd then retriving
419 // the value of that field from each of those records.
420 MovementsCommon movement = read(item.getCsid());
421 firstFieldValues.add(i, movement.getLocationDate());
422 secondFieldValues.add(i, movement.getMovementNote());
423 if (logger.isDebugEnabled()) {
424 logger.debug("list-item[" + i + "] locationDate=" + firstFieldValues.get(i));
425 logger.debug("list-item[" + i + "] movementNote=" + secondFieldValues.get(i));
427 // Verify that the value of the specified field in the current record
428 // is less than or equal to than its value in the previous record.
429 if (i > 0 && firstFieldValues.get(i) != null && firstFieldValues.get(i - 1) != null) {
430 Assert.assertTrue(comparator.compare(firstFieldValues.get(i), firstFieldValues.get(i - 1)) <= 0);
431 // If the value of the first sort field in the current record is identical to
432 // its value in the previous record, verify that the value of the second sort
433 // field is equal to or greater than its value in the previous record,
434 // using a locale-specific collator.
435 if (comparator.compare(firstFieldValues.get(i), firstFieldValues.get(i - 1)) == 0) {
436 if (i > 0 && secondFieldValues.get(i) != null && secondFieldValues.get(i - 1) != null) {
437 Assert.assertTrue(localeSpecificCollator.compare(secondFieldValues.get(i), secondFieldValues.get(i - 1)) >= 0);
447 * Tests whether a request to sort by an empty field name is handled
448 * as expected: the query parameter is simply ignored, and a list
449 * of records is returned, unsorted, with a success result.
451 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
452 public void sortWithEmptySortFieldName(String testName) throws Exception {
454 if (logger.isDebugEnabled()) {
455 logger.debug(testBanner(testName, CLASS_NAME));
457 testSetup(STATUS_OK, ServiceRequestType.READ);
459 // Submit the request to the service and store the response.
460 MovementClient client = new MovementClient();
461 final String EMPTY_SORT_FIELD_NAME = "";
462 ClientResponse<MovementsCommonList> res =
463 client.readListSortedBy(EMPTY_SORT_FIELD_NAME);
464 int statusCode = res.getStatus();
466 // Check the status code of the response: does it match
467 // the expected response(s)?
468 if (logger.isDebugEnabled()) {
469 logger.debug(testName + ": status = " + statusCode);
471 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
472 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
473 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
480 * Tests whether a request to sort by an unqualified field name is
481 * handled as expected. The field name provided in this test is valid,
482 * but has not been qualified by being prefixed by a schema name and delimiter.
484 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
485 public void sortWithUnqualifiedFieldName(String testName) throws Exception {
487 if (logger.isDebugEnabled()) {
488 logger.debug(testBanner(testName, CLASS_NAME));
490 // FIXME: Ultimately, this should return a BAD_REQUEST status.
491 testSetup(STATUS_INTERNAL_SERVER_ERROR, ServiceRequestType.READ);
493 // Submit the request to the service and store the response.
494 MovementClient client = new MovementClient();
495 ClientResponse<MovementsCommonList> res =
496 client.readListSortedBy(MovementJAXBSchema.LOCATION_DATE);
497 int statusCode = res.getStatus();
499 // Check the status code of the response: does it match
500 // the expected response(s)?
501 if (logger.isDebugEnabled()) {
502 logger.debug(testName + ": status = " + statusCode);
504 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
505 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
506 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
511 * Tests whether a request to sort by an invalid identifier for the
512 * sort order (ascending or descending) is handled as expected.
514 @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
515 public void sortWithInvalidSortOrderIdentifier(String testName) throws Exception {
517 if (logger.isDebugEnabled()) {
518 logger.debug(testBanner(testName, CLASS_NAME));
520 // FIXME: Ultimately, this should return a BAD_REQUEST status.
521 testSetup(STATUS_INTERNAL_SERVER_ERROR, ServiceRequestType.READ);
523 // Submit the request to the service and store the response.
524 MovementClient client = new MovementClient();
525 final String INVALID_SORT_ORDER_IDENTIFIER = "NO_DIRECTION";
526 ClientResponse<MovementsCommonList> res =
527 client.readListSortedBy(MovementJAXBSchema.LOCATION_DATE
528 + " " + INVALID_SORT_ORDER_IDENTIFIER);
529 int statusCode = res.getStatus();
531 // Check the status code of the response: does it match
532 // the expected response(s)?
533 if (logger.isDebugEnabled()) {
534 logger.debug(testName + ": status = " + statusCode);
536 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
537 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
538 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
543 * Tests whether a request to sort by a malformed field name is
544 * handled as expected.
547 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class)
548 public void sortWithMalformedFieldName(String testName) throws Exception {
550 // FIXME: Implement this stub method.
552 // FIXME: Consider splitting this test into various tests, with
553 // different malformed field name formats that might confuse parsers
554 // and/or validation code.
556 // FIXME: Consider fixing DocumentFilter.setSortOrder() to return
557 // an error response to this test case, then revise this test case
558 // to expect that response.
563 // ---------------------------------------------------------------
564 // Cleanup of resources created during testing
565 // ---------------------------------------------------------------
567 * Deletes all resources created by tests, after all tests have been run.
569 * This cleanup method will always be run, even if one or more tests fail.
570 * For this reason, it attempts to remove all resources created
571 * at any point during testing, even if some of those resources
572 * may be expected to be deleted by certain tests.
574 @AfterClass(alwaysRun = true)
575 public void cleanUp() {
576 String noTest = System.getProperty("noTestCleanup");
577 if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
578 if (logger.isDebugEnabled()) {
579 logger.debug("Skipping Cleanup phase ...");
583 if (logger.isDebugEnabled()) {
584 logger.debug("Cleaning up temporary resources created for testing ...");
586 // Delete all Movement resource(s) created during this test.
587 MovementClient movementClient = new MovementClient();
588 for (String resourceId : movementIdsCreated) {
589 // Note: Any non-success responses are ignored and not reported.
590 movementClient.delete(resourceId);
594 // ---------------------------------------------------------------
595 // Utility methods used by tests above
596 // ---------------------------------------------------------------
599 protected String getServiceName() {
604 public String getServicePathComponent() {
605 return SERVICE_PATH_COMPONENT;
608 private String getCommonSchemaName() {
609 // FIXME: While this convention - appending a suffix to the name of
610 // the service's first unique URL path component - works, it would
611 // be preferable to get the common schema name from configuration.
613 // Such configuration is provided for example, on the services side, in
614 // org.collectionspace.services.common.context.AbstractServiceContextImpl
615 return getServicePathComponent() + "_" + "common";
618 public String qualifySortFieldName(String fieldName) {
619 return getCommonSchemaName() + DELIMITER_SCHEMA_AND_FIELD + fieldName;
622 public String asDescendingSort(String qualifiedFieldName) {
623 return qualifiedFieldName + " " + KEYWORD_DESCENDING_SEARCH;
627 * A data provider that provides a set of unsorted values, which are
628 * to be used in populating (seeding) values in test records.
630 * Data elements provided for each test record consist of:
631 * * An integer, reflecting expected sort order.
632 * * US English text, to populate the value of a free text (String) field.
633 * * An ISO 8601 timestamp, to populate the value of a calendar date (dateTime) field.
635 @DataProvider(name = "unsortedValues")
636 public Object[][] unsortedValues() {
637 // FIXME: ADR Add a test record-specific string so we have the option of
638 // constraining tests to only test records, in list or search results.
639 final String TEST_RECORD_SPECIFIC_STRING = CLASS_NAME + " " + TEST_SPECIFIC_KEYWORD;
640 return new Object[][]{
641 {1, "Aardvark and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2009-01-29T00:00:05Z"},
642 {10, "Zounds! " + TEST_RECORD_SPECIFIC_STRING, "2010-08-31T00:00:00Z"},
643 {3, "Aardvark and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2010-08-30T00:00:00Z"},
644 {7, "Bat fling off wall. " + TEST_RECORD_SPECIFIC_STRING, "2010-08-30T00:00:00Z"},
645 {4, "Aardvarks and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2009-01-29T08:00:00Z"},
646 {5, "Aardvarks and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"},
647 {2, "Aardvark and plumeria. " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"},
648 {9, "Zounds! " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"}, // Identical to next record
649 {8, "Zounds! " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"},
650 {6, "Bat flies off ball. " + TEST_RECORD_SPECIFIC_STRING, "2009-05-29T00:00:00Z"}
655 * Create multiple test records, initially in unsorted order,
656 * using values for various fields obtained from the data provider.
658 @Test(dataProvider = "unsortedValues")
659 public void createList(int expectedSortOrder, String movementNote,
660 String locationDate) throws Exception {
662 String testName = "createList";
663 if (logger.isDebugEnabled()) {
664 logger.debug(testBanner(testName, CLASS_NAME));
666 testSetup(STATUS_CREATED, ServiceRequestType.CREATE);
668 // Iterates through the sets of values returned by the data provider,
669 // and creates a corresponding test record for each set of values.
670 create(movementNote, locationDate);
673 private void create(String movementNote, String locationDate) throws Exception {
675 String testName = "create";
676 testSetup(STATUS_CREATED, ServiceRequestType.CREATE);
678 // Submit the request to the service and store the response.
679 PoxPayloadOut multipart = createMovementInstance(createIdentifier(),
680 movementNote, locationDate);
681 MovementClient client = new MovementClient();
682 ClientResponse<Response> res = client.create(multipart);
683 int statusCode = res.getStatus();
685 // Check the status code of the response: does it match
686 // the expected response(s)?
689 // Does it fall within the set of valid status codes?
690 // Does it exactly match the expected status code?
691 if (logger.isDebugEnabled()) {
692 logger.debug(testName + ": status = " + statusCode);
694 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
695 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
696 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
698 // Store the IDs from every resource created by tests,
699 // so they can be deleted after tests have been run.
700 movementIdsCreated.add(extractId(res));
703 private MovementsCommon read(String csid) throws Exception {
705 String testName = "read";
706 testSetup(STATUS_OK, ServiceRequestType.READ);
708 // Submit the request to the service and store the response.
709 MovementClient client = new MovementClient();
710 ClientResponse<String> res = client.read(csid);
711 int statusCode = res.getStatus();
713 // Check the status code of the response: does it match
714 // the expected response(s)?
715 if (logger.isDebugEnabled()) {
716 logger.debug(testName + ": status = " + statusCode);
718 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
719 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
720 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
722 // Extract and return the common part of the record.
723 PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
724 PayloadInputPart payloadInputPart = input.getPart(client.getCommonPartName());
725 MovementsCommon movementCommon = null;
726 if (payloadInputPart != null) {
727 movementCommon = (MovementsCommon) payloadInputPart.getBody();
730 return movementCommon;
733 private PoxPayloadOut createMovementInstance(
734 String movementReferenceNumber,
736 String locationDate) {
737 MovementsCommon movementCommon = new MovementsCommon();
738 movementCommon.setMovementReferenceNumber(movementReferenceNumber);
739 movementCommon.setMovementNote(movementNote);
740 movementCommon.setLocationDate(locationDate);
742 PoxPayloadOut multipart = new PoxPayloadOut(this.getServicePathComponent());
743 PayloadOutputPart commonPart =
744 multipart.addPart(movementCommon, MediaType.APPLICATION_XML_TYPE);
745 commonPart.setLabel(new MovementClient().getCommonPartName());
746 if (logger.isDebugEnabled()) {
747 logger.debug("to be created, movement common");
748 logger.debug(objectAsXmlString(movementCommon, MovementsCommon.class));
754 private MovementsCommonList readSortedList(String sortFieldName) throws Exception {
756 String testName = "readSortedList";
757 testSetup(STATUS_OK, ServiceRequestType.READ);
759 // Submit the request to the service and store the response.
760 MovementClient client = new MovementClient();
762 ClientResponse<MovementsCommonList> res =
763 client.readListSortedBy(sortFieldName);
764 MovementsCommonList list = res.getEntity();
765 int statusCode = res.getStatus();
767 // Check the status code of the response: does it match
768 // the expected response(s)?
769 if (logger.isDebugEnabled()) {
770 logger.debug(testName + ": status = " + statusCode);
772 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
773 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
774 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
780 private MovementsCommonList keywordSearchSortedBy(String keywords,
781 String sortFieldName) throws Exception {
783 String testName = "keywordSearchSortedBy";
784 testSetup(STATUS_OK, ServiceRequestType.READ);
786 // Submit the request to the service and store the response.
787 MovementClient client = new MovementClient();
789 ClientResponse<MovementsCommonList> res =
790 client.keywordSearchSortedBy(keywords, sortFieldName);
791 MovementsCommonList list = res.getEntity();
792 int statusCode = res.getStatus();
794 // Check the status code of the response: does it match
795 // the expected response(s)?
796 if (logger.isDebugEnabled()) {
797 logger.debug(testName + ": status = " + statusCode);
799 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
800 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
801 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);