From 99f1565a5af64235a78721c235f8da8f476f8632 Mon Sep 17 00:00:00 2001 From: Lyn Elisa Goltz Date: Mon, 13 Aug 2018 11:32:32 +0200 Subject: [PATCH 1/4] #30 - removed assert from test validateFeatureCollectionsMetadataOperationResponse_Collections as it collects the collections --- .../FeatureCollectionsMetadataOperation.java | 41 +------------------ ...FeatureCollectionsMetadataOperationIT.java | 1 - 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java b/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java index 3e35dbd5..3dbee72c 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java @@ -45,8 +45,6 @@ public class FeatureCollectionsMetadataOperation extends CommonFixture { private final Map>> testPointAndCollections = new HashMap<>(); - private final List collectionNamesFromLandingPage = new ArrayList<>(); - private OpenApi3 apiModel; private Object[][] testPointsData; @@ -75,19 +73,6 @@ public Object[][] collections( ITestContext testContext ) { return objects; } - @BeforeClass - public void parseRequiredMetadata( ITestContext testContext ) { - Response request = init().baseUri( rootUri.toString() ).accept( JSON ).when().request( GET, "/" ); - JsonPath jsonPath = request.jsonPath(); - - List collections = jsonPath.getList( "collections" ); - for ( Object collectionObject : collections ) { - Map collection = (Map) collectionObject; - String collectionName = (String) collection.get( "name" ); - this.collectionNamesFromLandingPage.add( collectionName ); - } - } - @BeforeClass public void openApiDocument( ITestContext testContext ) { this.apiModel = (OpenApi3) testContext.getSuite().getAttribute( API_MODEL.getName() ); @@ -201,10 +186,8 @@ public void validateFeatureCollectionsMetadataOperationResponse_Collections( Tes JsonPath jsonPath = response.jsonPath(); List collections = jsonPath.getList( "collections" ); - List missingCollectionNames = findMissingCollectionNames( collections ); - assertTrue( missingCollectionNames.isEmpty(), - "Feature Collection Metadata document must include a collections property for each collection in the dataset. Missing collection properties " - + missingCollectionNames ); + // Test method cannot be verified as the provided collections are not known. + this.testPointAndCollections.put( testPoint, createCollectionsMap( collections ) ); } @@ -356,26 +339,6 @@ private void validateFeatureCollectionMetadataOperationResponse( Response respon assertEquals( collection, jsonPath.get() ); } - private List findMissingCollectionNames( List collections ) { - List missingCollectionNames = new ArrayList<>(); - for ( String collectionNameFromLandingPage : this.collectionNamesFromLandingPage ) { - Map collection = findCollectionByName( collectionNameFromLandingPage, collections ); - if ( collection == null ) - missingCollectionNames.add( collectionNameFromLandingPage ); - } - return missingCollectionNames; - } - - private Map findCollectionByName( String collectionNameFromLandingPage, List collections ) { - for ( Object collectionObject : collections ) { - Map collection = (Map) collectionObject; - Object collectionName = collection.get( "name" ); - if ( collectionNameFromLandingPage.equals( collectionName ) ) - return collection; - } - return null; - } - private List> createCollectionsMap( List collections ) { List> collectionsMap = new ArrayList<>(); for ( Object collection : collections ) diff --git a/src/test/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperationIT.java b/src/test/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperationIT.java index 5cc57821..469589cf 100644 --- a/src/test/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperationIT.java +++ b/src/test/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperationIT.java @@ -50,7 +50,6 @@ public static void initTestFixture() public void testValidateFeatureCollectionsMetadataOperationResponse() { FeatureCollectionsMetadataOperation featureCollectionsMetadataOperation = new FeatureCollectionsMetadataOperation(); featureCollectionsMetadataOperation.initCommonFixture( testContext ); - featureCollectionsMetadataOperation.parseRequiredMetadata( testContext ); featureCollectionsMetadataOperation.openApiDocument( testContext ); UriTemplate conformanceUri = new UriTemplate( "https://www.ldproxy.nrw.de/kataster/collections" ); TestPoint testPoint = new TestPoint( conformanceUri, mediaTypes() ); From 71021be1330b481a9f5f3f46c82553cf55fa49d2 Mon Sep 17 00:00:00 2001 From: Lyn Elisa Goltz Date: Tue, 14 Aug 2018 11:42:51 +0200 Subject: [PATCH 2/4] #28 - improved access to collection metadata, collections and features and detection of uri templates --- .../FeatureCollectionsMetadataOperation.java | 19 +- .../collections/GetFeatureOperation.java | 21 +- .../collections/GetFeaturesOperation.java | 5 +- .../cite/wfs30/openapi3/OpenApiUtils.java | 96 +- .../collections/GetFeatureOperationIT.java | 10 +- .../cite/wfs30/openapi3/OpenApiUtilsTest.java | 92 +- .../wfs30/openapi3/openapi_compact-api.json | 930 ++++++++++++++++++ 7 files changed, 1109 insertions(+), 64 deletions(-) create mode 100644 src/test/resources/org/opengis/cite/wfs30/openapi3/openapi_compact-api.json diff --git a/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java b/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java index 3dbee72c..0949d241 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java @@ -5,6 +5,7 @@ import static org.opengis.cite.wfs30.SuiteAttribute.API_MODEL; import static org.opengis.cite.wfs30.WFS3.PATH.COLLECTIONS; import static org.opengis.cite.wfs30.openapi3.OpenApiUtils.retrieveTestPoints; +import static org.opengis.cite.wfs30.openapi3.OpenApiUtils.retrieveTestPointsForCollectionMetadata; import static org.opengis.cite.wfs30.util.JsonUtils.findLinkByRel; import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithSupportedMediaTypeByRel; import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithoutRelOrType; @@ -21,7 +22,6 @@ 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; @@ -217,8 +217,8 @@ public void validateFeatureCollectionsMetadataOperationResponse_Collections( Tes @Test(description = "Implements A.4.4.6. Validate a Collections Metadata document (Requirement 13)", groups = "collections", dataProvider = "collections", dependsOnMethods = "validateFeatureCollectionsMetadataOperationResponse_Collections") public void validateCollectionsMetadataDocument_Links( TestPoint testPoint, Map collection ) { String collectionName = (String) collection.get( "name" ); - List testPointsForNamedCollection = OpenApiUtils.retrieveTestPoints( apiModel, COLLECTIONS, - collectionName ); + List testPointsForNamedCollection = retrieveTestPointsForCollectionMetadata( apiModel, + collectionName ); if ( testPointsForNamedCollection.isEmpty() ) throw new SkipException( "Could not find collection with name " + collectionName + " in the OpenAPI document" ); @@ -274,13 +274,14 @@ public void validateCollectionsMetadataDocument_Extent( TestPoint testPoint, Map public void validateTheFeatureCollectionMetadataOperationAndResponse( TestPoint testPoint, Map collection ) { String collectionName = (String) collection.get( "name" ); - List testPointsForNamedCollection = OpenApiUtils.retrieveTestPoints( apiModel, COLLECTIONS, - collectionName ); + List testPointsForNamedCollection = retrieveTestPointsForCollectionMetadata( apiModel, + collectionName ); if ( testPointsForNamedCollection.isEmpty() ) throw new SkipException( "Could not find collection with name " + collectionName + " in the OpenAPI document" ); - Response response = validateTheFeatureCollectionMetadataOperationAndResponse( testPointsForNamedCollection.get( 0 ) ); + TestPoint testPointCollectionMetadata = testPointsForNamedCollection.get(0); + Response response = validateTheFeatureCollectionMetadataOperationAndResponse(testPointCollectionMetadata, collectionName); validateFeatureCollectionMetadataOperationResponse( response, collection ); } @@ -304,12 +305,14 @@ public void validateTheFeatureCollectionMetadataOperationAndResponse( TestPoint * Go to test A.4.4.8 * * d) References: Requirement 15 - * + * * @param testPoint * to test, never null + * @param collectionName */ - private Response validateTheFeatureCollectionMetadataOperationAndResponse( TestPoint testPoint ) { + private Response validateTheFeatureCollectionMetadataOperationAndResponse(TestPoint testPoint, String collectionName) { String testPointUri = testPoint.createUri(); + // TODO: add collectionName as required Response response = init().baseUri( testPointUri ).accept( JSON ).when().request( GET ); response.then().statusCode( 200 ); return response; diff --git a/src/main/java/org/opengis/cite/wfs30/collections/GetFeatureOperation.java b/src/main/java/org/opengis/cite/wfs30/collections/GetFeatureOperation.java index 36b6478a..30488b3c 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/GetFeatureOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/GetFeatureOperation.java @@ -3,8 +3,7 @@ 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.openapi3.OpenApiUtils.retrieveTestPoints; +import static org.opengis.cite.wfs30.openapi3.OpenApiUtils.retrieveTestPointsForFeature; import static org.opengis.cite.wfs30.util.JsonUtils.findLinkByRel; import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithSupportedMediaTypeByRel; import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithoutRelOrType; @@ -45,15 +44,6 @@ public class GetFeatureOperation extends CommonFixture { private final Map collectionNameAndResponse = new HashMap<>(); - @DataProvider(name = "collectionItemUris") - public Iterator collectionItemUris( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - for ( Map collection : collections ) { - collectionsData.add( new Object[] { collection } ); - } - return collectionsData.iterator(); - } - @DataProvider(name = "collectionFeatureId") public Iterator collectionFeatureId( ITestContext testContext ) { Map collectionNameToFeatureId = (Map) testContext.getSuite().getAttribute( SuiteAttribute.FEATUREIDS.getName() ); @@ -154,15 +144,16 @@ public void getFeatureOperation( Map collection, String featureI * @param collection * the collection under test, never null */ - @Test(description = "Implements A.4.4.15. Validate the Get Feature Operation Response (Requirement 32)", dataProvider = "collectionItemUris", dependsOnMethods = "getFeatureOperation") - public void validateTheGetFeatureOperationResponse( Map collection ) { + @Test(description = "Implements A.4.4.15. Validate the Get Feature Operation Response (Requirement 32)", dataProvider = "collectionFeatureId", dependsOnMethods = "getFeatureOperation") + public void validateTheGetFeatureOperationResponse( Map collection, String featureId ) { 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 = retrieveTestPoints( apiModel, COLLECTIONS, - collectionName + "\\/items\\/\\{.*\\}" ); + List testPointsForNamedCollection = retrieveTestPointsForFeature( apiModel, collectionName, + featureId ); + if ( testPointsForNamedCollection.isEmpty() ) throw new SkipException( "Could not find collection with name " + collectionName + " in the OpenAPI document" ); 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 1eea7307..682477de 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/GetFeaturesOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/GetFeaturesOperation.java @@ -4,6 +4,7 @@ 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.openapi3.OpenApiUtils.retrieveTestPointsForCollection; import static org.opengis.cite.wfs30.util.JsonUtils.collectNumberOfAllReturnedFeatures; import static org.opengis.cite.wfs30.util.JsonUtils.findLinkByRel; import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithSupportedMediaTypeByRel; @@ -35,7 +36,6 @@ 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.opengis.cite.wfs30.util.BBox; import org.opengis.cite.wfs30.util.TemporalExtent; @@ -217,8 +217,7 @@ public void validateTheGetFeaturesOperationResponse_Links( Map c if ( response == null ) throw new SkipException( "Could not find a response for collection with name " + collectionName ); - List testPointsForNamedCollection = OpenApiUtils.retrieveTestPoints( apiModel, COLLECTIONS, - collectionName + "/items" ); + List testPointsForNamedCollection = retrieveTestPointsForCollection( apiModel, collectionName ); if ( testPointsForNamedCollection.isEmpty() ) throw new SkipException( "Could not find collection with name " + collectionName + " in the OpenAPI document" ); diff --git a/src/main/java/org/opengis/cite/wfs30/openapi3/OpenApiUtils.java b/src/main/java/org/opengis/cite/wfs30/openapi3/OpenApiUtils.java index 6ed753ec..d9a0051a 100644 --- a/src/main/java/org/opengis/cite/wfs30/openapi3/OpenApiUtils.java +++ b/src/main/java/org/opengis/cite/wfs30/openapi3/OpenApiUtils.java @@ -1,11 +1,14 @@ package org.opengis.cite.wfs30.openapi3; +import static org.opengis.cite.wfs30.WFS3.PATH.COLLECTIONS; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Matcher; import org.opengis.cite.wfs30.WFS3.PATH; @@ -18,6 +21,7 @@ import com.reprezen.kaizen.oasparser.model3.Schema; import com.reprezen.kaizen.oasparser.model3.Server; import com.sun.jersey.api.uri.UriTemplate; +import com.sun.jersey.api.uri.UriTemplateParser; /** * @author Lyn Goltz @@ -27,6 +31,8 @@ public class OpenApiUtils { // as described in https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#fixed-fields private static final String DEFAULT_SERVER_URL = "/"; + public static final String TEMPLATE = "\\{.*\\}"; + private OpenApiUtils() { } @@ -54,7 +60,8 @@ public static List retrieveTestPoints( OpenApi3 apiModel ) { * @return the parsed test points, may be empty but never null */ public static List retrieveTestPoints( OpenApi3 apiModel, PATH path ) { - return retrieveTestPoints( apiModel, path, null ); + String requestedPath = "/" + path.getPathItem(); + return retrieveTestPoints( apiModel, requestedPath ); } /** @@ -63,21 +70,66 @@ public static List retrieveTestPoints( OpenApi3 apiModel, PATH path ) * * @param apiModel * never null - * @param path - * the path the test points should be assigned to, never null - * @param extendedPath + * @param collectionName * the extended path, may be null * @return the parsed test points, may be empty but never null */ - public static List retrieveTestPoints( OpenApi3 apiModel, PATH path, String extendedPath ) { + public static List retrieveTestPointsForCollectionMetadata( OpenApi3 apiModel, String collectionName ) { StringBuilder requestedPath = new StringBuilder(); - requestedPath.append( path.getPathItem() ); - if ( extendedPath != null ) { - if ( !extendedPath.startsWith( "/" ) ) - requestedPath.append( "/" ); - requestedPath.append( extendedPath ); - } - List pathItemObjects = identifyTestPoints( apiModel, requestedPath.toString() ); + requestedPath.append( "/" ); + requestedPath.append( COLLECTIONS.getPathItem() ); + requestedPath.append( "/" ); + requestedPath.append( collectionName ); + + return retrieveTestPoints( apiModel, requestedPath.toString() ); + } + + /** + * Parse the test points with the passed path including the extended path from the passed OpenApi3 document as + * described in A.4.3. Identify the Test Points. + * + * @param apiModel + * never null + * @param collectionName + * the extended path, may be null + * @return the parsed test points, may be empty but never null + */ + public static List retrieveTestPointsForCollection( OpenApi3 apiModel, String collectionName ) { + StringBuilder requestedPath = new StringBuilder(); + requestedPath.append( "/" ); + requestedPath.append( COLLECTIONS.getPathItem() ); + requestedPath.append( "/" ); + requestedPath.append( collectionName ); + requestedPath.append( "/items" ); + + return retrieveTestPoints( apiModel, requestedPath.toString() ); + } + + /** + * Parse the test points with the passed path including the extended path from the passed OpenApi3 document as + * described in A.4.3. Identify the Test Points. + * + * @param apiModel + * never null + * @param collectionName + * the extended path, may be null + * @return the parsed test points, may be empty but never null + */ + public static List retrieveTestPointsForFeature( OpenApi3 apiModel, String collectionName, + String featureId ) { + StringBuilder requestedPath = new StringBuilder(); + requestedPath.append( "/" ); + requestedPath.append( COLLECTIONS.getPathItem() ); + requestedPath.append( "/" ); + requestedPath.append( collectionName ); + requestedPath.append( "/items/" ); + requestedPath.append( featureId ); + + return retrieveTestPoints( apiModel, requestedPath.toString() ); + } + + private static List retrieveTestPoints( OpenApi3 apiModel, String requestedPath ) { + List pathItemObjects = identifyTestPoints( apiModel, requestedPath ); List pathItemAndServers = identifyServerUrls( apiModel, pathItemObjects ); return processServerObjects( pathItemAndServers ); } @@ -107,17 +159,13 @@ public static List retrieveTestPoints( OpenApi3 apiModel, PATH path, * never null */ private static List identifyTestPoints( OpenApi3 apiModel ) { - List paths = new ArrayList<>(); + List allTestPoints = new ArrayList<>(); for ( PATH path : PATH.values() ) - paths.add( path.getPathItem() ); - return identifyTestPoints( apiModel, paths ); + allTestPoints.addAll( identifyTestPoints( apiModel, "/" + path.getPathItem() ) ); + return allTestPoints; } private static List identifyTestPoints( OpenApi3 apiModel, String path ) { - return identifyTestPoints( apiModel, Collections.singletonList( path ) ); - } - - private static List identifyTestPoints( OpenApi3 apiModel, List path ) { List pathItems = new ArrayList<>(); Map pathItemObjects = apiModel.getPaths(); for ( Path pathItemObject : pathItemObjects.values() ) { @@ -129,12 +177,10 @@ private static List identifyTestPoints( OpenApi3 apiModel, List pa return pathItems; } - private static boolean isRequestedPath( String pathString, List path ) { - for ( String pathRequested : path ) { - if ( pathString.matches( "\\/" + pathRequested + "(\\/?)" ) ) - return true; - } - return false; + private static boolean isRequestedPath( String pathUnderTest, String pathToMatch ) { + UriTemplateParser parser = new UriTemplateParser( pathUnderTest ); + Matcher matcher = parser.getPattern().matcher( pathToMatch ); + return matcher.matches(); } /** diff --git a/src/test/java/org/opengis/cite/wfs30/collections/GetFeatureOperationIT.java b/src/test/java/org/opengis/cite/wfs30/collections/GetFeatureOperationIT.java index a72b1156..75577e1f 100644 --- a/src/test/java/org/opengis/cite/wfs30/collections/GetFeatureOperationIT.java +++ b/src/test/java/org/opengis/cite/wfs30/collections/GetFeatureOperationIT.java @@ -77,15 +77,7 @@ public void testGetFeatureOperations() { assertThat( featureId, notNullValue() ); getFeatureOperation.getFeatureOperation( collection, featureId ); - - Iterator iterator = getFeatureOperation.collectionItemUris( testContext ); - Object[] collectionByName = findCollectionByName( COLLECTION_NAME, iterator ); - assertThat( collectionByName, notNullValue() ); - - Map collection2 = (Map) collectionByName[0]; - assertThat( collection2, notNullValue() ); - - getFeatureOperation.validateTheGetFeatureOperationResponse( collection2 ); + getFeatureOperation.validateTheGetFeatureOperationResponse( collection, featureId ); } private Object[] findCollectionByName( String collectionName, Iterator collections ) { diff --git a/src/test/java/org/opengis/cite/wfs30/openapi3/OpenApiUtilsTest.java b/src/test/java/org/opengis/cite/wfs30/openapi3/OpenApiUtilsTest.java index 7e460e77..abcfe681 100644 --- a/src/test/java/org/opengis/cite/wfs30/openapi3/OpenApiUtilsTest.java +++ b/src/test/java/org/opengis/cite/wfs30/openapi3/OpenApiUtilsTest.java @@ -5,6 +5,9 @@ import static org.opengis.cite.wfs30.WFS3.PATH.API; import static org.opengis.cite.wfs30.WFS3.PATH.COLLECTIONS; import static org.opengis.cite.wfs30.openapi3.OpenApiUtils.retrieveTestPoints; +import static org.opengis.cite.wfs30.openapi3.OpenApiUtils.retrieveTestPointsForCollection; +import static org.opengis.cite.wfs30.openapi3.OpenApiUtils.retrieveTestPointsForCollectionMetadata; +import static org.opengis.cite.wfs30.openapi3.OpenApiUtils.retrieveTestPointsForFeature; import java.net.URL; import java.util.List; @@ -90,12 +93,12 @@ public void testRetrieveTestPoints_COLLECTIONS() { } @Test - public void testRetrieveTestPoints_COLLECTIONS_WithExtendedPath() { + public void testRetrieveTestPointsForCollectionMetadata() { OpenApi3Parser parser = new OpenApi3Parser(); URL openAppiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - List testPoints = retrieveTestPoints( apiModel, COLLECTIONS, "flurstueck" ); + List testPoints = retrieveTestPointsForCollectionMetadata( apiModel, "flurstueck" ); assertThat( testPoints.size(), is( 1 ) ); @@ -107,12 +110,29 @@ public void testRetrieveTestPoints_COLLECTIONS_WithExtendedPath() { } @Test - public void testRetrieveTestPoints_COLLECTIONS_WithRegEx() { + public void testRetrieveTestPointsForCollection() { OpenApi3Parser parser = new OpenApi3Parser(); URL openAppiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - List testPoints = retrieveTestPoints( apiModel, COLLECTIONS, "flurstueck\\/items\\/\\{.*\\}" ); + List testPoints = retrieveTestPointsForCollection( apiModel, "flurstueck" ); + + assertThat( testPoints.size(), is( 1 ) ); + + TestPoint testPoint = testPoints.get( 0 ); + assertThat( testPoint.createUri(), + is( "http://www.ldproxy.nrw.de/rest/services/kataster/collections/flurstueck/items" ) ); + Map contentMediaTypes = testPoint.getContentMediaTypes(); + assertThat( contentMediaTypes.size(), is( 2 ) ); + } + + @Test + public void testRetrieveTestPointsForFeature() { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openAppiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); + OpenApi3 apiModel = parser.parse( openAppiDocument, true ); + List testPoints = retrieveTestPointsForFeature( apiModel, "flurstueck", "abc" ); assertThat( testPoints.size(), is( 1 ) ); @@ -124,4 +144,68 @@ public void testRetrieveTestPoints_COLLECTIONS_WithRegEx() { assertThat( contentMediaTypes.size(), is( 2 ) ); } + @Test + public void testRetrieveTestPoints_COLLECTIONS_compactAPI() { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openAppiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); + OpenApi3 apiModel = parser.parse( openAppiDocument, true ); + List testPoints = retrieveTestPoints( apiModel, COLLECTIONS ); + + assertThat( testPoints.size(), is( 1 ) ); + + TestPoint testPoint = testPoints.get( 0 ); + assertThat( testPoint.createUri(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections" ) ); + assertThat( testPoint.getContentMediaTypes().size(), is( 4 ) ); + } + + @Test + public void testRetrieveTestPointsForCollectionMetadata_compactAPI() { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openAppiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); + OpenApi3 apiModel = parser.parse( openAppiDocument, true ); + List testPoints = retrieveTestPointsForCollectionMetadata( apiModel, "test__countries" ); + + assertThat( testPoints.size(), is( 1 ) ); + + TestPoint testPoint = testPoints.get( 0 ); + testPoint.addTemplateReplacement( "collectionId", "test__countries" ); + assertThat( testPoint.createUri(), + is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections/test__countries" ) ); + } + + @Test + public void testRetrieveTestPointsForCollection_compactAPI() { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openAppiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); + OpenApi3 apiModel = parser.parse( openAppiDocument, true ); + List testPoints = retrieveTestPointsForCollection( apiModel, "test__countries" ); + + assertThat( testPoints.size(), is( 1 ) ); + + TestPoint testPoint = testPoints.get( 0 ); + testPoint.addTemplateReplacement( "collectionId", "test__countries" ); + assertThat( testPoint.createUri(), + is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections/test__countries/items" ) ); + } + + @Test + public void testRetrieveTestPointsForFeature_compactAPI() { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openAppiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); + OpenApi3 apiModel = parser.parse( openAppiDocument, true ); + List testPoints = retrieveTestPointsForFeature( apiModel, "test__countries", "abc" ); + + assertThat( testPoints.size(), is( 1 ) ); + + TestPoint testPoint = testPoints.get( 0 ); + testPoint.addTemplateReplacement( "collectionId", "test__countries" ); + testPoint.addTemplateReplacement( "featureId", "abc" ); + assertThat( testPoint.createUri(), + is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections/test__countries/items/abc" ) ); + } + } diff --git a/src/test/resources/org/opengis/cite/wfs30/openapi3/openapi_compact-api.json b/src/test/resources/org/opengis/cite/wfs30/openapi3/openapi_compact-api.json new file mode 100644 index 00000000..9b2eb04d --- /dev/null +++ b/src/test/resources/org/opengis/cite/wfs30/openapi3/openapi_compact-api.json @@ -0,0 +1,930 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "WFS 3.0 server", + "contact": { + "name": "Andrea Aime - GeoSolutions", + "email": "andrea.aime@geo-solutions.it" + }, + "version": "2.14-SNAPSHOT" + }, + "externalDocs": { + "description": "WFS specification", + "url": "https://github.com/opengeospatial/WFS_FES" + }, + "servers": [ + { + "url": "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3", + "description": "This server" + } + ], + "tags": [ + { + "name": "Capabilities", + "description": "Essential characteristics of this API including information about the data." + }, + { + "name": "Features", + "description": "Access to data (features)." + } + ], + "paths": { + "/": { + "get": { + "tags": [ + "Capabilities" + ], + "summary": "landing page of this API", + "description": "The landing page provides links to the API definition, the Conformance statements and the metadata about the feature data in this dataset.", + "operationId": "getLandingPage", + "responses": { + "200": { + "description": "links to the API capabilities", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/root" + } + }, + "text/html": { + "schema": { + "type": "string" + } + }, + "application/openapi+json;version=3.0": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/xml": { + "schema": { + "type": "string" + } + }, + "application/x-yaml": { + "schema": { + "$ref": "#/components/schemas/root" + } + } + } + } + } + } + }, + "/conformance": { + "get": { + "tags": [ + "Capabilities" + ], + "summary": "information about standards that this API conforms to", + "description": "list all requirements classes specified in a standard (e.g., WFS 3.0 Part 1: Core) that the server conforms to", + "operationId": "getRequirementsClasses", + "responses": { + "200": { + "description": "the URIs of all requirements classes supported by the server", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/req-classes" + } + }, + "text/xml": { + "schema": { + "type": "string" + } + }, + "application/x-yaml": { + "schema": { + "$ref": "#/components/schemas/req-classes" + } + } + } + }, + "default": { + "description": "An error occured.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/exception" + } + } + } + } + } + } + }, + "/collections": { + "get": { + "tags": [ + "Capabilities" + ], + "summary": "describe the feature collections in the dataset", + "operationId": "describeCollections", + "responses": { + "200": { + "description": "Metdata about the feature collections shared by this API.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/content" + } + }, + "text/html": { + "schema": { + "type": "string" + } + }, + "text/xml": { + "schema": { + "type": "string" + } + }, + "application/x-yaml": { + "schema": { + "$ref": "#/components/schemas/content" + } + } + } + }, + "default": { + "description": "An error occured.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/exception" + } + }, + "text/html": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/collections/{collectionId}": { + "get": { + "tags": [ + "Capabilities" + ], + "summary": "describe the {collectionId} feature collection", + "operationId": "describeCollection", + "parameters": [ + { + "$ref": "#/components/parameters/collectionId" + } + ], + "responses": { + "200": { + "description": "Metadata about the {collectionId} collection shared by this API.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/collectionInfo" + } + }, + "text/html": { + "schema": { + "type": "string" + } + }, + "text/xml": { + "schema": { + "type": "string" + } + }, + "application/x-yaml": { + "schema": { + "$ref": "#/components/schemas/collectionInfo" + } + } + } + }, + "default": { + "description": "An error occured.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/exception" + } + }, + "text/html": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/collections/{collectionId}/items": { + "get": { + "tags": [ + "Features" + ], + "summary": "retrieve features of feature collection {collectionId}", + "description": "Every feature in a dataset belongs to a collection. A dataset may consist of multiple feature collections. A feature collection is often a collection of features of a similar type, based on a common schema.\\\nUse content negotiation to request HTML or GeoJSON.", + "operationId": "getFeatures", + "parameters": [ + { + "$ref": "#/components/parameters/collectionId" + }, + { + "$ref": "#/components/parameters/limit" + }, + { + "$ref": "#/components/parameters/bbox" + }, + { + "$ref": "#/components/parameters/time" + } + ], + "responses": { + "200": { + "description": "Information about the feature collection plus the first features matching the selection parameters.", + "content": { + "application/geo+json": { + "schema": { + "$ref": "#/components/schemas/featureCollectionGeoJSON" + } + }, + "text/html": { + "schema": { + "type": "string" + } + }, + "application/gml+xml; version=3.2": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/xml; subtype=gml/2.1.2": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/xml; subtype=gml/3.2": { + "schema": { + "type": "string" + } + }, + "application/vnd.google-earth.kml+xml": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "application/vnd.google-earth.kml xml": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/xml; subtype=gml/3.1.1": { + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "An error occured.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/exception" + } + }, + "text/html": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/collections/{collectionId}/items/{featureId}": { + "get": { + "tags": [ + "Features" + ], + "summary": "retrieve a feature; use content negotiation to request HTML or GeoJSON", + "operationId": "getFeature", + "parameters": [ + { + "$ref": "#/components/parameters/collectionId" + }, + { + "$ref": "#/components/parameters/featureId" + } + ], + "responses": { + "200": { + "description": "A feature.", + "content": { + "application/geo+json": { + "schema": { + "$ref": "#/components/schemas/featureGeoJSON" + } + }, + "text/html": { + "schema": { + "type": "string" + } + }, + "application/gml+xml; version=3.2": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/xml; subtype=gml/2.1.2": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/xml; subtype=gml/3.2": { + "schema": { + "type": "string" + } + }, + "application/vnd.google-earth.kml+xml": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "application/vnd.google-earth.kml xml": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/xml; subtype=gml/3.1.1": { + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "An error occured.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/exception" + } + }, + "text/html": { + "schema": { + "type": "string" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "exception": { + "required": [ + "code" + ], + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "description": { + "type": "string" + } + } + }, + "root": { + "required": [ + "links" + ], + "type": "object", + "properties": { + "links": { + "type": "array", + "example": [ + { + "href": "http://data.example.org/", + "rel": "self", + "type": "application/json", + "title": "this document" + }, + { + "href": "http://data.example.org/api", + "rel": "service", + "type": "application/openapi+json;version=3.0", + "title": "the API definition" + }, + { + "href": "http://data.example.org/conformance", + "rel": "conformance", + "type": "application/json", + "title": "WFS 3.0 conformance classes implemented by this server" + }, + { + "href": "http://data.example.org/collections", + "rel": "data", + "type": "application/json", + "title": "Metadata about the feature collections" + } + ], + "items": { + "$ref": "#/components/schemas/link" + } + } + } + }, + "req-classes": { + "required": [ + "conformsTo" + ], + "type": "object", + "properties": { + "conformsTo": { + "type": "array", + "example": [ + "http://www.opengis.net/spec/wfs-1/3.0/req/core", + "http://www.opengis.net/spec/wfs-1/3.0/req/oas30", + "http://www.opengis.net/spec/wfs-1/3.0/req/html", + "http://www.opengis.net/spec/wfs-1/3.0/req/geojson" + ], + "items": { + "type": "string" + } + } + } + }, + "link": { + "required": [ + "href" + ], + "type": "object", + "properties": { + "href": { + "type": "string" + }, + "rel": { + "type": "string", + "example": "prev" + }, + "type": { + "type": "string", + "example": "application/geo+json" + }, + "hreflang": { + "type": "string", + "example": "en" + } + } + }, + "content": { + "required": [ + "collections", + "links" + ], + "type": "object", + "properties": { + "links": { + "type": "array", + "example": [ + { + "href": "http://data.example.org/collections.json", + "rel": "self", + "type": "application/json", + "title": "this document" + }, + { + "href": "http://data.example.org/collections.html", + "rel": "alternate", + "type": "text/html", + "title": "this document as HTML" + }, + { + "href": "http://schemas.example.org/1.0/foobar.xsd", + "rel": "describedBy", + "type": "application/xml", + "title": "XML schema for Acme Corporation data" + } + ], + "items": { + "$ref": "#/components/schemas/link" + } + }, + "collections": { + "type": "array", + "items": { + "$ref": "#/components/schemas/collectionInfo" + } + } + } + }, + "collectionInfo": { + "required": [ + "links", + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "identifier of the collection used, for example, in URIs", + "example": "buildings" + }, + "title": { + "type": "string", + "description": "human readable title of the collection", + "example": "Buildings" + }, + "description": { + "type": "string", + "description": "a description of the features in the collection", + "example": "Buildings in the city of Bonn." + }, + "links": { + "type": "array", + "example": [ + { + "href": "http://data.example.org/collections/buildings/items", + "rel": "item", + "type": "application/geo+json", + "title": "Buildings" + }, + { + "href": "http://example.org/concepts/building.html", + "rel": "describedBy", + "type": "text/html", + "title": "Feature catalogue for buildings" + } + ], + "items": { + "$ref": "#/components/schemas/link" + } + }, + "extent": { + "$ref": "#/components/schemas/extent" + }, + "crs": { + "type": "array", + "description": "The coordinate reference systems in which geometries may be retrieved. Coordinate reference systems are identified by a URI. The first coordinate reference system is the coordinate reference system that is used by default. This is always \"http://www.opengis.net/def/crs/OGC/1.3/CRS84\", i.e. WGS84 longitude/latitude.", + "items": { + "type": "string" + }, + "default": [ + "http://www.opengis.net/def/crs/OGC/1.3/CRS84" + ] + } + } + }, + "extent": { + "type": "object", + "properties": { + "crs": { + "type": "string", + "description": "Coordinate reference system of the coordinates in the spatial extent (property `spatial`). In the Core, only WGS84 longitude/latitude is supported. Extensions may support additional coordinate reference systems.", + "enum": [ + "http://www.opengis.net/def/crs/OGC/1.3/CRS84" + ], + "default": "http://www.opengis.net/def/crs/OGC/1.3/CRS84" + }, + "spatial": { + "maxItems": 6, + "minItems": 4, + "type": "array", + "description": "West, north, east, south edges of the spatial extent. The minimum and maximum values apply to the coordinate reference system WGS84 longitude/latitude that is supported in the Core. If, for example, a projected coordinate reference system is used, the minimum and maximum values need to be adjusted.", + "example": [ + -180, + -90, + 180, + 90 + ], + "items": { + "type": "number" + } + }, + "trs": { + "type": "string", + "description": "Temporal reference system of the coordinates in the temporal extent (property `temporal`). In the Core, only the Gregorian calendar is supported. Extensions may support additional temporal reference systems.", + "enum": [ + "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian" + ], + "default": "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian" + }, + "temporal": { + "maxItems": 2, + "minItems": 2, + "type": "array", + "description": "Begin and end times of the temporal extent.", + "example": [ + "2011-11-11T12:22:11Z", + "2012-11-24T12:32:43Z" + ], + "items": { + "type": "string", + "format": "dateTime" + } + } + } + }, + "featureCollectionGeoJSON": { + "required": [ + "features", + "type" + ], + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "FeatureCollection" + ] + }, + "features": { + "type": "array", + "items": { + "$ref": "#/components/schemas/featureGeoJSON" + } + }, + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + } + }, + "timeStamp": { + "type": "string", + "format": "dateTime" + }, + "numberMatched": { + "minimum": 0, + "type": "integer" + }, + "numberReturned": { + "minimum": 0, + "type": "integer" + } + } + }, + "featureGeoJSON": { + "required": [ + "geometry", + "properties", + "type" + ], + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "Feature" + ] + }, + "geometry": { + "$ref": "#/components/schemas/geometryGeoJSON" + }, + "properties": { + "type": "object", + "nullable": true + }, + "id": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } + } + }, + "geometryGeoJSON": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "Point", + "MultiPoint", + "LineString", + "MultiLineString", + "Polygon", + "MultiPolygon", + "GeometryCollection" + ] + } + } + } + }, + "parameters": { + "limit": { + "name": "limit", + "in": "query", + "description": "The optional limit parameter limits the number of items that are\npresented in the response document.\n\nOnly items are counted that are on the first level of the collection in\nthe response document. Nested objects contained within the explicitly\nrequested items shall not be counted.\n", + "required": false, + "style": "form", + "explode": false, + "schema": { + "maximum": 1000000, + "minimum": 1, + "type": "integer", + "default": 1000000 + } + }, + "bbox": { + "name": "bbox", + "in": "query", + "description": "Only features that have a geometry that intersects the bounding box are selected. The bounding box is provided as four or six numbers, depending on whether the coordinate reference system includes a vertical axis (elevation or depth):\n* Lower left corner, coordinate axis 1 * Lower left corner, coordinate axis 2 * Lower left corner, coordinate axis 3 (optional) * Upper right corner, coordinate axis 1 * Upper right corner, coordinate axis 2 * Upper right corner, coordinate axis 3 (optional)\nThe coordinate reference system of the values is WGS84 longitude/latitude (http://www.opengis.net/def/crs/OGC/1.3/CRS84) unless a different coordinate reference system is specified in the parameter `bbox-crs`.\nFor WGS84 longitude/latitude the values are in most cases the sequence of minimum longitude, minimum latitude, maximum longitude and maximum latitude. However, in cases where the box spans the antimeridian the first value (west-most box edge) is larger than the third value (east-most box edge).\nIf a feature has multiple spatial geometry properties, it is the decision of the server whether only a single spatial geometry property is used to determine the extent or all relevant geometries.\n", + "required": false, + "style": "form", + "explode": false, + "schema": { + "maxItems": 6, + "minItems": 4, + "type": "array", + "items": { + "type": "number" + } + } + }, + "time": { + "name": "time", + "in": "query", + "description": "Either a date-time or a period string that adheres to RFC 3339. Examples:\n* A date-time: \"2018-02-12T23:20:50Z\" * A period: \"2018-02-12T00:00:00Z/2018-03-18T12:31:12Z\" or \"2018-02-12T00:00:00Z/P1M6DT12H31M12S\"\nOnly features that have a temporal property that intersects the value of `time` are selected.\nIf a feature has multiple temporal properties, it is the decision of the server whether only a single temporal property is used to determine the extent or all relevant temporal properties.", + "required": false, + "style": "form", + "explode": false, + "schema": { + "type": "string" + } + }, + "collectionId": { + "name": "collectionId", + "in": "path", + "description": "Identifier (name) of a specific collection", + "required": true, + "schema": { + "type": "string", + "enum": [ + "eumetsat__ne_10m_coastline", + "eumetsat__ne_boundary_lines_land", + "eumetsat__wind_ascat", + "eumetsat__wind_ascat_reduced", + "eumetsat__wind_ascat_thinned", + "landsat8__B3_index", + "geosolutions__LANDSAT8__B1", + "geosolutions__SENTINEL1_V2", + "geosolutions__SENTINEL1__MOSAIC_B1", + "geosolutions__SENTINEL1__vv", + "geosolutions__SENTINEL2_V2", + "geosolutions__SENTINEL2__B04", + "geosolutions__SENTINEL2__MOSAIC_B01", + "geosolutions__product", + "geosolutions__smb_simple_points", + "geosolutions__testing", + "zaatari__AgricultureSrf", + "zaatari__CultureSrf", + "zaatari__FacilitySrf", + "zaatari__HydrographySrf", + "zaatari__InformationPnt", + "zaatari__RecreationSrf", + "zaatari__SettlementSrf", + "zaatari__StructurePnt", + "zaatari__StructureSrf", + "zaatari__TransportationGroundCrv", + "zaatari__TransportationGroundSrf", + "zaatari__UtilityInfrastructureSrf", + "zaatari__o2s_A", + "zaatari__o2s_L", + "zaatari__osm_points", + "zaatari__zaatari_worldview_timeseries_index", + "geoedge__administrative_subdivision_s", + "geoedge__anchorage_p", + "geoedge__building_p", + "geoedge__built_up_area_p", + "geoedge__cemetery_s", + "geoedge__code_list_t", + "geoedge__conservation_area_s", + "geoedge__dam_c", + "geoedge__dam_s", + "geoedge__dataset_s", + "geoedge__dataset_t", + "geoedge__entity_collection_metadata_s", + "geoedge__entity_collection_metadata_t", + "geoedge__foreshore_s", + "geoedge__forest_s", + "geoedge__gauging_station_p", + "geoedge__heliport_p", + "geoedge__inland_waterbody_s", + "geoedge__land_aerodrome_p", + "geoedge__land_water_boundary_c", + "geoedge__maritime_limit_c", + "geoedge__military_installation_s", + "geoedge__navigable_canal_s", + "geoedge__park_s", + "geoedge__pipeline_c", + "geoedge__port_p", + "geoedge__reef_c", + "geoedge__restriction_info_t", + "geoedge__river_c", + "geoedge__river_s", + "geoedge__road_c", + "geoedge__rock_formation_p", + "geoedge__runway_s", + "geoedge__soil_surface_region_s", + "geoedge__trail_c", + "geoedge__tunnel_c", + "geoedge__water_aerodrome_p", + "geoedge__water_well_p", + "test__countries", + "test__eo_collection", + "test__eo_product", + "test__granule", + "sf__AggregateGeoFeature", + "sf__EntitéGénérique", + "sf__PrimitiveGeoFeature", + "daraa__AgriculturePnt", + "daraa__AgricultureSrf", + "daraa__Cultivated_2011", + "daraa__Cultivated_2012", + "daraa__Cultivated_2013", + "daraa__CulturePnt", + "daraa__CultureSrf", + "daraa__FacilityPnt", + "daraa__FacilitySrf", + "daraa__FieldBoundary_2011", + "daraa__Health_2011", + "daraa__Health_2012", + "daraa__Health_2013", + "daraa__HydrographyCrv", + "daraa__HydrographySrf", + "daraa__InformationPnt", + "daraa__Inventory_2011", + "daraa__Inventory_2012", + "daraa__Inventory_2013", + "daraa__MilitarySrf", + "daraa__RecreationPnt", + "daraa__RecreationSrf", + "daraa__SettlementPnt", + "daraa__SettlementSrf", + "daraa__StructureCrv", + "daraa__StructurePnt", + "daraa__StructureSrf", + "daraa__TransportationGroundCrv", + "daraa__TransportationGroundPnt", + "daraa__TransportationGroundSrf", + "daraa__UtilityInfrastructureCrv", + "daraa__UtilityInfrastructurePnt", + "daraa__VegetationSrf", + "daraa__daraa_landsat8_timeseries_index", + "daraa__daraa_worldview_timeseries_index", + "daraa__o2s_A", + "daraa__o2s_L", + "daraa__o2s_P", + "osm__public_gns_iceland_version_log", + "osm__public_osm_administrative_version_log", + "osm__public_osm_protected_area_version_log" + ] + } + }, + "featureId": { + "name": "featureId", + "in": "path", + "description": "Local identifier of a specific feature", + "required": true, + "schema": { + "type": "string" + } + } + } + } +} \ No newline at end of file From c44cb06663cb2895599d740b2792392d1d9e0ec3 Mon Sep 17 00:00:00 2001 From: Lyn Elisa Goltz Date: Tue, 14 Aug 2018 14:00:03 +0200 Subject: [PATCH 3/4] #28 - added UriBuilder to create test urls with template replacements --- .../FeatureCollectionsMetadataOperation.java | 14 +-- .../conformance/ConformanceOperation.java | 3 +- .../cite/wfs30/openapi3/OpenApiUtils.java | 9 +- .../cite/wfs30/openapi3/TestPoint.java | 84 ++++++++---------- .../cite/wfs30/openapi3/UriBuilder.java | 88 +++++++++++++++++++ ...FeatureCollectionsMetadataOperationIT.java | 7 +- .../conformance/ConformanceOperationIT.java | 4 +- .../cite/wfs30/openapi3/OpenApiUtilsTest.java | 64 ++++++++------ .../cite/wfs30/openapi3/UrlBuilderTest.java | 75 ++++++++++++++++ 9 files changed, 254 insertions(+), 94 deletions(-) create mode 100644 src/main/java/org/opengis/cite/wfs30/openapi3/UriBuilder.java create mode 100644 src/test/java/org/opengis/cite/wfs30/openapi3/UrlBuilderTest.java diff --git a/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java b/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java index 0949d241..c623fc57 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java @@ -23,6 +23,7 @@ import org.opengis.cite.wfs30.CommonFixture; import org.opengis.cite.wfs30.SuiteAttribute; import org.opengis.cite.wfs30.openapi3.TestPoint; +import org.opengis.cite.wfs30.openapi3.UriBuilder; import org.testng.ITestContext; import org.testng.SkipException; import org.testng.annotations.AfterClass; @@ -107,7 +108,7 @@ public void storeCollectionsInTestContext( ITestContext testContext ) { */ @Test(description = "Implements A.4.4.4. Validate the Feature Collections Metadata Operation (Requirement 9, 10)", groups = "collections", dataProvider = "collectionsUris", dependsOnGroups = "apidefinition") public void validateFeatureCollectionsMetadataOperation( TestPoint testPoint ) { - String testPointUri = testPoint.createUri(); + String testPointUri = new UriBuilder( testPoint ).buildUrl(); Response response = init().baseUri( testPointUri ).accept( JSON ).when().request( GET ); response.then().statusCode( 200 ); this.testPointAndResponses.put( testPoint, response ); @@ -280,8 +281,9 @@ public void validateTheFeatureCollectionMetadataOperationAndResponse( TestPoint throw new SkipException( "Could not find collection with name " + collectionName + " in the OpenAPI document" ); - TestPoint testPointCollectionMetadata = testPointsForNamedCollection.get(0); - Response response = validateTheFeatureCollectionMetadataOperationAndResponse(testPointCollectionMetadata, collectionName); + TestPoint testPointCollectionMetadata = testPointsForNamedCollection.get( 0 ); + Response response = validateTheFeatureCollectionMetadataOperationAndResponse( testPointCollectionMetadata, + collectionName ); validateFeatureCollectionMetadataOperationResponse( response, collection ); } @@ -310,9 +312,9 @@ public void validateTheFeatureCollectionMetadataOperationAndResponse( TestPoint * to test, never null * @param collectionName */ - private Response validateTheFeatureCollectionMetadataOperationAndResponse(TestPoint testPoint, String collectionName) { - String testPointUri = testPoint.createUri(); - // TODO: add collectionName as required + private Response validateTheFeatureCollectionMetadataOperationAndResponse( TestPoint testPoint, + String collectionName ) { + String testPointUri = new UriBuilder( testPoint ).collectionName( collectionName ).buildUrl(); Response response = init().baseUri( testPointUri ).accept( JSON ).when().request( GET ); response.then().statusCode( 200 ); return response; diff --git a/src/main/java/org/opengis/cite/wfs30/conformance/ConformanceOperation.java b/src/main/java/org/opengis/cite/wfs30/conformance/ConformanceOperation.java index 847cc5b7..322d2c1d 100644 --- a/src/main/java/org/opengis/cite/wfs30/conformance/ConformanceOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/conformance/ConformanceOperation.java @@ -12,6 +12,7 @@ import org.opengis.cite.wfs30.CommonFixture; import org.opengis.cite.wfs30.openapi3.TestPoint; +import org.opengis.cite.wfs30.openapi3.UriBuilder; import org.testng.ITestContext; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -63,7 +64,7 @@ public void validateConformanceOperationAndResponse( TestPoint testPoint ) { * d) References: Requirement 5 */ private Response validateConformanceOperation( TestPoint testPoint ) { - String testPointUri = testPoint.createUri(); + String testPointUri = new UriBuilder( testPoint ).buildUrl(); return init().baseUri( testPointUri ).accept( JSON ).when().request( GET ); } diff --git a/src/main/java/org/opengis/cite/wfs30/openapi3/OpenApiUtils.java b/src/main/java/org/opengis/cite/wfs30/openapi3/OpenApiUtils.java index d9a0051a..90426255 100644 --- a/src/main/java/org/opengis/cite/wfs30/openapi3/OpenApiUtils.java +++ b/src/main/java/org/opengis/cite/wfs30/openapi3/OpenApiUtils.java @@ -295,23 +295,24 @@ private static List processServerObjects( List pat private static void processServerObject( List uris, PathItemAndServer pathItemAndServer ) { String pathString = pathItemAndServer.pathItemObject.getPathString(); - UriTemplate uriTemplate = new UriTemplate( pathItemAndServer.serverUrl + pathString ); Response response = pathItemAndServer.operationObject.getResponse( "200" ); Map contentMediaTypes = response.getContentMediaTypes(); + UriTemplate uriTemplate = new UriTemplate( pathItemAndServer.serverUrl + pathString ); if ( uriTemplate.getNumberOfTemplateVariables() == 0 ) { - TestPoint testPoint = new TestPoint( uriTemplate, contentMediaTypes ); + TestPoint testPoint = new TestPoint( pathItemAndServer.serverUrl, pathString, contentMediaTypes ); uris.add( testPoint ); } else { List> templateReplacements = collectTemplateReplacements( pathItemAndServer, uriTemplate ); if ( templateReplacements.isEmpty() ) { - TestPoint testPoint = new TestPoint( uriTemplate, contentMediaTypes ); + TestPoint testPoint = new TestPoint( pathItemAndServer.serverUrl, pathString, contentMediaTypes ); uris.add( testPoint ); } else { for ( Map templateReplacement : templateReplacements ) { - TestPoint testPoint = new TestPoint( uriTemplate, templateReplacement, contentMediaTypes ); + TestPoint testPoint = new TestPoint( pathItemAndServer.serverUrl, pathString, templateReplacement, + contentMediaTypes ); uris.add( testPoint ); } } diff --git a/src/main/java/org/opengis/cite/wfs30/openapi3/TestPoint.java b/src/main/java/org/opengis/cite/wfs30/openapi3/TestPoint.java index 29b343af..69d34d15 100644 --- a/src/main/java/org/opengis/cite/wfs30/openapi3/TestPoint.java +++ b/src/main/java/org/opengis/cite/wfs30/openapi3/TestPoint.java @@ -1,12 +1,11 @@ package org.opengis.cite.wfs30.openapi3; -import java.util.HashMap; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import com.reprezen.kaizen.oasparser.model3.MediaType; -import com.sun.jersey.api.uri.UriTemplate; /** * Encapsulates a Test Point with the UriTemplate and predefined replacements. @@ -15,69 +14,70 @@ */ public class TestPoint { - private UriTemplate uriTemplate; + private final String serverUrl; - private Map templateReplacement; + private final String path; + + private Map predefinedTemplateReplacement; private List requirementClasses; private Map contentMediaTypes; /** - * Instantiates a TestPoint with UriTemplate but without defined replacements. + * Instantiates a TestPoint with UriTemplate but without predefined replacements. * - * @param uriTemplate - * never null + * @param serverUrl + * the serverUrl, never null + * @param path + * the path never, null * @param contentMediaTypes * the content media types for the GET operation with response "200", may be null */ - public TestPoint( UriTemplate uriTemplate, Map contentMediaTypes ) { - this( uriTemplate, null, contentMediaTypes ); + public TestPoint( String serverUrl, String path, Map contentMediaTypes ) { + this( serverUrl, path, Collections.emptyMap(), contentMediaTypes ); } /** * Instantiates a TestPoint with UriTemplate and predefined replacements. * - * @param uriTemplate - * never null - * @param templateReplacement - * may be null + * @param serverUrl + * the serverUrl, never null + * @param path + * the path, never null + * @param predefinedTemplateReplacement + * a list of predefined replacements never null * @param contentMediaTypes * the content media types for the GET operation with response "200", may be null */ - public TestPoint( UriTemplate uriTemplate, Map templateReplacement, + public TestPoint( String serverUrl, String path, Map predefinedTemplateReplacement, Map contentMediaTypes ) { - this.uriTemplate = uriTemplate; - this.templateReplacement = templateReplacement; + this.serverUrl = serverUrl; + this.path = path; + this.predefinedTemplateReplacement = Collections.unmodifiableMap( predefinedTemplateReplacement ); this.contentMediaTypes = contentMediaTypes; } /** - * @return the UriTemplate, never null + * + * @return the serverUrl never null */ - public UriTemplate getUriTemplate() { - return uriTemplate; + public String getServerUrl() { + return serverUrl; } /** - * @return predefined replacements, may be null + * @return the path never, null */ - public Map getTemplateReplacement() { - return templateReplacement; + public String getPath() { + return path; } /** - * Adds a new template replacement - * - * @param key - * the key of the template, never null - * @param value - * the value of the template, never null + * @return an unmodifiable mao with predefined replacements, may be empty but never null */ - public void addTemplateReplacement( String key, String value ) { - if ( this.templateReplacement == null ) - this.templateReplacement = new HashMap<>(); - this.templateReplacement.put( key, value ); + public Map getPredefinedTemplateReplacement() { + return predefinedTemplateReplacement; } /** @@ -105,20 +105,9 @@ public Map getContentMediaTypes() { return contentMediaTypes; } - /** - * Creates an URI from the template with the replacement. - * - * @return the URI created from the template, never null - */ - public String createUri() { - if ( templateReplacement != null ) - return uriTemplate.createURI( templateReplacement ); - return uriTemplate.createURI(); - } - @Override public String toString() { - return "Pattern: " + uriTemplate.getPattern() + ", Replacements: " + templateReplacement; + return "Server URL: " + serverUrl + " , Path: " + path + ", Replacements: " + predefinedTemplateReplacement; } @Override @@ -128,15 +117,16 @@ public boolean equals( Object o ) { if ( o == null || getClass() != o.getClass() ) return false; TestPoint testPoint = (TestPoint) o; - return Objects.equals( uriTemplate, testPoint.uriTemplate ) - && Objects.equals( templateReplacement, testPoint.templateReplacement ) + return Objects.equals( serverUrl, testPoint.serverUrl ) + && Objects.equals( path, testPoint.predefinedTemplateReplacement ) + && Objects.equals( predefinedTemplateReplacement, testPoint.path ) && Objects.equals( requirementClasses, testPoint.requirementClasses ) && Objects.equals( contentMediaTypes, testPoint.contentMediaTypes ); } @Override public int hashCode() { - return Objects.hash( uriTemplate, templateReplacement, requirementClasses, contentMediaTypes ); + return Objects.hash( serverUrl, path, predefinedTemplateReplacement, requirementClasses, contentMediaTypes ); } } diff --git a/src/main/java/org/opengis/cite/wfs30/openapi3/UriBuilder.java b/src/main/java/org/opengis/cite/wfs30/openapi3/UriBuilder.java new file mode 100644 index 00000000..94614c6d --- /dev/null +++ b/src/main/java/org/opengis/cite/wfs30/openapi3/UriBuilder.java @@ -0,0 +1,88 @@ +package org.opengis.cite.wfs30.openapi3; + +import java.util.HashMap; +import java.util.Map; + +import com.sun.jersey.api.uri.UriTemplate; +import com.sun.jersey.api.uri.UriTemplateParser; + +/** + * Builds a URL out of a TestPoint. + * + * @author Lyn Goltz + */ +public class UriBuilder { + + private final TestPoint testPoint; + + private final Map templateReplacements = new HashMap<>(); + + /** + * @param testPoint + * never null + */ + public UriBuilder( TestPoint testPoint ) { + this.testPoint = testPoint; + this.templateReplacements.putAll( testPoint.getPredefinedTemplateReplacement() ); + } + + /** + * Adds the collectionName to the URI + * + * @param collectionName + * never null + * @return this UrlBuilder + */ + public UriBuilder collectionName( String collectionName ) { + String templateName = retrieveCollectionNameTemplateName(); + addTemplateReplacement( collectionName, templateName ); + return this; + } + + /** + * Adds the featureId to the URI + * + * @param featureId + * never null + * @return this UrlBuilder + */ + public UriBuilder featureId( String featureId ) { + String templateName = retrieveFeatureIdTemplateName(); + addTemplateReplacement( featureId, templateName ); + return this; + } + + /** + * @return this URI, never null + */ + public String buildUrl() { + UriTemplate uriTemplate = new UriTemplate( testPoint.getServerUrl() + testPoint.getPath() ); + return uriTemplate.createURI( templateReplacements ); + } + + private void addTemplateReplacement( String collectionName, String templateName ) { + if ( templateName != null ) + templateReplacements.put( templateName, collectionName ); + } + + private String retrieveCollectionNameTemplateName() { + String path = testPoint.getPath(); + UriTemplateParser uriTemplateParser = new UriTemplateParser( path ); + for ( String templateName : uriTemplateParser.getNames() ) { + if ( path.startsWith( "/collections/{" + templateName + "}" ) ) + return templateName; + } + return null; + } + + private String retrieveFeatureIdTemplateName() { + String path = testPoint.getPath(); + UriTemplateParser uriTemplateParser = new UriTemplateParser( path ); + for ( String templateName : uriTemplateParser.getNames() ) { + if ( path.endsWith( "items/{" + templateName + "}" ) ) + return templateName; + } + return null; + } + +} \ No newline at end of file diff --git a/src/test/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperationIT.java b/src/test/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperationIT.java index 469589cf..c8808555 100644 --- a/src/test/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperationIT.java +++ b/src/test/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperationIT.java @@ -19,7 +19,6 @@ import com.reprezen.kaizen.oasparser.OpenApi3Parser; import com.reprezen.kaizen.oasparser.model3.MediaType; import com.reprezen.kaizen.oasparser.model3.OpenApi3; -import com.sun.jersey.api.uri.UriTemplate; /** * @author Lyn Goltz @@ -51,8 +50,7 @@ public void testValidateFeatureCollectionsMetadataOperationResponse() { FeatureCollectionsMetadataOperation featureCollectionsMetadataOperation = new FeatureCollectionsMetadataOperation(); featureCollectionsMetadataOperation.initCommonFixture( testContext ); featureCollectionsMetadataOperation.openApiDocument( testContext ); - UriTemplate conformanceUri = new UriTemplate( "https://www.ldproxy.nrw.de/kataster/collections" ); - TestPoint testPoint = new TestPoint( conformanceUri, mediaTypes() ); + TestPoint testPoint = new TestPoint( "https://www.ldproxy.nrw.de/kataster", "/collections", mediaTypes() ); featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperation( testPoint ); featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperationResponse_Links( testPoint ); featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperationResponse_Collections( testPoint ); @@ -63,7 +61,8 @@ public void testValidateFeatureCollectionsMetadataOperationResponse() { Map collection = (Map) object[1]; featureCollectionsMetadataOperation.validateCollectionsMetadataDocument_Links( tp, collection ); featureCollectionsMetadataOperation.validateCollectionsMetadataDocument_Extent( tp, collection ); - featureCollectionsMetadataOperation.validateTheFeatureCollectionMetadataOperationAndResponse( tp, collection ); + featureCollectionsMetadataOperation.validateTheFeatureCollectionMetadataOperationAndResponse( tp, + collection ); } } diff --git a/src/test/java/org/opengis/cite/wfs30/conformance/ConformanceOperationIT.java b/src/test/java/org/opengis/cite/wfs30/conformance/ConformanceOperationIT.java index 2e38170b..5cb34dc3 100644 --- a/src/test/java/org/opengis/cite/wfs30/conformance/ConformanceOperationIT.java +++ b/src/test/java/org/opengis/cite/wfs30/conformance/ConformanceOperationIT.java @@ -16,7 +16,6 @@ import org.testng.ITestContext; import com.reprezen.kaizen.oasparser.model3.MediaType; -import com.sun.jersey.api.uri.UriTemplate; /** * @author Lyn Goltz @@ -42,8 +41,7 @@ public static void initTestFixture() public void testApiDefinition() { ConformanceOperation conformanceOperation = new ConformanceOperation(); conformanceOperation.initCommonFixture( testContext ); - UriTemplate conformanceUri = new UriTemplate( "https://www.ldproxy.nrw.de/kataster/conformance" ); - TestPoint testPoint = new TestPoint( conformanceUri, mediaTypes() ); + TestPoint testPoint = new TestPoint( "https://www.ldproxy.nrw.de/kataster", "/conformance", mediaTypes() ); conformanceOperation.validateConformanceOperationAndResponse( testPoint ); } diff --git a/src/test/java/org/opengis/cite/wfs30/openapi3/OpenApiUtilsTest.java b/src/test/java/org/opengis/cite/wfs30/openapi3/OpenApiUtilsTest.java index abcfe681..5f4bf2eb 100644 --- a/src/test/java/org/opengis/cite/wfs30/openapi3/OpenApiUtilsTest.java +++ b/src/test/java/org/opengis/cite/wfs30/openapi3/OpenApiUtilsTest.java @@ -49,23 +49,23 @@ public void testRetrieveTestPoints_moreComplex() { assertThat( testPoints.size(), is( 4 ) ); TestPoint testPointWIthIndex = testPoints.get( 0 ); - assertThat( testPointWIthIndex.getTemplateReplacement().size(), is( 1 ) ); - assertThat( testPointWIthIndex.getTemplateReplacement().get( "index" ), is( "10" ) ); + assertThat( testPointWIthIndex.getPredefinedTemplateReplacement().size(), is( 1 ) ); + assertThat( testPointWIthIndex.getPredefinedTemplateReplacement().get( "index" ), is( "10" ) ); TestPoint testPointWIthIndexAndEnum1 = testPoints.get( 1 ); - assertThat( testPointWIthIndexAndEnum1.getTemplateReplacement().size(), is( 2 ) ); - assertThat( testPointWIthIndexAndEnum1.getTemplateReplacement().get( "index" ), is( "10" ) ); - assertThat( testPointWIthIndexAndEnum1.getTemplateReplacement().get( "enum" ), is( "eins" ) ); + assertThat( testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().size(), is( 2 ) ); + assertThat( testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().get( "index" ), is( "10" ) ); + assertThat( testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().get( "enum" ), is( "eins" ) ); TestPoint testPointWIthIndexAndEnum2 = testPoints.get( 2 ); - assertThat( testPointWIthIndexAndEnum2.getTemplateReplacement().size(), is( 2 ) ); - assertThat( testPointWIthIndexAndEnum2.getTemplateReplacement().get( "index" ), is( "10" ) ); - assertThat( testPointWIthIndexAndEnum2.getTemplateReplacement().get( "enum" ), is( "zwei" ) ); + assertThat( testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().size(), is( 2 ) ); + assertThat( testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().get( "index" ), is( "10" ) ); + assertThat( testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().get( "enum" ), is( "zwei" ) ); TestPoint testPointWIthIndexAndEnum3 = testPoints.get( 3 ); - assertThat( testPointWIthIndexAndEnum3.getTemplateReplacement().size(), is( 2 ) ); - assertThat( testPointWIthIndexAndEnum3.getTemplateReplacement().get( "index" ), is( "10" ) ); - assertThat( testPointWIthIndexAndEnum3.getTemplateReplacement().get( "enum" ), is( "drei" ) ); + assertThat( testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().size(), is( 2 ) ); + assertThat( testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().get( "index" ), is( "10" ) ); + assertThat( testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().get( "enum" ), is( "drei" ) ); } @Test @@ -103,8 +103,11 @@ public void testRetrieveTestPointsForCollectionMetadata() { assertThat( testPoints.size(), is( 1 ) ); TestPoint testPoint = testPoints.get( 0 ); - assertThat( testPoint.createUri(), - is( "http://www.ldproxy.nrw.de/rest/services/kataster/collections/flurstueck" ) ); + // assertThat( testPoint.createUri(), + // is( "http://www.ldproxy.nrw.de/rest/services/kataster/collections/flurstueck" ) ); + assertThat( testPoint.getServerUrl(), is( "http://www.ldproxy.nrw.de/rest/services/kataster" ) ); + assertThat( testPoint.getPath(), is( "/collections/flurstueck" ) ); + Map contentMediaTypes = testPoint.getContentMediaTypes(); assertThat( contentMediaTypes.size(), is( 2 ) ); } @@ -120,8 +123,11 @@ public void testRetrieveTestPointsForCollection() { assertThat( testPoints.size(), is( 1 ) ); TestPoint testPoint = testPoints.get( 0 ); - assertThat( testPoint.createUri(), - is( "http://www.ldproxy.nrw.de/rest/services/kataster/collections/flurstueck/items" ) ); + // assertThat( testPoint.createUri(), + // is( "http://www.ldproxy.nrw.de/rest/services/kataster/collections/flurstueck/items" ) ); + assertThat( testPoint.getServerUrl(), is( "http://www.ldproxy.nrw.de/rest/services/kataster" ) ); + assertThat( testPoint.getPath(), is( "/collections/flurstueck/items" ) ); + Map contentMediaTypes = testPoint.getContentMediaTypes(); assertThat( contentMediaTypes.size(), is( 2 ) ); } @@ -137,9 +143,8 @@ public void testRetrieveTestPointsForFeature() { assertThat( testPoints.size(), is( 1 ) ); TestPoint testPoint = testPoints.get( 0 ); - testPoint.addTemplateReplacement( "featureId", "abc" ); - assertThat( testPoint.createUri(), - is( "http://www.ldproxy.nrw.de/rest/services/kataster/collections/flurstueck/items/abc" ) ); + assertThat( testPoint.getServerUrl(), is( "http://www.ldproxy.nrw.de/rest/services/kataster" ) ); + assertThat( testPoint.getPath(), is( "/collections/flurstueck/items/{featureId}" ) ); Map contentMediaTypes = testPoint.getContentMediaTypes(); assertThat( contentMediaTypes.size(), is( 2 ) ); } @@ -155,7 +160,11 @@ public void testRetrieveTestPoints_COLLECTIONS_compactAPI() { assertThat( testPoints.size(), is( 1 ) ); TestPoint testPoint = testPoints.get( 0 ); - assertThat( testPoint.createUri(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections" ) ); + // assertThat( testPoint.createUri(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections" ) ); + + assertThat( testPoint.getServerUrl(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3" ) ); + assertThat( testPoint.getPath(), is( "/collections" ) ); + assertThat( testPoint.getContentMediaTypes().size(), is( 4 ) ); } @@ -170,9 +179,9 @@ public void testRetrieveTestPointsForCollectionMetadata_compactAPI() { assertThat( testPoints.size(), is( 1 ) ); TestPoint testPoint = testPoints.get( 0 ); - testPoint.addTemplateReplacement( "collectionId", "test__countries" ); - assertThat( testPoint.createUri(), - is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections/test__countries" ) ); + + assertThat( testPoint.getServerUrl(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3" ) ); + assertThat( testPoint.getPath(), is( "/collections/{collectionId}" ) ); } @Test @@ -186,9 +195,8 @@ public void testRetrieveTestPointsForCollection_compactAPI() { assertThat( testPoints.size(), is( 1 ) ); TestPoint testPoint = testPoints.get( 0 ); - testPoint.addTemplateReplacement( "collectionId", "test__countries" ); - assertThat( testPoint.createUri(), - is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections/test__countries/items" ) ); + assertThat( testPoint.getServerUrl(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3" ) ); + assertThat( testPoint.getPath(), is( "/collections/{collectionId}/items" ) ); } @Test @@ -202,10 +210,8 @@ public void testRetrieveTestPointsForFeature_compactAPI() { assertThat( testPoints.size(), is( 1 ) ); TestPoint testPoint = testPoints.get( 0 ); - testPoint.addTemplateReplacement( "collectionId", "test__countries" ); - testPoint.addTemplateReplacement( "featureId", "abc" ); - assertThat( testPoint.createUri(), - is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections/test__countries/items/abc" ) ); + assertThat( testPoint.getServerUrl(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3" ) ); + assertThat( testPoint.getPath(), is( "/collections/{collectionId}/items/{featureId}" ) ); } } diff --git a/src/test/java/org/opengis/cite/wfs30/openapi3/UrlBuilderTest.java b/src/test/java/org/opengis/cite/wfs30/openapi3/UrlBuilderTest.java new file mode 100644 index 00000000..c5010180 --- /dev/null +++ b/src/test/java/org/opengis/cite/wfs30/openapi3/UrlBuilderTest.java @@ -0,0 +1,75 @@ +package org.opengis.cite.wfs30.openapi3; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.Collections; + +import org.junit.Test; + +/** + * @author Lyn Goltz + */ +public class UrlBuilderTest { + + @Test + public void testBuildUrl_collectionMetadata_withTemplate() { + TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/{name}", Collections.emptyMap() ); + String url = new UriBuilder( tp ).collectionName( "water" ).buildUrl(); + + assertThat( url, is( "http://localhost:8080/service/collections/water" ) ); + } + + @Test + public void testBuildUrl_collectionMetadata_withoutTemplate() { + TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/forest", Collections.emptyMap() ); + String url = new UriBuilder( tp ).collectionName( "forest" ).buildUrl(); + + assertThat( url, is( "http://localhost:8080/service/collections/forest" ) ); + } + + @Test + public void testBuildUrl_collection_withTemplate() { + TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/{name}/items", + Collections.emptyMap() ); + String url = new UriBuilder( tp ).collectionName( "water" ).buildUrl(); + + assertThat( url, is( "http://localhost:8080/service/collections/water/items" ) ); + } + + @Test + public void testBuildUrl_collection_withoutTemplate() { + TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/forest/items", + Collections.emptyMap() ); + String url = new UriBuilder( tp ).collectionName( "forest" ).buildUrl(); + + assertThat( url, is( "http://localhost:8080/service/collections/forest/items" ) ); + } + + @Test + public void testBuildUrl_feature_withFeatureIdTemplate() { + TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/forest/items/{featureId}", + Collections.emptyMap() ); + String url = new UriBuilder( tp ).collectionName( "forest" ).featureId( "1" ).buildUrl(); + + assertThat( url, is( "http://localhost:8080/service/collections/forest/items/1" ) ); + } + + @Test + public void testBuildUrl_feature_withCollectionNameAndFeatureIdTemplate() { + TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/{name}/items/{featureId}", + Collections.emptyMap() ); + String url = new UriBuilder( tp ).collectionName( "water" ).featureId( "2" ).buildUrl(); + + assertThat( url, is( "http://localhost:8080/service/collections/water/items/2" ) ); + } + + @Test + public void testBuildUrl_feature_withoutTemplates() { + TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/forest/items/3", + Collections.emptyMap() ); + String url = new UriBuilder( tp ).collectionName( "forest" ).featureId( "3" ).buildUrl(); + + assertThat( url, is( "http://localhost:8080/service/collections/forest/items/3" ) ); + } +} From 124d3ad750151769808ae8d4f47ab128b5b00ae5 Mon Sep 17 00:00:00 2001 From: Lyn Elisa Goltz Date: Wed, 15 Aug 2018 09:18:49 +0200 Subject: [PATCH 4/4] #36 - fixed test for links with media types --- .../opengis/cite/wfs30/CommonDataFixture.java | 55 ++++++++++++ .../opengis/cite/wfs30/SuiteAttribute.java | 5 ++ .../FeatureCollectionsMetadataOperation.java | 38 +++----- .../collections/GetFeatureOperation.java | 26 +----- .../collections/GetFeaturesOperation.java | 24 +----- .../conformance/ConformanceOperation.java | 29 +++++-- .../wfs30/conformance/RequirementClass.java | 86 +++++++++++++++++++ .../cite/wfs30/openapi3/TestPoint.java | 24 +----- .../conformance/ConformanceOperationTest.java | 15 ++-- 9 files changed, 193 insertions(+), 109 deletions(-) create mode 100644 src/main/java/org/opengis/cite/wfs30/CommonDataFixture.java create mode 100644 src/main/java/org/opengis/cite/wfs30/conformance/RequirementClass.java diff --git a/src/main/java/org/opengis/cite/wfs30/CommonDataFixture.java b/src/main/java/org/opengis/cite/wfs30/CommonDataFixture.java new file mode 100644 index 00000000..98bdc712 --- /dev/null +++ b/src/main/java/org/opengis/cite/wfs30/CommonDataFixture.java @@ -0,0 +1,55 @@ +package org.opengis.cite.wfs30; + +import static org.opengis.cite.wfs30.SuiteAttribute.REQUIREMENTCLASSES; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.opengis.cite.wfs30.conformance.RequirementClass; +import org.testng.ITestContext; +import org.testng.SkipException; +import org.testng.annotations.BeforeClass; + +/** + * @author Lyn Goltz + */ +public class CommonDataFixture extends CommonFixture { + + private List requirementClasses; + + @BeforeClass + public void requirementClasses( ITestContext testContext ) { + this.requirementClasses = (List) testContext.getSuite().getAttribute( REQUIREMENTCLASSES.getName() ); + } + + protected List createListOfMediaTypesToSupportForOtherResources( Map linkToSelf ) { + if ( this.requirementClasses == null ) + throw new SkipException( "No requirement classes described in resource /conformance available" ); + List mediaTypesToSupport = new ArrayList<>(); + for ( RequirementClass requirementClass : this.requirementClasses ) + if ( requirementClass.hasMediaTypeForOtherResources() ) + mediaTypesToSupport.add( requirementClass.getMediaTypeOtherResources() ); + if ( linkToSelf != null ) + mediaTypesToSupport.remove( linkToSelf.get( "type" ) ); + return mediaTypesToSupport; + } + + protected List createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures() { + if ( this.requirementClasses == null ) + throw new SkipException( "No requirement classes described in resource /conformance available" ); + List mediaTypesToSupport = new ArrayList<>(); + for ( RequirementClass requirementClass : this.requirementClasses ) + if ( requirementClass.hasMediaTypeForFeaturesAndCollections() ) + mediaTypesToSupport.add( requirementClass.getMediaTypeFeaturesAndCollections() ); + return mediaTypesToSupport; + } + + protected List createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures( Map linkToSelf ) { + List mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures(); + if ( linkToSelf != null ) + mediaTypesToSupport.remove( linkToSelf.get( "type" ) ); + return mediaTypesToSupport; + } + +} diff --git a/src/main/java/org/opengis/cite/wfs30/SuiteAttribute.java b/src/main/java/org/opengis/cite/wfs30/SuiteAttribute.java index 56bcfaa8..86d33120 100644 --- a/src/main/java/org/opengis/cite/wfs30/SuiteAttribute.java +++ b/src/main/java/org/opengis/cite/wfs30/SuiteAttribute.java @@ -34,6 +34,11 @@ public enum SuiteAttribute { */ API_MODEL( "apiModel", OpenApi3.class ), + /** + * Requirement classes parsed from /conformance; Added during execution. + */ + REQUIREMENTCLASSES( "requirementclasses", List.class ), + /** * Parsed collections from resource /collections; Added during execution. */ diff --git a/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java b/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java index c623fc57..dc145544 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/FeatureCollectionsMetadataOperation.java @@ -20,7 +20,7 @@ import java.util.List; import java.util.Map; -import org.opengis.cite.wfs30.CommonFixture; +import org.opengis.cite.wfs30.CommonDataFixture; import org.opengis.cite.wfs30.SuiteAttribute; import org.opengis.cite.wfs30.openapi3.TestPoint; import org.opengis.cite.wfs30.openapi3.UriBuilder; @@ -31,7 +31,6 @@ 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; @@ -40,7 +39,7 @@ /** * @author Lyn Goltz */ -public class FeatureCollectionsMetadataOperation extends CommonFixture { +public class FeatureCollectionsMetadataOperation extends CommonDataFixture { private final Map testPointAndResponses = new HashMap<>(); @@ -149,7 +148,7 @@ public void validateFeatureCollectionsMetadataOperationResponse_Links( TestPoint // Validate that the retrieved document includes links for: Itself, 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 mediaTypesToSupport = createListOfMediaTypesToSupportForOtherResources( linkToSelf ); List> alternateLinks = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, "alternate" ); List typesWithoutLink = findUnsupportedTypes( alternateLinks, mediaTypesToSupport ); @@ -218,25 +217,21 @@ public void validateFeatureCollectionsMetadataOperationResponse_Collections( Tes @Test(description = "Implements A.4.4.6. Validate a Collections Metadata document (Requirement 13)", groups = "collections", dataProvider = "collections", dependsOnMethods = "validateFeatureCollectionsMetadataOperationResponse_Collections") public void validateCollectionsMetadataDocument_Links( TestPoint testPoint, Map collection ) { String collectionName = (String) collection.get( "name" ); - List testPointsForNamedCollection = retrieveTestPointsForCollectionMetadata( apiModel, - collectionName ); - if ( testPointsForNamedCollection.isEmpty() ) - throw new SkipException( "Could not find collection with name " + collectionName - + " in the OpenAPI document" ); - List mediaTypesToSupport = createListOfMediaTypesToSupport( testPointsForNamedCollection.get( 0 ), null ); + List mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures(); List> links = (List>) collection.get( "links" ); - List> alternateLinks = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, - "item" ); - List typesWithoutLink = findUnsupportedTypes( alternateLinks, mediaTypesToSupport ); + List> items = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, "item" ); + List typesWithoutLink = findUnsupportedTypes( items, mediaTypesToSupport ); assertTrue( typesWithoutLink.isEmpty(), - "Collections Metadata document must include links with relation 'item' for each supported encodings. Missing links for types " - + typesWithoutLink ); - List linksWithoutRelOrType = findLinksWithoutRelOrType( alternateLinks ); + "Collections Metadata document for collection with name " + + collectionName + + " must include links with relation 'item' for each supported encodings. Missing links for types " + + String.join( ", ", typesWithoutLink ) ); + List linksWithoutRelOrType = findLinksWithoutRelOrType( items ); assertTrue( linksWithoutRelOrType.isEmpty(), "Links with relation 'item' for encodings must include a rel and type parameter. Missing for links " - + linksWithoutRelOrType ); + + String.join( ", ", linksWithoutRelOrType ) ); } /** @@ -351,13 +346,4 @@ private List> createCollectionsMap( List collections return collectionsMap; } - 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; - } - } \ No newline at end of file diff --git a/src/main/java/org/opengis/cite/wfs30/collections/GetFeatureOperation.java b/src/main/java/org/opengis/cite/wfs30/collections/GetFeatureOperation.java index 30488b3c..f8746094 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/GetFeatureOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/GetFeatureOperation.java @@ -3,7 +3,6 @@ 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.openapi3.OpenApiUtils.retrieveTestPointsForFeature; import static org.opengis.cite.wfs30.util.JsonUtils.findLinkByRel; import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithSupportedMediaTypeByRel; import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithoutRelOrType; @@ -18,16 +17,14 @@ import java.util.List; import java.util.Map; -import org.opengis.cite.wfs30.CommonFixture; +import org.opengis.cite.wfs30.CommonDataFixture; import org.opengis.cite.wfs30.SuiteAttribute; -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; @@ -36,7 +33,7 @@ /** * @author Lyn Goltz */ -public class GetFeatureOperation extends CommonFixture { +public class GetFeatureOperation extends CommonDataFixture { private OpenApi3 apiModel; @@ -151,14 +148,6 @@ public void validateTheGetFeatureOperationResponse( Map collecti if ( response == null ) throw new SkipException( "Could not find a response for collection with name " + collectionName ); - List testPointsForNamedCollection = retrieveTestPointsForFeature( apiModel, collectionName, - featureId ); - - 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" ); @@ -179,7 +168,7 @@ public void validateTheGetFeatureOperationResponse( Map collecti // 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 mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures( linkToSelf ); List> alternateLinks = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, "alternate" ); List typesWithoutLink = findUnsupportedTypes( alternateLinks, mediaTypesToSupport ); @@ -194,15 +183,6 @@ public void validateTheGetFeatureOperationResponse( Map collecti + linksWithoutRelOrType ); } - 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; - } - private String findGetFeatureUrlForGeoJson( Map collection ) { List links = (List) collection.get( "links" ); for ( Object linkObject : links ) { 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 682477de..2d029b22 100644 --- a/src/main/java/org/opengis/cite/wfs30/collections/GetFeaturesOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/collections/GetFeaturesOperation.java @@ -4,7 +4,6 @@ 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.openapi3.OpenApiUtils.retrieveTestPointsForCollection; import static org.opengis.cite.wfs30.util.JsonUtils.collectNumberOfAllReturnedFeatures; import static org.opengis.cite.wfs30.util.JsonUtils.findLinkByRel; import static org.opengis.cite.wfs30.util.JsonUtils.findLinksWithSupportedMediaTypeByRel; @@ -34,9 +33,8 @@ import java.util.Map; import java.util.Random; -import org.opengis.cite.wfs30.CommonFixture; +import org.opengis.cite.wfs30.CommonDataFixture; import org.opengis.cite.wfs30.SuiteAttribute; -import org.opengis.cite.wfs30.openapi3.TestPoint; import org.opengis.cite.wfs30.util.BBox; import org.opengis.cite.wfs30.util.TemporalExtent; import org.testng.ITestContext; @@ -45,7 +43,6 @@ 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 com.reprezen.kaizen.oasparser.model3.Operation; import com.reprezen.kaizen.oasparser.model3.Parameter; @@ -58,7 +55,7 @@ /** * @author Lyn Goltz */ -public class GetFeaturesOperation extends CommonFixture { +public class GetFeaturesOperation extends CommonDataFixture { private final Map collectionNameAndResponse = new HashMap<>(); @@ -217,12 +214,6 @@ public void validateTheGetFeaturesOperationResponse_Links( Map c if ( response == null ) throw new SkipException( "Could not find a response for collection with name " + collectionName ); - List testPointsForNamedCollection = retrieveTestPointsForCollection( apiModel, collectionName ); - 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" ); @@ -233,7 +224,7 @@ public void validateTheGetFeaturesOperationResponse_Links( Map c // 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 mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures( linkToSelf ); List> alternateLinks = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, "alternate" ); List typesWithoutLink = findUnsupportedTypes( alternateLinks, mediaTypesToSupport ); @@ -735,15 +726,6 @@ private String findGetFeaturesUrlForGeoJson( 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; - } - private void assertIntegerGreaterZero( Object value, String propertyName ) { if ( value instanceof Number ) assertIntegerGreaterZero( ( (Number) value ).intValue(), propertyName ); diff --git a/src/main/java/org/opengis/cite/wfs30/conformance/ConformanceOperation.java b/src/main/java/org/opengis/cite/wfs30/conformance/ConformanceOperation.java index 322d2c1d..925af121 100644 --- a/src/main/java/org/opengis/cite/wfs30/conformance/ConformanceOperation.java +++ b/src/main/java/org/opengis/cite/wfs30/conformance/ConformanceOperation.java @@ -3,6 +3,7 @@ import static io.restassured.http.ContentType.JSON; import static io.restassured.http.Method.GET; import static org.opengis.cite.wfs30.SuiteAttribute.API_MODEL; +import static org.opengis.cite.wfs30.SuiteAttribute.REQUIREMENTCLASSES; import static org.opengis.cite.wfs30.WFS3.PATH.CONFORMANCE; import static org.opengis.cite.wfs30.openapi3.OpenApiUtils.retrieveTestPoints; import static org.testng.Assert.assertNotNull; @@ -14,6 +15,7 @@ import org.opengis.cite.wfs30.openapi3.TestPoint; import org.opengis.cite.wfs30.openapi3.UriBuilder; import org.testng.ITestContext; +import org.testng.annotations.AfterClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -27,6 +29,8 @@ */ public class ConformanceOperation extends CommonFixture { + private List requirementClasses; + @DataProvider(name = "conformanceUris") public Object[][] conformanceUris( ITestContext testContext ) { OpenApi3 apiModel = (OpenApi3) testContext.getSuite().getAttribute( API_MODEL.getName() ); @@ -34,6 +38,11 @@ public Object[][] conformanceUris( ITestContext testContext ) { return new Object[][] { testPoints.toArray() }; } + @AfterClass + public void storeRequirementClassesInTestContext( ITestContext testContext ) { + testContext.getSuite().setAttribute( REQUIREMENTCLASSES.getName(), this.requirementClasses ); + } + /** * Implements A.4.4.2. Validate Conformance Operation and A.4.4.3. Validate Conformance Operation Response. * @@ -43,7 +52,7 @@ public Object[][] conformanceUris( ITestContext testContext ) { @Test(description = "Implements A.4.4.2. Validate Conformance Operation (Requirement 5) and A.4.4.3. Validate Conformance Operation Response (Requirement 6)", dataProvider = "conformanceUris", dependsOnGroups = "apidefinition") public void validateConformanceOperationAndResponse( TestPoint testPoint ) { Response response = validateConformanceOperation( testPoint ); - validateConformanceOperationResponse( testPoint, response ); + validateConformanceOperationResponse( response ); } /** @@ -88,12 +97,11 @@ private Response validateConformanceOperation( TestPoint testPoint ) { * * d) References: Requirement 6 */ - private void validateConformanceOperationResponse( TestPoint testPoint, Response response ) { + private void validateConformanceOperationResponse( Response response ) { response.then().statusCode( 200 ); JsonPath jsonPath = response.jsonPath(); - List requirementClasses = parseAndValidateRequirementClasses( jsonPath ); - testPoint.addRequirementClasses( requirementClasses ); + this.requirementClasses = parseAndValidateRequirementClasses( jsonPath ); } /** @@ -103,15 +111,18 @@ private void validateConformanceOperationResponse( TestPoint testPoint, Response * @throws AssertionError * if the json does not follow the expected structure */ - List parseAndValidateRequirementClasses( JsonPath jsonPath ) { - List requirementClasses = new ArrayList<>(); + List parseAndValidateRequirementClasses( JsonPath jsonPath ) { + List requirementClasses = new ArrayList<>(); List conformsTo = jsonPath.getList( "conformsTo" ); assertNotNull( conformsTo, "Missing member 'conformsTo'." ); for ( Object conformTo : conformsTo ) { - if ( conformTo instanceof String ) - requirementClasses.add( (String) conformTo ); - else + if ( conformTo instanceof String ) { + String conformanceClass = (String) conformTo; + RequirementClass requirementClass = RequirementClass.byConformanceClass( conformanceClass ); + if ( requirementClass != null ) + requirementClasses.add( requirementClass ); + } else throw new AssertionError( "At least one element array 'conformsTo' is not a string value (" + conformTo + ")" ); } diff --git a/src/main/java/org/opengis/cite/wfs30/conformance/RequirementClass.java b/src/main/java/org/opengis/cite/wfs30/conformance/RequirementClass.java new file mode 100644 index 00000000..ab97fca5 --- /dev/null +++ b/src/main/java/org/opengis/cite/wfs30/conformance/RequirementClass.java @@ -0,0 +1,86 @@ +package org.opengis.cite.wfs30.conformance; + +/** + * + * Encapsulates all known requirement classes. + * + * @author Lyn Goltz + */ +public enum RequirementClass { + + CORE( "http://www.opengis.net/spec/wfs-1/3.0/req/core" ), + + HTML( "http://www.opengis.net/spec/wfs-1/3.0/req/html", "text/html", "text/html" ), + + GEOJSON( "http://www.opengis.net/spec/wfs-1/3.0/req/geojson", "application/geo+json", "application/json" ), + + GMLSF0( "http://www.opengis.net/spec/wfs-1/3.0/req/gmlsf0", + "application/gml+xml;version=3.2;profile=http://www.opengis.net/def/profile/ogc/2.0/gml-sf0", + "application/xml" ), + + GMLSF2( "http://www.opengis.net/spec/wfs-1/3.0/req/gmlsf2", + "application/gml+xml;version=3.2;profile=http://www.opengis.net/def/profile/ogc/2.0/gml-sf2", + "application/xml" ), + + OPENAPI30( "http://www.opengis.net/spec/wfs-1/3.0/req/oas30" ); + + private final String conformanceClass; + + private final String mediaTypeFeaturesAndCollections; + + private final String mediaTypeOtherResources; + + RequirementClass( String conformanceClass ) { + this( conformanceClass, null, null ); + } + + RequirementClass( String conformanceClass, String mediaTypeFeaturesAndCollections, String mediaTypeOtherResources ) { + this.conformanceClass = conformanceClass; + this.mediaTypeFeaturesAndCollections = mediaTypeFeaturesAndCollections; + this.mediaTypeOtherResources = mediaTypeOtherResources; + } + + /** + * @return true if the RequirementClass has a media type for features and collections, + * true otherwise + */ + public boolean hasMediaTypeForFeaturesAndCollections() { + return mediaTypeFeaturesAndCollections != null; + } + + /** + * @return media type for features and collections, null if not available + */ + public String getMediaTypeFeaturesAndCollections() { + return mediaTypeFeaturesAndCollections; + } + + /** + * @return true if the RequirementClass has a media type for other resources, + * true otherwise + */ + public boolean hasMediaTypeForOtherResources() { + return mediaTypeOtherResources != null; + } + + /** + * @return media type of other resources, null if not available + */ + public String getMediaTypeOtherResources() { + return mediaTypeOtherResources; + } + + /** + * @param conformanceClass + * the conformance class of the RequirementClass to return. + * @return the RequirementClass with the passed conformance class, null if RequirementClass exists + */ + public static RequirementClass byConformanceClass( String conformanceClass ) { + for ( RequirementClass requirementClass : values() ) { + if ( requirementClass.conformanceClass.equals( conformanceClass ) ) + return requirementClass; + } + return null; + } + +} \ No newline at end of file diff --git a/src/main/java/org/opengis/cite/wfs30/openapi3/TestPoint.java b/src/main/java/org/opengis/cite/wfs30/openapi3/TestPoint.java index 69d34d15..e413e351 100644 --- a/src/main/java/org/opengis/cite/wfs30/openapi3/TestPoint.java +++ b/src/main/java/org/opengis/cite/wfs30/openapi3/TestPoint.java @@ -1,7 +1,6 @@ package org.opengis.cite.wfs30.openapi3; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Objects; @@ -20,8 +19,6 @@ public class TestPoint { private Map predefinedTemplateReplacement; - private List requirementClasses; - private Map contentMediaTypes; /** @@ -80,24 +77,6 @@ public Map getPredefinedTemplateReplacement() { return predefinedTemplateReplacement; } - /** - * @return a list of requirement classes the server conforms to, null if the conformance classes are - * not requested - */ - public List getRequirementClasses() { - return requirementClasses; - } - - /** - * Adds the requirement classes the server conforms to - * - * @param requirementClasses - * never null - */ - public void addRequirementClasses( List requirementClasses ) { - this.requirementClasses = requirementClasses; - } - /** * @return the content media types for the GET operation with response "200", may be null */ @@ -120,13 +99,12 @@ public boolean equals( Object o ) { return Objects.equals( serverUrl, testPoint.serverUrl ) && Objects.equals( path, testPoint.predefinedTemplateReplacement ) && Objects.equals( predefinedTemplateReplacement, testPoint.path ) - && Objects.equals( requirementClasses, testPoint.requirementClasses ) && Objects.equals( contentMediaTypes, testPoint.contentMediaTypes ); } @Override public int hashCode() { - return Objects.hash( serverUrl, path, predefinedTemplateReplacement, requirementClasses, contentMediaTypes ); + return Objects.hash( serverUrl, path, predefinedTemplateReplacement, contentMediaTypes ); } } diff --git a/src/test/java/org/opengis/cite/wfs30/conformance/ConformanceOperationTest.java b/src/test/java/org/opengis/cite/wfs30/conformance/ConformanceOperationTest.java index 3d5f363d..0464e459 100644 --- a/src/test/java/org/opengis/cite/wfs30/conformance/ConformanceOperationTest.java +++ b/src/test/java/org/opengis/cite/wfs30/conformance/ConformanceOperationTest.java @@ -1,8 +1,13 @@ package org.opengis.cite.wfs30.conformance; -import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import static org.opengis.cite.wfs30.conformance.RequirementClass.CORE; +import static org.opengis.cite.wfs30.conformance.RequirementClass.GEOJSON; +import static org.opengis.cite.wfs30.conformance.RequirementClass.GMLSF2; +import static org.opengis.cite.wfs30.conformance.RequirementClass.HTML; +import static org.opengis.cite.wfs30.conformance.RequirementClass.OPENAPI30; import java.io.InputStream; import java.util.List; @@ -21,14 +26,10 @@ public void testParseAndValidateRequirementClasses() { ConformanceOperation conformanceOperationTest = new ConformanceOperation(); InputStream json = ConformanceOperationTest.class.getResourceAsStream( "req-classes.json" ); JsonPath jsonPath = new JsonPath( json ); - List requirementClasses = conformanceOperationTest.parseAndValidateRequirementClasses( jsonPath ); + List requirementClasses = conformanceOperationTest.parseAndValidateRequirementClasses( jsonPath ); assertThat( requirementClasses.size(), is( 5 ) ); - assertThat( requirementClasses, hasItem( "http://www.opengis.net/spec/wfs-1/3.0/req/core" ) ); - assertThat( requirementClasses, hasItem( "http://www.opengis.net/spec/wfs-1/3.0/req/oas30" ) ); - assertThat( requirementClasses, hasItem( "http://www.opengis.net/spec/wfs-1/3.0/req/html" ) ); - assertThat( requirementClasses, hasItem( "http://www.opengis.net/spec/wfs-1/3.0/req/geojson" ) ); - assertThat( requirementClasses, hasItem( "http://www.opengis.net/spec/wfs-1/3.0/req/gmlsf2" ) ); + assertThat( requirementClasses, hasItems( CORE, OPENAPI30, HTML, GEOJSON, GMLSF2 ) ); } @Test(expectedExceptions = AssertionError.class)