diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8bdc5268..ec8e428d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -464,7 +464,6 @@ add_jsonschema_test(test/pass_single_resolve_verbose) add_jsonschema_test(test/pass_single_resolve_fragment) add_jsonschema_test(test/pass_single_resolve_fragment_verbose) add_jsonschema_test(test/pass_single_comment_verbose) -add_jsonschema_test(test/pass_single_no_description_verbose) add_jsonschema_test(test/pass_single_no_test_description_verbose) add_jsonschema_test(test/pass_single_data_path) add_jsonschema_test(test/pass_single_data_path_verbose) @@ -669,7 +668,6 @@ add_jsonschema_test(compile/fail_invalid_header) add_jsonschema_test(compile/pass_bundled_metaschema) # Codegen -add_jsonschema_test(codegen/pass_typescript) add_jsonschema_test(codegen/pass_typescript_name) add_jsonschema_test(codegen/pass_typescript_name_short) add_jsonschema_test(codegen/pass_typescript_explicit) @@ -1119,9 +1117,9 @@ add_jsonschema_test(decode/fail_no_output) # CI specific tests add_jsonschema_test_ci(pass_bundle_http) -add_jsonschema_test_ci(fail_bundle_http_non_200) +add_jsonschema_test_ci(fail_bundle_http_non_json) add_jsonschema_test_ci(fail_bundle_http_non_schema) -add_jsonschema_test_ci(fail_validate_http_non_200) +add_jsonschema_test_ci(fail_validate_http_non_json) add_jsonschema_test_ci(fail_validate_http_non_schema) add_jsonschema_test_ci(pass_validate_http) add_jsonschema_test_ci(pass_install_http) diff --git a/test/bundle/pass_ref_in_bundled_resolves_against_id.clitest b/test/bundle/pass_ref_in_bundled_resolves_against_id.clitest index 5009fd87..4f44b5c0 100644 --- a/test/bundle/pass_ref_in_bundled_resolves_against_id.clitest +++ b/test/bundle/pass_ref_in_bundled_resolves_against_id.clitest @@ -22,6 +22,9 @@ EOF RUN bundle entry.json STDIN /dev/null IN . INTO result.txt EXPECTING 0 +// Taken before the placeholders go in, so the bundle keeps its real identifiers +EXTRACT STDOUT FROM result.txt INTO bundled.json + REPLACE $CWD_URI WITH '[CWD_URI]' IN result.txt REPLACE $CWD WITH '[CWD]' IN result.txt @@ -47,3 +50,11 @@ WRITE expected.txt UNTIL EOF EOF COMPARE result.txt AGAINST expected.txt + +// Prove the emitted bundle is well formed JSON, as the sibling bundle tests do +WRITE silent.txt UNTIL EOF +EOF + +RUN fmt bundled.json --check STDIN /dev/null IN . INTO checked.txt EXPECTING 0 + +COMPARE checked.txt AGAINST silent.txt diff --git a/test/ci/fail_bundle_http_non_200.clitest b/test/ci/fail_bundle_http_non_json.clitest similarity index 72% rename from test/ci/fail_bundle_http_non_200.clitest rename to test/ci/fail_bundle_http_non_json.clitest index e5b1b45c..0fd1a0ae 100644 --- a/test/ci/fail_bundle_http_non_200.clitest +++ b/test/ci/fail_bundle_http_non_json.clitest @@ -1,3 +1,6 @@ +// The remote answers 200 with an HTML body, so this covers a +// response that is not JSON at all, as distinct from the sibling +// test where the body is JSON but not a schema WRITE schema.json UNTIL EOF { "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/test/ci/fail_validate_http_non_200.clitest b/test/ci/fail_validate_http_non_json.clitest similarity index 75% rename from test/ci/fail_validate_http_non_200.clitest rename to test/ci/fail_validate_http_non_json.clitest index db5f4073..c99e5fb9 100644 --- a/test/ci/fail_validate_http_non_200.clitest +++ b/test/ci/fail_validate_http_non_json.clitest @@ -1,3 +1,6 @@ +// The remote answers 200 with an HTML body, so this covers a +// response that is not JSON at all, as distinct from the sibling +// test where the body is JSON but not a schema WRITE schema.json UNTIL EOF { "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/test/codegen/pass_default_dialect_option_config.clitest b/test/codegen/pass_default_dialect_option_config.clitest index a4ad6b2f..0a4b80fe 100644 --- a/test/codegen/pass_default_dialect_option_config.clitest +++ b/test/codegen/pass_default_dialect_option_config.clitest @@ -1,6 +1,11 @@ +// `const` arrived in Draft 6, so this schema generates a literal type under +// 2020-12 and fails outright under Draft 4. That makes the output prove which +// dialect won, where a plain `{"type": "string"}` would generate the same +// either way and prove nothing + WRITE schema.json UNTIL EOF { - "type": "string" + "const": "hello" } EOF @@ -13,7 +18,7 @@ EOF RUN codegen schema.json --default-dialect https://json-schema.org/draft/2020-12/schema --target typescript STDIN /dev/null IN . INTO result.txt EXPECTING 0 WRITE expected.txt UNTIL EOF -1> export type Schema = string; +1> export type Schema = "hello"; EOF COMPARE result.txt AGAINST expected.txt diff --git a/test/codegen/pass_typescript.clitest b/test/codegen/pass_typescript.clitest deleted file mode 100644 index fe87eec2..00000000 --- a/test/codegen/pass_typescript.clitest +++ /dev/null @@ -1,27 +0,0 @@ -WRITE schema.json UNTIL EOF -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "name": { "type": "string" }, - "age": { "type": "integer" } - }, - "required": [ "name" ] -} -EOF - -RUN codegen schema.json --target typescript STDIN /dev/null IN . INTO result.txt EXPECTING 0 - -WRITE expected.txt UNTIL EOF -1> export type SchemaName = string; -1> -1> export type SchemaAge = number; -1> -1> export interface Schema { -1> "name": SchemaName; -1> "age"?: SchemaAge; -1> [key: string]: unknown | undefined; -1> } -EOF - -COMPARE result.txt AGAINST expected.txt diff --git a/test/compile/pass_patternproperties.clitest b/test/compile/pass_patternproperties.clitest index 77346c7f..a5c06b6a 100644 --- a/test/compile/pass_patternproperties.clitest +++ b/test/compile/pass_patternproperties.clitest @@ -11,8 +11,15 @@ WRITE schema.json UNTIL EOF } EOF +// The instances below carry a property whose name matches the pattern, so the +// compiled subschema is actually reached. An empty object would satisfy any +// schema and prove nothing about the compilation WRITE instance.json UNTIL EOF -{} +{ "foo-bar": "value" } +EOF + +WRITE instance_invalid.json UNTIL EOF +{ "foo-bar": 1 } EOF WRITE silent.txt UNTIL EOF @@ -25,3 +32,51 @@ EXTRACT STDOUT FROM compiled.txt INTO template.json RUN validate --template template.json schema.json instance.json STDIN /dev/null IN . INTO validated.txt EXPECTING 0 COMPARE validated.txt AGAINST silent.txt + +// Validation failure +RUN validate --template template.json schema.json instance_invalid.json STDIN /dev/null IN . INTO validated_invalid.txt EXPECTING 2 + +REPLACE $CWD WITH '[CWD]' IN validated_invalid.txt + +WRITE expected_invalid.txt UNTIL EOF +2> fail: [CWD]/instance_invalid.json +2> error: Schema validation failure +2> The value was expected to be of type string but it was of type integer +2> at instance location "/foo-bar" (line 1, column 3) +2> at evaluate path "/patternProperties/[\-]/type" +2> The object properties that match the regular expression "[\-]" were expected to validate against the defined pattern property subschema +2> at instance location "" (line 1, column 1) +2> at evaluate path "/patternProperties" +EOF + +COMPARE validated_invalid.txt AGAINST expected_invalid.txt + +// Validation failure +RUN validate --template template.json schema.json instance_invalid.json --json STDIN /dev/null IN . INTO validated_invalid_json.txt EXPECTING 2 + +REPLACE $CWD_URI WITH '[CWD_URI]' IN validated_invalid_json.txt +REPLACE $CWD WITH '[CWD]' IN validated_invalid_json.txt + +WRITE expected_invalid_json.txt UNTIL EOF +1> { +1> "valid": false, +1> "errors": [ +1> { +1> "keywordLocation": "/patternProperties/[\\-]/type", +1> "absoluteKeywordLocation": "[CWD_URI]/schema.json#/patternProperties/%5B%5C-%5D/type", +1> "instanceLocation": "/foo-bar", +1> "instancePosition": [ 1, 3, 1, 14 ], +1> "error": "The value was expected to be of type string but it was of type integer" +1> }, +1> { +1> "keywordLocation": "/patternProperties", +1> "absoluteKeywordLocation": "[CWD_URI]/schema.json#/patternProperties", +1> "instanceLocation": "", +1> "instancePosition": [ 1, 1, 1, 16 ], +1> "error": "The object properties that match the regular expression \"[\\-]\" were expected to validate against the defined pattern property subschema" +1> } +1> ] +1> } +EOF + +COMPARE validated_invalid_json.txt AGAINST expected_invalid_json.txt diff --git a/test/lint/fail_draft4_x_keyword_ref_target_fix.clitest b/test/lint/fail_draft4_x_keyword_ref_target_fix.clitest index 5f0f89f5..c59e3afb 100644 --- a/test/lint/fail_draft4_x_keyword_ref_target_fix.clitest +++ b/test/lint/fail_draft4_x_keyword_ref_target_fix.clitest @@ -24,6 +24,8 @@ WRITE schema.json UNTIL EOF EOF // Schema input error +COPY schema.json TO original.json + RUN lint schema.json --fix STDIN /dev/null IN . INTO result_0.txt EXPECTING 4 REPLACE $CWD_URI WITH '[CWD_URI]' IN result_0.txt @@ -56,3 +58,6 @@ WRITE expected_1.txt UNTIL EOF EOF COMPARE result_1.txt AGAINST expected_1.txt + +// A failed fix must leave the schema exactly as it was +COMPARE schema.json AGAINST original.json diff --git a/test/lint/fail_lint_config_rule_top_level_violation.clitest b/test/lint/fail_lint_config_rule_top_level_violation.clitest index aea490db..9c425dec 100644 --- a/test/lint/fail_lint_config_rule_top_level_violation.clitest +++ b/test/lint/fail_lint_config_rule_top_level_violation.clitest @@ -17,9 +17,17 @@ WRITE jsonschema.json UNTIL EOF } EOF +// The subschema below is what makes `topLevel` observable: with the setting +// only the root is reported, and without it this subschema would be reported +// too. A schema with a root node alone would look identical either way WRITE schema.json UNTIL EOF { - "$schema": "https://json-schema.org/draft/2020-12/schema" + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$defs": { + "inner": { + "type": "string" + } + } } EOF @@ -43,7 +51,7 @@ REPLACE $CWD WITH '[CWD]' IN result_1.txt WRITE expected_1.txt UNTIL EOF 1> { 1> "valid": false, -1> "health": 0, +1> "health": 50, 1> "errors": [ 1> { 1> "path": "[CWD]/schema.json", @@ -51,7 +59,7 @@ WRITE expected_1.txt UNTIL EOF 1> "message": "The root schema must declare an $id", 1> "description": "The object value was expected to define the property \"$id\"", 1> "schemaLocation": [], -1> "position": [ 1, 1, 3, 1 ] +1> "position": [ 1, 1, 8, 1 ] 1> } 1> ] 1> } diff --git a/test/lint/fail_lint_directory_unresolvable_fix.clitest b/test/lint/fail_lint_directory_unresolvable_fix.clitest index e52f9182..ac0dd132 100644 --- a/test/lint/fail_lint_directory_unresolvable_fix.clitest +++ b/test/lint/fail_lint_directory_unresolvable_fix.clitest @@ -1,4 +1,8 @@ -WRITE foo.json UNTIL EOF +// The schemas live in a subdirectory so that the untouched copies taken below +// are not themselves picked up by the recursive lint +MAKE DIRECTORY schemas + +WRITE schemas/foo.json UNTIL EOF { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Test", @@ -6,7 +10,7 @@ WRITE foo.json UNTIL EOF } EOF -WRITE bar.json UNTIL EOF +WRITE schemas/bar.json UNTIL EOF { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Test", @@ -14,7 +18,7 @@ WRITE bar.json UNTIL EOF } EOF -WRITE baz.json UNTIL EOF +WRITE schemas/baz.json UNTIL EOF { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Test", @@ -24,18 +28,27 @@ WRITE baz.json UNTIL EOF } EOF +COPY schemas/foo.json TO original_foo.json +COPY schemas/bar.json TO original_bar.json +COPY schemas/baz.json TO original_baz.json + // Validation failure -RUN lint $CWD --fix --verbose STDIN /dev/null IN . INTO result_0.txt EXPECTING 2 +RUN lint $CWD/schemas --fix --verbose STDIN /dev/null IN . INTO result_0.txt EXPECTING 2 REPLACE $CWD WITH '[CWD]' IN result_0.txt WRITE expected_0.txt UNTIL EOF -1> baz.json:5:16: +1> schemas/baz.json:5:16: 1> External references must point to schemas that can be resolved (invalid_external_ref) 1> at location "/allOf/0/$ref" -2> Linting: [CWD]/bar.json -2> Linting: [CWD]/baz.json -2> Linting: [CWD]/foo.json +2> Linting: [CWD]/schemas/bar.json +2> Linting: [CWD]/schemas/baz.json +2> Linting: [CWD]/schemas/foo.json EOF COMPARE result_0.txt AGAINST expected_0.txt + +// A failed fix must leave every schema in the directory as it was +COMPARE schemas/foo.json AGAINST original_foo.json +COMPARE schemas/bar.json AGAINST original_bar.json +COMPARE schemas/baz.json AGAINST original_baz.json diff --git a/test/lint/fail_lint_rule_violation.clitest b/test/lint/fail_lint_rule_violation.clitest index e64f715e..4f34bf95 100644 --- a/test/lint/fail_lint_rule_violation.clitest +++ b/test/lint/fail_lint_rule_violation.clitest @@ -14,10 +14,19 @@ WRITE schema.json UNTIL EOF EOF // Validation failure -RUN lint --rule rule.json --only require_type schema.json STDIN /dev/null IN . INTO result_0.txt EXPECTING 2 +RUN lint --rule rule.json schema.json STDIN /dev/null IN . INTO result_0.txt EXPECTING 2 WRITE expected_0.txt UNTIL EOF 1> schema.json:1:1: +1> Set a concise non-empty title at the top level of the schema to explain what the definition is about (top_level_title) +1> at location "" +1> schema.json:1:1: +1> Set a non-empty description at the top level of the schema to explain what the definition is about in detail (top_level_description) +1> at location "" +1> schema.json:1:1: +1> Set a non-empty examples array at the top level of the schema to illustrate the expected data (top_level_examples) +1> at location "" +1> schema.json:1:1: 1> Every subschema must declare the type keyword (require_type) 1> at location "" 1> The object value was expected to define the property "type" diff --git a/test/lint/fail_lint_rule_violation_json.clitest b/test/lint/fail_lint_rule_violation_json.clitest index 9ec6259a..264c1d16 100644 --- a/test/lint/fail_lint_rule_violation_json.clitest +++ b/test/lint/fail_lint_rule_violation_json.clitest @@ -14,7 +14,7 @@ WRITE schema.json UNTIL EOF EOF // Validation failure -RUN lint --rule rule.json --only require_type --json schema.json STDIN /dev/null IN . INTO result_0.txt EXPECTING 2 +RUN lint --rule rule.json --json schema.json STDIN /dev/null IN . INTO result_0.txt EXPECTING 2 REPLACE $CWD WITH '[CWD]' IN result_0.txt @@ -25,6 +25,30 @@ WRITE expected_0.txt UNTIL EOF 1> "errors": [ 1> { 1> "path": "[CWD]/schema.json", +1> "id": "top_level_title", +1> "message": "Set a concise non-empty title at the top level of the schema to explain what the definition is about", +1> "description": null, +1> "schemaLocation": [], +1> "position": [ 1, 1, 3, 1 ] +1> }, +1> { +1> "path": "[CWD]/schema.json", +1> "id": "top_level_description", +1> "message": "Set a non-empty description at the top level of the schema to explain what the definition is about in detail", +1> "description": null, +1> "schemaLocation": [], +1> "position": [ 1, 1, 3, 1 ] +1> }, +1> { +1> "path": "[CWD]/schema.json", +1> "id": "top_level_examples", +1> "message": "Set a non-empty examples array at the top level of the schema to illustrate the expected data", +1> "description": null, +1> "schemaLocation": [], +1> "position": [ 1, 1, 3, 1 ] +1> }, +1> { +1> "path": "[CWD]/schema.json", 1> "id": "require_type", 1> "message": "Every subschema must declare the type keyword", 1> "description": "The object value was expected to define the property \"type\"", diff --git a/test/lint/pass_lint_config_rule_no_violation.clitest b/test/lint/pass_lint_config_rule_no_violation.clitest index 053ccba7..06dd00f5 100644 --- a/test/lint/pass_lint_config_rule_no_violation.clitest +++ b/test/lint/pass_lint_config_rule_no_violation.clitest @@ -17,14 +17,20 @@ WRITE jsonschema.json UNTIL EOF } EOF +// The title, description and examples below satisfy the built-in top level +// rules, so the schema stays clean under the full rule set and this test only +// fails if a rule regresses on it WRITE schema.json UNTIL EOF { "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test schema", + "examples": [ "foo" ], "type": "string" } EOF -RUN lint --only require_type schema.json STDIN /dev/null IN . INTO result_0.txt EXPECTING 0 +RUN lint schema.json STDIN /dev/null IN . INTO result_0.txt EXPECTING 0 WRITE expected_0.txt UNTIL EOF EOF diff --git a/test/lint/pass_lint_rule_no_violation.clitest b/test/lint/pass_lint_rule_no_violation.clitest index 3feacc9a..ee7a2049 100644 --- a/test/lint/pass_lint_rule_no_violation.clitest +++ b/test/lint/pass_lint_rule_no_violation.clitest @@ -7,14 +7,20 @@ WRITE rule.json UNTIL EOF } EOF +// The title, description and examples below satisfy the built-in top level +// rules, so the schema stays clean under the full rule set and this test only +// fails if a rule regresses on it WRITE schema.json UNTIL EOF { "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test schema", + "examples": [ "foo" ], "type": "string" } EOF -RUN lint --rule rule.json --only require_type schema.json STDIN /dev/null IN . INTO result_0.txt EXPECTING 0 +RUN lint --rule rule.json schema.json STDIN /dev/null IN . INTO result_0.txt EXPECTING 0 WRITE expected_0.txt UNTIL EOF EOF diff --git a/test/test/pass_single_no_description_verbose.clitest b/test/test/pass_single_no_description_verbose.clitest deleted file mode 100644 index 5bf7f2b6..00000000 --- a/test/test/pass_single_no_description_verbose.clitest +++ /dev/null @@ -1,38 +0,0 @@ -WRITE schema.json UNTIL EOF -{ - "id": "https://example.com", - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Test", - "description": "Test schema", - "type": "string" -} -EOF - -WRITE test.json UNTIL EOF -{ - "target": "https://example.com", - "tests": [ - { - "valid": true, - "data": "foo" - }, - { - "valid": false, - "data": 1 - } - ] -} -EOF - -RUN test test.json --resolve schema.json --verbose --jobs 1 STDIN /dev/null IN . INTO result_0.txt EXPECTING 0 - -REPLACE $CWD WITH '[CWD]' IN result_0.txt - -WRITE expected_0.txt UNTIL EOF -1> [CWD]/test.json: -1> 1/2 PASS -1> 2/2 PASS -2> Using parallelism: 1 -EOF - -COMPARE result_0.txt AGAINST expected_0.txt