diff --git a/src/main/java/org/opengis/cite/wfs30/collections/GetFeaturesOperation.java b/src/main/java/org/opengis/cite/wfs30/collections/GetFeaturesOperation.java index 733c38b9..9e593f92 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/GetFeaturesOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/GetFeaturesOperation.java @@ -1,20 +1,34 @@ package org.opengis.cite.wfs30.collections; import static io.restassured.http.Method.GET; +import static org.opengis.cite.wfs30.SuiteAttribute.API_MODEL; import static org.opengis.cite.wfs30.WFS3.GEOJSON_MIME_TYPE; - +import static org.opengis.cite.wfs30.WFS3.PATH.COLLECTIONS; +import static org.opengis.cite.wfs30.util.JsonUtils.findLinkToItself; +import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithSupportedMediaTypeByRel; +import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithoutRelOrType; +import static org.opengis.cite.wfs30.util.JsonUtils.findUnsupportedTypes; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.opengis.cite.wfs30.CommonFixture; import org.opengis.cite.wfs30.SuiteAttribute; +import org.opengis.cite.wfs30.openapi3.OpenApiUtils; +import org.opengis.cite.wfs30.openapi3.TestPoint; import org.testng.ITestContext; import org.testng.SkipException; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import com.reprezen.kaizen.oasparser.model3.MediaType; +import com.reprezen.kaizen.oasparser.model3.OpenApi3; + import io.restassured.path.json.JsonPath; import io.restassured.response.Response; @@ -27,6 +41,8 @@ public class GetFeaturesOperation extends CommonFixture { private List> collections; + private OpenApi3 apiModel; + @DataProvider(name = "collectionItemUris") public Object[][] collectionItemUris( ITestContext testContext ) { Object[][] collectionsData = new Object[collections.size()][]; @@ -38,6 +54,7 @@ public Object[][] collectionItemUris( ITestContext testContext ) { @BeforeClass public void retrieveRequiredInformationFromTestContext( ITestContext testContext ) { + this.apiModel = (OpenApi3) testContext.getSuite().getAttribute( API_MODEL.getName() ); this.collections = (List>) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTIONS.getName() ); } @@ -65,7 +82,7 @@ public void retrieveRequiredInformationFromTestContext( ITestContext testContext * @param collection * the collection under test, never null */ - @Test(description = "Implements A.4.4.9. Validate the Get Features Operation (Requirement 17, Requirement 24)", dataProvider = "collectionItemUris", dependsOnGroups = "collections") + @Test(description = "Implements A.4.4.9. Validate the Get Features Operation (Requirement 17, 24)", dataProvider = "collectionItemUris", dependsOnGroups = "collections") public void validateGetFeaturesOperation( Map collection ) { String collectionName = (String) collection.get( "name" ); @@ -80,7 +97,7 @@ public void validateGetFeaturesOperation( Map collection ) { } /** - * A.4.4.10. Validate the Get Features Operation Response + * A.4.4.10. Validate the Get Features Operation Response (Part 1) * * a) Test Purpose: Validate the Get Feature Operation Response. * @@ -88,19 +105,63 @@ public void validateGetFeaturesOperation( Map collection ) { * * c) Test Method: * - * Validate the structure of the response as follows: + * Validate that the following links are included in the response document: To itself, Alternate encodings of this + * document in every other media type as identified by the compliance classes for this server. * - * For HTML use TBD + * Validate that each link includes a rel and type parameter. * - * For GeoJSON use featureCollectionGeoJSON.yaml + * d) References: Requirements 25, 26 * - * For GML use featureCollectionGML.yaml + * @param collection + * the collection under test, never null + */ + @Test(description = "Implements A.4.4.10. Validate the Get Features Operation Response (Requirement 25, 26)", dataProvider = "collectionItemUris", dependsOnMethods = "validateGetFeaturesOperation") + public void validateGetFeaturesOperationResponse_Links( Map collection ) { + String collectionName = (String) collection.get( "name" ); + Response response = collectionNameAndResponse.get( collectionName ); + if ( response == null ) + throw new SkipException( "Could not find a response for collection with name " + collectionName ); + + List testPointsForNamedCollection = OpenApiUtils.retrieveTestPoints( apiModel, COLLECTIONS, + collectionName + "/items" ); + if ( testPointsForNamedCollection.isEmpty() ) + throw new SkipException( "Could not find collection with name " + collectionName + + " in the OpenAPI document" ); + TestPoint testPoint = testPointsForNamedCollection.get( 0 ); + + JsonPath jsonPath = response.jsonPath(); + List> links = jsonPath.getList( "links" ); + + // Validate that the retrieved document includes links for: Itself + Map linkToSelf = findLinkToItself( links ); + assertNotNull( linkToSelf, "Feature Collection Metadata document must include a link for itself" ); + + // Validate that the retrieved document includes links for: Alternate encodings of this document in + // every other media type as identified by the compliance classes for this server. + List mediaTypesToSupport = createListOfMediaTypesToSupport( testPoint, linkToSelf ); + List> alternateLinks = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, + "alternate" ); + List typesWithoutLink = findUnsupportedTypes( alternateLinks, mediaTypesToSupport ); + assertTrue( typesWithoutLink.isEmpty(), + "Feature Collection Metadata document must include links for alternate encodings. Missing links for types " + + typesWithoutLink ); + + // Validate that each link includes a rel and type parameter. + List linksWithoutRelOrType = findLinksWithoutRelOrType( links ); + assertTrue( linksWithoutRelOrType.isEmpty(), + "Links for alternate encodings must include a rel and type parameter. Missing for links " + + linksWithoutRelOrType ); + } + + /** + * A.4.4.10. Validate the Get Features Operation Response (Part 2) * - * Validate that the following links are included in the response document: To itself, Alternate encodings of this - * document in every other media type as identified by the compliance classes for this server. + * a) Test Purpose: Validate the Get Feature Operation Response. * - * Validate that each link includes a rel and type parameter. + * b) Pre-conditions: A collection of Features has been retrieved * + * c) Test Method: + * * If a property timeStamp is included in the response, validate that it is close to the current time. * * If a property numberReturned is included in the response, validate that the number is equal to the number of @@ -110,21 +171,19 @@ public void validateGetFeaturesOperation( Map collection ) { * included and count the aggregated number of features returned in all responses during the iteration. Validate * that the value is identical to the numberReturned stated in the initial response. * - * d) References: Requirements 24, 25, 26, 27, 28 and 29 + * d) References: Requirements 27, 28 and 29 * * @param collection * the collection under test, never null */ - @Test(description = "Implements A.4.4.10. Validate the Get Features Operation Response (Requirement 25)", dataProvider = "collectionItemUris", dependsOnMethods = "validateGetFeaturesOperation") - public void validateGetFeaturesOperationResponse( Map collection ) { + @Test(description = "Implements A.4.4.10. Validate the Get Features Operation Response (Requirement 27, 28, 29)", dataProvider = "collectionItemUris", dependsOnMethods = "validateGetFeaturesOperation") + public void validateGetFeaturesOperationResponse_Properties( Map collection ) { String collectionName = (String) collection.get( "name" ); Response response = collectionNameAndResponse.get( collectionName ); if ( response == null ) throw new SkipException( "Could not find a response for collection with name " + collectionName ); - JsonPath jsonPath = response.jsonPath(); - // TODO... - + // TODO } private String findGetFeatureUrlForGeoJson( Map collection ) { @@ -138,4 +197,13 @@ private String findGetFeatureUrlForGeoJson( Map collection ) { } return null; } + + private List createListOfMediaTypesToSupport( TestPoint testPoint, Map linkToSelf ) { + Map contentMediaTypes = testPoint.getContentMediaTypes(); + List mediaTypesToSupport = new ArrayList<>(); + mediaTypesToSupport.addAll( contentMediaTypes.keySet() ); + if ( linkToSelf != null ) + mediaTypesToSupport.remove( linkToSelf.get( "type" ) ); + return mediaTypesToSupport; + } } diff --git a/src/test/java/org/opengis/cite/wfs30/collections/GetFeaturesOperationIT.java b/src/test/java/org/opengis/cite/wfs30/collections/GetFeaturesOperationIT.java index 6bf581fc..5bae62c2 100644 --- a/src/test/java/org/opengis/cite/wfs30/collections/GetFeaturesOperationIT.java +++ b/src/test/java/org/opengis/cite/wfs30/collections/GetFeaturesOperationIT.java @@ -51,7 +51,8 @@ public void testGetFeatureOperations() { for ( Object[] collection : collections ) { Map parameter = (Map) collection[0]; getFeaturesOperation.validateGetFeaturesOperation( parameter ); - getFeaturesOperation.validateGetFeaturesOperationResponse( parameter ); + getFeaturesOperation.validateGetFeaturesOperationResponse_Links( parameter ); + getFeaturesOperation.validateGetFeaturesOperationResponse_Properties( parameter ); } }