From 09f0cea1ca0f96ad22fa751987641748ff51a4a9 Mon Sep 17 00:00:00 2001 From: Mitchell Paff Date: Fri, 8 Oct 2021 15:53:33 +1300 Subject: [PATCH] feat: replace remaining non-examples with unit tests --- .../aerial-photo/non-examples/no_run.json | 26 ----- .../non-examples/no_sequence_number.json | 26 ----- .../non-examples/run_integer.json | 27 ----- .../non-examples/sequence_number_string.json | 27 ----- .../tests/aerial_photo_item.test.js | 103 ++++++++++++++++++ extensions/camera/tests/camera.test.js | 19 ++-- .../film/non-examples/film_id_integer.json | 26 ----- .../negative_sequence_string.json | 26 ----- extensions/film/non-examples/no_film_id.json | 25 ----- .../non-examples/no_negative_sequence.json | 25 ----- extensions/film/tests/film.test.js | 101 +++++++++++++++++ validate.sh | 10 -- 12 files changed, 215 insertions(+), 226 deletions(-) delete mode 100644 extensions/aerial-photo/non-examples/no_run.json delete mode 100644 extensions/aerial-photo/non-examples/no_sequence_number.json delete mode 100644 extensions/aerial-photo/non-examples/run_integer.json delete mode 100644 extensions/aerial-photo/non-examples/sequence_number_string.json create mode 100644 extensions/aerial-photo/tests/aerial_photo_item.test.js delete mode 100644 extensions/film/non-examples/film_id_integer.json delete mode 100644 extensions/film/non-examples/negative_sequence_string.json delete mode 100644 extensions/film/non-examples/no_film_id.json delete mode 100644 extensions/film/non-examples/no_negative_sequence.json create mode 100644 extensions/film/tests/film.test.js diff --git a/extensions/aerial-photo/non-examples/no_run.json b/extensions/aerial-photo/non-examples/no_run.json deleted file mode 100644 index 60ebd9f7..00000000 --- a/extensions/aerial-photo/non-examples/no_run.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": ["https://linz.github.io/stac/_STAC_VERSION_/aerial-photo/schema.json"], - "description": "This is a non-conformant STAC example using the aerial photography extension. It is missing the mandatory aerial-photo:run property.", - "type": "Feature", - "id": "72360", - "geometry": null, - "properties": { - "datetime": "1952-04-23T00:00:00.000Z", - "platform": "Fixed-wing Aircraft", - "instruments": ["EAGLE IV"], - "mission": "SURVEY_1", - "aerial-photo:altitude": 3325, - "aerial-photo:scale": 4800, - "aerial-photo:sequence_number": 14, - "aerial-photo:anomalies": "Cloud shadow" - }, - "links": [], - "assets": { - "image/tiff; application=geotiff; profile=cloud-optimized": { - "href": "./72360.tiff", - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "file:checksum": "1220b7deb18ad9dc6f3f94df60c26dd235a019946b8b6b7d1a36f100a8f9f1889130" - } - } -} diff --git a/extensions/aerial-photo/non-examples/no_sequence_number.json b/extensions/aerial-photo/non-examples/no_sequence_number.json deleted file mode 100644 index 0c82303c..00000000 --- a/extensions/aerial-photo/non-examples/no_sequence_number.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": ["https://linz.github.io/stac/_STAC_VERSION_/aerial-photo/schema.json"], - "description": "This is a non-conformant STAC example using the aerial photography extension. It is missing the mandatory aerial-photo:sequence_number property.", - "type": "Feature", - "id": "72360", - "geometry": null, - "properties": { - "datetime": "1952-04-23T00:00:00.000Z", - "platform": "Fixed-wing Aircraft", - "instruments": ["EAGLE IV"], - "mission": "SURVEY_1", - "aerial-photo:run": "P1", - "aerial-photo:altitude": 3325, - "aerial-photo:scale": 4800, - "aerial-photo:anomalies": "Cloud shadow" - }, - "links": [], - "assets": { - "image/tiff; application=geotiff; profile=cloud-optimized": { - "href": "./72360.tiff", - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "file:checksum": "1220b7deb18ad9dc6f3f94df60c26dd235a019946b8b6b7d1a36f100a8f9f1889130" - } - } -} diff --git a/extensions/aerial-photo/non-examples/run_integer.json b/extensions/aerial-photo/non-examples/run_integer.json deleted file mode 100644 index bd64148f..00000000 --- a/extensions/aerial-photo/non-examples/run_integer.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": ["https://linz.github.io/stac/_STAC_VERSION_/aerial-photo/schema.json"], - "description": "This is a non-conformant STAC example using the aerial photography extension. The aerial-photo:run field is an integer instead of a string.", - "type": "Feature", - "id": "72360", - "geometry": null, - "properties": { - "datetime": "1952-04-23T00:00:00.000Z", - "platform": "Fixed-wing Aircraft", - "instruments": ["EAGLE IV"], - "mission": "SURVEY_1", - "aerial-photo:run": 248, - "aerial-photo:altitude": 3325, - "aerial-photo:scale": 4800, - "aerial-photo:sequence_number": 14, - "aerial-photo:anomalies": "Cloud shadow" - }, - "links": [], - "assets": { - "image/tiff; application=geotiff; profile=cloud-optimized": { - "href": "./72360.tiff", - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "file:checksum": "1220b7deb18ad9dc6f3f94df60c26dd235a019946b8b6b7d1a36f100a8f9f1889130" - } - } -} diff --git a/extensions/aerial-photo/non-examples/sequence_number_string.json b/extensions/aerial-photo/non-examples/sequence_number_string.json deleted file mode 100644 index 50c7fd84..00000000 --- a/extensions/aerial-photo/non-examples/sequence_number_string.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": ["https://linz.github.io/stac/_STAC_VERSION_/aerial-photo/schema.json"], - "description": "This is a non-conformant STAC example using the aerial photography extension. The aerial-photo:sequence_number field is a string instead of an integer.", - "type": "Feature", - "id": "72360", - "geometry": null, - "properties": { - "datetime": "1952-04-23T00:00:00.000Z", - "platform": "Fixed-wing Aircraft", - "instruments": ["EAGLE IV"], - "mission": "SURVEY_1", - "aerial-photo:run": "P1", - "aerial-photo:altitude": 3325, - "aerial-photo:scale": 4800, - "aerial-photo:sequence_number": "incorrect string", - "aerial-photo:anomalies": "Cloud shadow" - }, - "links": [], - "assets": { - "image/tiff; application=geotiff; profile=cloud-optimized": { - "href": "./72360.tiff", - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "file:checksum": "1220b7deb18ad9dc6f3f94df60c26dd235a019946b8b6b7d1a36f100a8f9f1889130" - } - } -} diff --git a/extensions/aerial-photo/tests/aerial_photo_item.test.js b/extensions/aerial-photo/tests/aerial_photo_item.test.js new file mode 100644 index 00000000..83893bad --- /dev/null +++ b/extensions/aerial-photo/tests/aerial_photo_item.test.js @@ -0,0 +1,103 @@ +import o from 'ospec'; +import Ajv from 'ajv'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; +import { promises as fs } from 'fs'; +import { AjvOptions } from '../../validation.js'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const schemaPath = join(__dirname, '..', 'schema.json'); +const exampleItemPath = join(__dirname, '..', 'examples/item.json'); + +o.spec('aerial-photo-item', () => { + let validate; + const ajv = new Ajv(AjvOptions); + + o.before(async () => { + const data = JSON.parse(await fs.readFile(schemaPath)); + validate = await ajv.compileAsync(data); + }); + + o('Item should pass validation', async () => { + // given + const aerialPhotoItemExample = JSON.parse(await fs.readFile(exampleItemPath)); + + // when + let valid = validate(aerialPhotoItemExample); + + // then + o(valid).equals(true)(JSON.stringify(validate.errors, null, 2)); + }); + + o("Item with an incorrect 'aerial-photo:run' field should fail validation", async () => { + // given + const aerialPhotoItemExample = JSON.parse(await fs.readFile(exampleItemPath)); + aerialPhotoItemExample.properties['aerial-photo:run'] = 1234; + + // when + let valid = validate(aerialPhotoItemExample); + + // then + o(valid).equals(false); + o( + validate.errors.some( + (error) => error.dataPath === ".properties['aerial-photo:run']" && error.message === 'should be string', + ), + ).equals(true)(JSON.stringify(validate.errors)); + }); + + o("Item without the mandatory 'aerial-photo:run' field should fail validation", async () => { + // given + const aerialPhotoItemExample = JSON.parse(await fs.readFile(exampleItemPath)); + delete aerialPhotoItemExample.properties['aerial-photo:run']; + + // when + let valid = validate(aerialPhotoItemExample); + + // then + o(valid).equals(false); + o( + validate.errors.some( + (error) => + error.dataPath === '.properties' && error.message === "should have required property '['aerial-photo:run']'", + ), + ).equals(true)(JSON.stringify(validate.errors)); + }); + + o("Item without a mandatory 'aerial-photo:sequence_number' field should fail validation", async () => { + // given + const aerialPhotoItemExample = JSON.parse(await fs.readFile(exampleItemPath)); + delete aerialPhotoItemExample.properties['aerial-photo:sequence_number']; + + // when + let valid = validate(aerialPhotoItemExample); + + // then + o(valid).equals(false); + o( + validate.errors.some( + (error) => + error.dataPath === '.properties' && + error.message === "should have required property '['aerial-photo:sequence_number']'", + ), + ).equals(true)(JSON.stringify(validate.errors)); + }); + + o("Item with an incorrect 'aerial-photo:sequence_number' field should fail validation", async () => { + // given + const aerialPhotoItemExample = JSON.parse(await fs.readFile(exampleItemPath)); + aerialPhotoItemExample.properties['aerial-photo:sequence_number'] = 'incorrect_example'; + + // when + let valid = validate(aerialPhotoItemExample); + + // then + o(valid).equals(false); + o( + validate.errors.some( + (error) => + error.dataPath === ".properties['aerial-photo:sequence_number']" && error.message === 'should be integer', + ), + ).equals(true)(JSON.stringify(validate.errors)); + }); +}); diff --git a/extensions/camera/tests/camera.test.js b/extensions/camera/tests/camera.test.js index 49da936d..6698ad28 100644 --- a/extensions/camera/tests/camera.test.js +++ b/extensions/camera/tests/camera.test.js @@ -20,26 +20,29 @@ o.spec('camera', () => { o('camera-validates-successfully', async () => { // given - const camera_item_example = JSON.parse(await fs.readFile(examplePath)); + const cameraItemExample = JSON.parse(await fs.readFile(examplePath)); // when - let valid = validate(camera_item_example); + let valid = validate(cameraItemExample); // then o(valid).equals(true)(JSON.stringify(validate.errors, null, 2)); }); - o('camera-validation-fails', async () => { + o("Item with an incorrect 'camera:sequence_number' field should fail validation", async () => { // given - const camera_item_example = JSON.parse(await fs.readFile(examplePath)); - camera_item_example.properties['camera:sequence_number'] = 'incorrect_value'; + const cameraItemExample = JSON.parse(await fs.readFile(examplePath)); + cameraItemExample.properties['camera:sequence_number'] = 'incorrect_value'; // when - let valid = validate(camera_item_example); + let valid = validate(cameraItemExample); // then o(valid).equals(false); - o(validate.errors.length).equals(1); - o(validate.errors[0].message).equals('should be integer'); + o( + validate.errors.some( + (error) => error.dataPath === ".properties['camera:sequence_number']" && error.message === 'should be integer', + ), + ).equals(true)(JSON.stringify(validate.errors)); }); }); diff --git a/extensions/film/non-examples/film_id_integer.json b/extensions/film/non-examples/film_id_integer.json deleted file mode 100644 index 25dadc1d..00000000 --- a/extensions/film/non-examples/film_id_integer.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": ["https://linz.github.io/stac/_STAC_VERSION_/film/schema.json"], - "description": "This is a non-conformant STAC example using the film extension. The film:id field is an integer instead of a string.", - "type": "Feature", - "id": "72360", - "geometry": null, - "properties": { - "datetime": "1952-04-23T00:00:00.000Z", - "platform": "Fixed-wing Aircraft", - "instruments": ["EAGLE IV"], - "mission": "SURVEY_1", - "film:id": 2250, - "film:negative_sequence": 19, - "film:physical_condition": "Metadata manually populated, Flight chart not available", - "film:physical_size": "18cm x 23cm" - }, - "links": [], - "assets": { - "image/tiff; application=geotiff; profile=cloud-optimized": { - "href": "./72360.tiff", - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "file:checksum": "1220b7deb18ad9dc6f3f94df60c26dd235a019946b8b6b7d1a36f100a8f9f1889130" - } - } -} diff --git a/extensions/film/non-examples/negative_sequence_string.json b/extensions/film/non-examples/negative_sequence_string.json deleted file mode 100644 index 5706233c..00000000 --- a/extensions/film/non-examples/negative_sequence_string.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": ["https://linz.github.io/stac/_STAC_VERSION_/film/schema.json"], - "description": "This is a non-conformant STAC example using the film extension. The film:negative_sequence field is a string instead of an integer.", - "type": "Feature", - "id": "72360", - "geometry": null, - "properties": { - "datetime": "1952-04-23T00:00:00.000Z", - "platform": "Fixed-wing Aircraft", - "instruments": ["EAGLE IV"], - "mission": "SURVEY_1", - "film:id": "TL109A", - "film:negative_sequence": "incorrect string", - "film:physical_condition": "Metadata manually populated, Flight chart not available", - "film:physical_size": "18cm x 23cm" - }, - "links": [], - "assets": { - "image/tiff; application=geotiff; profile=cloud-optimized": { - "href": "./72360.tiff", - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "file:checksum": "1220b7deb18ad9dc6f3f94df60c26dd235a019946b8b6b7d1a36f100a8f9f1889130" - } - } -} diff --git a/extensions/film/non-examples/no_film_id.json b/extensions/film/non-examples/no_film_id.json deleted file mode 100644 index 2f833d95..00000000 --- a/extensions/film/non-examples/no_film_id.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": ["https://linz.github.io/stac/_STAC_VERSION_/film/schema.json"], - "description": "This is a non-conformant STAC example using the film extension. It is missing the mandatory film:id property.", - "type": "Feature", - "id": "72360", - "geometry": null, - "properties": { - "datetime": "1952-04-23T00:00:00.000Z", - "platform": "Fixed-wing Aircraft", - "instruments": ["EAGLE IV"], - "mission": "SURVEY_1", - "film:negative_sequence": 19, - "film:physical_condition": "Metadata manually populated, Flight chart not available", - "film:physical_size": "18cm x 23cm" - }, - "links": [], - "assets": { - "image/tiff; application=geotiff; profile=cloud-optimized": { - "href": "./72360.tiff", - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "file:checksum": "1220b7deb18ad9dc6f3f94df60c26dd235a019946b8b6b7d1a36f100a8f9f1889130" - } - } -} diff --git a/extensions/film/non-examples/no_negative_sequence.json b/extensions/film/non-examples/no_negative_sequence.json deleted file mode 100644 index e70cf3a9..00000000 --- a/extensions/film/non-examples/no_negative_sequence.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": ["https://linz.github.io/stac/_STAC_VERSION_/film/schema.json"], - "description": "This is a non-conformant STAC example using the film extension. It is missing the mandatory film:negative_sequence property.", - "type": "Feature", - "id": "72360", - "geometry": null, - "properties": { - "datetime": "1952-04-23T00:00:00.000Z", - "platform": "Fixed-wing Aircraft", - "instruments": ["EAGLE IV"], - "mission": "SURVEY_1", - "film:id": "TL109A", - "film:physical_condition": "Metadata manually populated, Flight chart not available", - "film:physical_size": "18cm x 23cm" - }, - "links": [], - "assets": { - "image/tiff; application=geotiff; profile=cloud-optimized": { - "href": "./72360.tiff", - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "file:checksum": "1220b7deb18ad9dc6f3f94df60c26dd235a019946b8b6b7d1a36f100a8f9f1889130" - } - } -} diff --git a/extensions/film/tests/film.test.js b/extensions/film/tests/film.test.js new file mode 100644 index 00000000..41d4ba73 --- /dev/null +++ b/extensions/film/tests/film.test.js @@ -0,0 +1,101 @@ +import o from 'ospec'; +import Ajv from 'ajv'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; +import { promises as fs } from 'fs'; +import { AjvOptions } from '../../validation.js'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const schemaPath = join(__dirname, '..', 'schema.json'); +const examplePath = join(__dirname, '..', 'examples/item.json'); + +o.spec('film', () => { + let validate; + const ajv = new Ajv(AjvOptions); + + o.before(async () => { + const data = JSON.parse(await fs.readFile(schemaPath)); + validate = await ajv.compileAsync(data); + }); + + o('film-validates-successfully', async () => { + // given + const filmItemExample = JSON.parse(await fs.readFile(examplePath)); + + // when + let valid = validate(filmItemExample); + + // then + o(valid).equals(true)(JSON.stringify(validate.errors, null, 2)); + }); + + o("Item with an incorrect 'film:id' field should fail validation", async () => { + // given + const filmItemExample = JSON.parse(await fs.readFile(examplePath)); + filmItemExample.properties['film:id'] = 1234; + + // when + let valid = validate(filmItemExample); + + // then + o(valid).equals(false); + o( + validate.errors.some( + (error) => error.dataPath === ".properties['film:id']" && error.message === 'should be string', + ), + ).equals(true)(JSON.stringify(validate.errors)); + }); + + o("Item without a mandatory 'film:id' field should fail validation", async () => { + // given + const filmItemExample = JSON.parse(await fs.readFile(examplePath)); + delete filmItemExample.properties['film:id']; + + // when + let valid = validate(filmItemExample); + + // then + o(valid).equals(false); + o( + validate.errors.some( + (error) => error.dataPath === '.properties' && error.message === "should have required property '['film:id']'", + ), + ).equals(true)(JSON.stringify(validate.errors)); + }); + + o("Item with an incorrect 'film:negative_sequence' field should fail validation", async () => { + // given + const filmItemExample = JSON.parse(await fs.readFile(examplePath)); + filmItemExample.properties['film:negative_sequence'] = 'incorrect_example'; + + // when + let valid = validate(filmItemExample); + + // then + o(valid).equals(false); + o( + validate.errors.some( + (error) => error.dataPath === ".properties['film:negative_sequence']" && error.message === 'should be integer', + ), + ).equals(true)(JSON.stringify(validate.errors)); + }); + + o("Item without a mandatory 'film:negative_sequence' field should fail validation", async () => { + // given + const filmItemExample = JSON.parse(await fs.readFile(examplePath)); + delete filmItemExample.properties['film:negative_sequence']; + + // when + let valid = validate(filmItemExample); + + // then + o(valid).equals(false); + o( + validate.errors.some( + (error) => + error.dataPath === '.properties' && + error.message === "should have required property '['film:negative_sequence']'", + ), + ).equals(true)(JSON.stringify(validate.errors)); + }); +}); diff --git a/validate.sh b/validate.sh index 6a2da219..d5ea84a3 100755 --- a/validate.sh +++ b/validate.sh @@ -14,14 +14,4 @@ validator_command=( --schemaMap=https://linz.github.io/stac/_STAC_VERSION_/linz/schema.json=extensions/linz/schema.json ) "${validator_command[@]}" extensions/*/examples/*.json - -for path in extensions/*/non-examples/*.json -do - if "${validator_command[@]}" "$path" - then - echo "Valid non-example: ${path}" >&2 - exit_code=1 - fi -done - exit "${exit_code-0}"