├── .check.exs ├── .credo.exs ├── .dialyzer_ignore.exs ├── .formatter.exs ├── .github ├── dependabot.yml └── workflows │ ├── dependencies.yaml │ └── elixir.yaml ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── cliff.toml ├── config ├── config.exs └── dev.exs ├── dev ├── doc_gen │ └── generator.ex ├── gen.test.suite.ex └── update_jsts_ref.ex ├── guides ├── build │ ├── build-basics.md │ ├── resolvers.md │ └── vocabularies.md ├── schemas │ ├── cast-functions.md │ └── defining-schemas.md └── validation │ ├── decimal-support.md │ └── validation-basics.md ├── justfile ├── lib ├── jsv.ex └── jsv │ ├── boolean_schema.ex │ ├── build_error.ex │ ├── builder.ex │ ├── cast.ex │ ├── codec.ex │ ├── codec │ ├── jason_codec.ex │ ├── native_codec.ex │ └── poison_codec.ex │ ├── debanger.ex │ ├── error_formatter.ex │ ├── format_validator.ex │ ├── format_validator │ ├── default.ex │ └── default │ │ ├── optional.ex │ │ └── optional │ │ ├── email_address.ex │ │ ├── iri.ex │ │ ├── json_pointer.ex │ │ ├── uri.ex │ │ ├── uri_template.ex │ │ └── uuid.ex │ ├── helpers │ ├── enum_ext.ex │ ├── map_ext.ex │ ├── math.ex │ ├── string_ext.ex │ └── traverse.ex │ ├── key.ex │ ├── normalizer.ex │ ├── normalizer │ └── normalize.ex │ ├── ref.ex │ ├── resolver.ex │ ├── resolver │ ├── embedded.ex │ ├── embedded │ │ ├── draft202012 │ │ │ ├── meta │ │ │ │ ├── applicator.ex │ │ │ │ ├── content.ex │ │ │ │ ├── core.ex │ │ │ │ ├── format_annotation.ex │ │ │ │ ├── meta_data.ex │ │ │ │ ├── unevaluated.ex │ │ │ │ └── validation.ex │ │ │ └── schema.ex │ │ └── draft7 │ │ │ └── schema.ex │ ├── httpc.ex │ ├── internal.ex │ └── local.ex │ ├── rns.ex │ ├── root.ex │ ├── schema.ex │ ├── schema │ └── defcompose.ex │ ├── struct_support.ex │ ├── subschema.ex │ ├── validation_error.ex │ ├── validator.ex │ ├── validator │ └── error.ex │ ├── vocabulary.ex │ └── vocabulary │ ├── cast.ex │ ├── v202012 │ ├── applicator.ex │ ├── content.ex │ ├── core.ex │ ├── format.ex │ ├── meta_data.ex │ ├── unevaluated.ex │ └── validation.ex │ └── v7 │ ├── applicator.ex │ ├── content.ex │ ├── core.ex │ ├── format.ex │ ├── meta_data.ex │ └── validation.ex ├── mix.exs ├── mix.lock ├── priv └── grammars │ ├── email-address.abnf │ ├── iri.abnf │ ├── json-pointer.abnf │ ├── uri-template.abnf │ └── uri.abnf ├── test ├── jsv │ ├── builder_test.exs │ ├── cast_test.exs │ ├── codec_test.exs │ ├── custom_vocabularies_test.exs │ ├── error_format_test.exs │ ├── format_validation_test.exs │ ├── generated │ │ ├── draft202012 │ │ │ ├── atom_keys │ │ │ │ ├── additional_properties_test.exs │ │ │ │ ├── all_of_test.exs │ │ │ │ ├── anchor_test.exs │ │ │ │ ├── any_of_test.exs │ │ │ │ ├── boolean_schema_test.exs │ │ │ │ ├── const_test.exs │ │ │ │ ├── contains_test.exs │ │ │ │ ├── content_test.exs │ │ │ │ ├── date_test.exs │ │ │ │ ├── date_time_test.exs │ │ │ │ ├── default_test.exs │ │ │ │ ├── defs_test.exs │ │ │ │ ├── dependent_required_test.exs │ │ │ │ ├── dependent_schemas_test.exs │ │ │ │ ├── duration_test.exs │ │ │ │ ├── dynamic_ref_test.exs │ │ │ │ ├── email_test.exs │ │ │ │ ├── enum_test.exs │ │ │ │ ├── exclusive_maximum_test.exs │ │ │ │ ├── exclusive_minimum_test.exs │ │ │ │ ├── format_test.exs │ │ │ │ ├── hostname_test.exs │ │ │ │ ├── if_then_else_test.exs │ │ │ │ ├── infinite_loop_detection_test.exs │ │ │ │ ├── ipv4_test.exs │ │ │ │ ├── ipv6_test.exs │ │ │ │ ├── iri_reference_test.exs │ │ │ │ ├── iri_test.exs │ │ │ │ ├── items_test.exs │ │ │ │ ├── json_pointer_test.exs │ │ │ │ ├── max_contains_test.exs │ │ │ │ ├── max_items_test.exs │ │ │ │ ├── max_length_test.exs │ │ │ │ ├── max_properties_test.exs │ │ │ │ ├── maximum_test.exs │ │ │ │ ├── min_contains_test.exs │ │ │ │ ├── min_items_test.exs │ │ │ │ ├── min_length_test.exs │ │ │ │ ├── min_properties_test.exs │ │ │ │ ├── minimum_test.exs │ │ │ │ ├── multiple_of_test.exs │ │ │ │ ├── not_test.exs │ │ │ │ ├── one_of_test.exs │ │ │ │ ├── optional │ │ │ │ │ ├── anchor_test.exs │ │ │ │ │ ├── bignum_test.exs │ │ │ │ │ ├── dependencies_compatibility_test.exs │ │ │ │ │ ├── dynamic_ref_test.exs │ │ │ │ │ ├── format_assertion_test.exs │ │ │ │ │ ├── id_test.exs │ │ │ │ │ ├── no_schema_test.exs │ │ │ │ │ └── ref_of_unknown_keyword_test.exs │ │ │ │ ├── pattern_properties_test.exs │ │ │ │ ├── pattern_test.exs │ │ │ │ ├── prefix_items_test.exs │ │ │ │ ├── properties_test.exs │ │ │ │ ├── property_names_test.exs │ │ │ │ ├── ref_remote_test.exs │ │ │ │ ├── ref_test.exs │ │ │ │ ├── regex_test.exs │ │ │ │ ├── relative_json_pointer_test.exs │ │ │ │ ├── required_test.exs │ │ │ │ ├── time_test.exs │ │ │ │ ├── type_test.exs │ │ │ │ ├── unevaluated_items_test.exs │ │ │ │ ├── unevaluated_properties_test.exs │ │ │ │ ├── unique_items_test.exs │ │ │ │ ├── unknown_test.exs │ │ │ │ ├── uri_reference_test.exs │ │ │ │ ├── uri_template_test.exs │ │ │ │ ├── uri_test.exs │ │ │ │ ├── uuid_test.exs │ │ │ │ └── vocabulary_test.exs │ │ │ ├── binary_keys │ │ │ │ ├── additional_properties_test.exs │ │ │ │ ├── all_of_test.exs │ │ │ │ ├── anchor_test.exs │ │ │ │ ├── any_of_test.exs │ │ │ │ ├── boolean_schema_test.exs │ │ │ │ ├── const_test.exs │ │ │ │ ├── contains_test.exs │ │ │ │ ├── content_test.exs │ │ │ │ ├── date_test.exs │ │ │ │ ├── date_time_test.exs │ │ │ │ ├── default_test.exs │ │ │ │ ├── defs_test.exs │ │ │ │ ├── dependent_required_test.exs │ │ │ │ ├── dependent_schemas_test.exs │ │ │ │ ├── duration_test.exs │ │ │ │ ├── dynamic_ref_test.exs │ │ │ │ ├── email_test.exs │ │ │ │ ├── enum_test.exs │ │ │ │ ├── exclusive_maximum_test.exs │ │ │ │ ├── exclusive_minimum_test.exs │ │ │ │ ├── format_test.exs │ │ │ │ ├── hostname_test.exs │ │ │ │ ├── if_then_else_test.exs │ │ │ │ ├── infinite_loop_detection_test.exs │ │ │ │ ├── ipv4_test.exs │ │ │ │ ├── ipv6_test.exs │ │ │ │ ├── iri_reference_test.exs │ │ │ │ ├── iri_test.exs │ │ │ │ ├── items_test.exs │ │ │ │ ├── json_pointer_test.exs │ │ │ │ ├── max_contains_test.exs │ │ │ │ ├── max_items_test.exs │ │ │ │ ├── max_length_test.exs │ │ │ │ ├── max_properties_test.exs │ │ │ │ ├── maximum_test.exs │ │ │ │ ├── min_contains_test.exs │ │ │ │ ├── min_items_test.exs │ │ │ │ ├── min_length_test.exs │ │ │ │ ├── min_properties_test.exs │ │ │ │ ├── minimum_test.exs │ │ │ │ ├── multiple_of_test.exs │ │ │ │ ├── not_test.exs │ │ │ │ ├── one_of_test.exs │ │ │ │ ├── optional │ │ │ │ │ ├── anchor_test.exs │ │ │ │ │ ├── bignum_test.exs │ │ │ │ │ ├── dependencies_compatibility_test.exs │ │ │ │ │ ├── dynamic_ref_test.exs │ │ │ │ │ ├── format_assertion_test.exs │ │ │ │ │ ├── id_test.exs │ │ │ │ │ ├── no_schema_test.exs │ │ │ │ │ └── ref_of_unknown_keyword_test.exs │ │ │ │ ├── pattern_properties_test.exs │ │ │ │ ├── pattern_test.exs │ │ │ │ ├── prefix_items_test.exs │ │ │ │ ├── properties_test.exs │ │ │ │ ├── property_names_test.exs │ │ │ │ ├── ref_remote_test.exs │ │ │ │ ├── ref_test.exs │ │ │ │ ├── regex_test.exs │ │ │ │ ├── relative_json_pointer_test.exs │ │ │ │ ├── required_test.exs │ │ │ │ ├── time_test.exs │ │ │ │ ├── type_test.exs │ │ │ │ ├── unevaluated_items_test.exs │ │ │ │ ├── unevaluated_properties_test.exs │ │ │ │ ├── unique_items_test.exs │ │ │ │ ├── unknown_test.exs │ │ │ │ ├── uri_reference_test.exs │ │ │ │ ├── uri_template_test.exs │ │ │ │ ├── uri_test.exs │ │ │ │ ├── uuid_test.exs │ │ │ │ └── vocabulary_test.exs │ │ │ └── decimal_values │ │ │ │ ├── any_of_test.exs │ │ │ │ ├── date_test.exs │ │ │ │ ├── date_time_test.exs │ │ │ │ ├── duration_test.exs │ │ │ │ ├── dynamic_ref_test.exs │ │ │ │ ├── email_test.exs │ │ │ │ ├── exclusive_maximum_test.exs │ │ │ │ ├── exclusive_minimum_test.exs │ │ │ │ ├── format_test.exs │ │ │ │ ├── hostname_test.exs │ │ │ │ ├── ipv4_test.exs │ │ │ │ ├── ipv6_test.exs │ │ │ │ ├── iri_reference_test.exs │ │ │ │ ├── iri_test.exs │ │ │ │ ├── json_pointer_test.exs │ │ │ │ ├── maximum_test.exs │ │ │ │ ├── minimum_test.exs │ │ │ │ ├── multiple_of_test.exs │ │ │ │ ├── one_of_test.exs │ │ │ │ ├── optional │ │ │ │ └── bignum_test.exs │ │ │ │ ├── pattern_test.exs │ │ │ │ ├── ref_test.exs │ │ │ │ ├── regex_test.exs │ │ │ │ ├── relative_json_pointer_test.exs │ │ │ │ ├── time_test.exs │ │ │ │ ├── type_test.exs │ │ │ │ ├── unevaluated_items_test.exs │ │ │ │ ├── unevaluated_properties_test.exs │ │ │ │ ├── unknown_test.exs │ │ │ │ ├── uri_reference_test.exs │ │ │ │ ├── uri_template_test.exs │ │ │ │ ├── uri_test.exs │ │ │ │ └── uuid_test.exs │ │ └── draft7 │ │ │ ├── atom_keys │ │ │ ├── additional_items_test.exs │ │ │ ├── additional_properties_test.exs │ │ │ ├── all_of_test.exs │ │ │ ├── any_of_test.exs │ │ │ ├── boolean_schema_test.exs │ │ │ ├── const_test.exs │ │ │ ├── contains_test.exs │ │ │ ├── date_test.exs │ │ │ ├── date_time_test.exs │ │ │ ├── default_test.exs │ │ │ ├── definitions_test.exs │ │ │ ├── dependencies_test.exs │ │ │ ├── email_test.exs │ │ │ ├── enum_test.exs │ │ │ ├── exclusive_maximum_test.exs │ │ │ ├── exclusive_minimum_test.exs │ │ │ ├── format_test.exs │ │ │ ├── hostname_test.exs │ │ │ ├── if_then_else_test.exs │ │ │ ├── infinite_loop_detection_test.exs │ │ │ ├── ipv4_test.exs │ │ │ ├── ipv6_test.exs │ │ │ ├── iri_reference_test.exs │ │ │ ├── iri_test.exs │ │ │ ├── items_test.exs │ │ │ ├── json_pointer_test.exs │ │ │ ├── max_items_test.exs │ │ │ ├── max_length_test.exs │ │ │ ├── max_properties_test.exs │ │ │ ├── maximum_test.exs │ │ │ ├── min_items_test.exs │ │ │ ├── min_length_test.exs │ │ │ ├── min_properties_test.exs │ │ │ ├── minimum_test.exs │ │ │ ├── multiple_of_test.exs │ │ │ ├── not_test.exs │ │ │ ├── one_of_test.exs │ │ │ ├── optional │ │ │ │ ├── bignum_test.exs │ │ │ │ └── id_test.exs │ │ │ ├── pattern_properties_test.exs │ │ │ ├── pattern_test.exs │ │ │ ├── properties_test.exs │ │ │ ├── property_names_test.exs │ │ │ ├── ref_remote_test.exs │ │ │ ├── ref_test.exs │ │ │ ├── regex_test.exs │ │ │ ├── relative_json_pointer_test.exs │ │ │ ├── required_test.exs │ │ │ ├── time_test.exs │ │ │ ├── type_test.exs │ │ │ ├── unique_items_test.exs │ │ │ ├── unknown_test.exs │ │ │ ├── uri_reference_test.exs │ │ │ ├── uri_template_test.exs │ │ │ └── uri_test.exs │ │ │ ├── binary_keys │ │ │ ├── additional_items_test.exs │ │ │ ├── additional_properties_test.exs │ │ │ ├── all_of_test.exs │ │ │ ├── any_of_test.exs │ │ │ ├── boolean_schema_test.exs │ │ │ ├── const_test.exs │ │ │ ├── contains_test.exs │ │ │ ├── date_test.exs │ │ │ ├── date_time_test.exs │ │ │ ├── default_test.exs │ │ │ ├── definitions_test.exs │ │ │ ├── dependencies_test.exs │ │ │ ├── email_test.exs │ │ │ ├── enum_test.exs │ │ │ ├── exclusive_maximum_test.exs │ │ │ ├── exclusive_minimum_test.exs │ │ │ ├── format_test.exs │ │ │ ├── hostname_test.exs │ │ │ ├── if_then_else_test.exs │ │ │ ├── infinite_loop_detection_test.exs │ │ │ ├── ipv4_test.exs │ │ │ ├── ipv6_test.exs │ │ │ ├── iri_reference_test.exs │ │ │ ├── iri_test.exs │ │ │ ├── items_test.exs │ │ │ ├── json_pointer_test.exs │ │ │ ├── max_items_test.exs │ │ │ ├── max_length_test.exs │ │ │ ├── max_properties_test.exs │ │ │ ├── maximum_test.exs │ │ │ ├── min_items_test.exs │ │ │ ├── min_length_test.exs │ │ │ ├── min_properties_test.exs │ │ │ ├── minimum_test.exs │ │ │ ├── multiple_of_test.exs │ │ │ ├── not_test.exs │ │ │ ├── one_of_test.exs │ │ │ ├── optional │ │ │ │ ├── bignum_test.exs │ │ │ │ └── id_test.exs │ │ │ ├── pattern_properties_test.exs │ │ │ ├── pattern_test.exs │ │ │ ├── properties_test.exs │ │ │ ├── property_names_test.exs │ │ │ ├── ref_remote_test.exs │ │ │ ├── ref_test.exs │ │ │ ├── regex_test.exs │ │ │ ├── relative_json_pointer_test.exs │ │ │ ├── required_test.exs │ │ │ ├── time_test.exs │ │ │ ├── type_test.exs │ │ │ ├── unique_items_test.exs │ │ │ ├── unknown_test.exs │ │ │ ├── uri_reference_test.exs │ │ │ ├── uri_template_test.exs │ │ │ └── uri_test.exs │ │ │ └── decimal_values │ │ │ ├── any_of_test.exs │ │ │ ├── date_test.exs │ │ │ ├── date_time_test.exs │ │ │ ├── email_test.exs │ │ │ ├── exclusive_maximum_test.exs │ │ │ ├── exclusive_minimum_test.exs │ │ │ ├── format_test.exs │ │ │ ├── hostname_test.exs │ │ │ ├── ipv4_test.exs │ │ │ ├── ipv6_test.exs │ │ │ ├── iri_reference_test.exs │ │ │ ├── iri_test.exs │ │ │ ├── json_pointer_test.exs │ │ │ ├── maximum_test.exs │ │ │ ├── minimum_test.exs │ │ │ ├── multiple_of_test.exs │ │ │ ├── one_of_test.exs │ │ │ ├── optional │ │ │ └── bignum_test.exs │ │ │ ├── pattern_test.exs │ │ │ ├── ref_test.exs │ │ │ ├── regex_test.exs │ │ │ ├── relative_json_pointer_test.exs │ │ │ ├── time_test.exs │ │ │ ├── type_test.exs │ │ │ ├── unknown_test.exs │ │ │ ├── uri_reference_test.exs │ │ │ ├── uri_template_test.exs │ │ │ └── uri_test.exs │ ├── helpers │ │ ├── enum_ext_test.exs │ │ └── traverse_test.exs │ ├── macrogen_test.exs │ ├── normalizer_test.exs │ ├── ref_test.exs │ ├── resolver │ │ ├── httpc_test.exs │ │ ├── internal_test.exs │ │ └── local_test.exs │ ├── resolver_test.exs │ ├── rns_test.exs │ ├── schema_test.exs │ ├── struct_schema_test.exs │ └── struct_support_test.exs ├── jsv_test.exs ├── support │ ├── example_modules.ex │ ├── json_schema_suite.ex │ ├── schemas │ │ └── user-schema.json │ ├── test_helpers.ex │ └── test_resolver.ex └── test_helper.exs └── tools └── check-docs-format.exs /.check.exs: -------------------------------------------------------------------------------- 1 | [ 2 | parallel: true, 3 | skipped: false, 4 | fix: false, 5 | retry: false, 6 | tools: [ 7 | {:compiler, true}, 8 | {:doctor, false}, 9 | {:gettext, false}, 10 | {:credo, "mix credo --all --strict"}, 11 | # custom audit command 12 | {:"deps.audit", "mix deps.audit --format human"}, 13 | {:mix_audit, false} 14 | ] 15 | ] 16 | -------------------------------------------------------------------------------- /.dialyzer_ignore.exs: -------------------------------------------------------------------------------- 1 | [ 2 | {"lib/jsv/format_validator/default/optional/iri.ex", :unused_fun}, 3 | {"lib/jsv/format_validator/default/optional/iri.ex", :extra_range}, 4 | {"lib/jsv/format_validator/default/optional/json_pointer.ex", :extra_range}, 5 | {"lib/jsv/format_validator/default/optional/uri.ex", :unused_fun}, 6 | {"lib/jsv/format_validator/default/optional/uri.ex", :extra_range}, 7 | {"lib/jsv/format_validator/default/optional/uri_template.ex", :extra_range}, 8 | {"lib/jsv/format_validator/default/optional/email_address.ex", :extra_range}, 9 | {"lib/jsv/codec.ex", :extra_range} 10 | ] 11 | -------------------------------------------------------------------------------- /.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | line_length: 120, 4 | import_deps: [:readmix], 5 | inputs: ["*.exs", "{config,lib,test,tools,tmp,dev}/**/*.{ex,exs}"], 6 | force_do_end_blocks: true, 7 | locals_without_parens: [ 8 | pass: 1, 9 | passp: 1, 10 | ignore_keyword: 1, 11 | take_keyword: 5, 12 | take_keyword: 6, 13 | consume_keyword: 1, 14 | defcompose: 2, 15 | defcast: 1, 16 | defcast: 2, 17 | defcast: 3, 18 | with_decimal: 1, 19 | debang: 1 20 | ] 21 | ] 22 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: mix 5 | directory: / 6 | schedule: 7 | interval: daily 8 | timezone: Europe/Paris 9 | time: "06:00" 10 | commit-message: 11 | prefix: "chore(deps)" 12 | open-pull-requests-limit: 1 13 | groups: 14 | prod: 15 | dependency-type: production 16 | dev: 17 | dependency-type: development 18 | 19 | - package-ecosystem: "github-actions" 20 | directory: / 21 | schedule: 22 | interval: daily 23 | timezone: Europe/Paris 24 | time: "06:00" 25 | commit-message: 26 | prefix: "chore(deps)" 27 | open-pull-requests-limit: 1 28 | groups: 29 | github-actions: 30 | applies-to: version-updates 31 | patterns: 32 | - "*" 33 | -------------------------------------------------------------------------------- /.github/workflows/dependencies.yaml: -------------------------------------------------------------------------------- 1 | name: "Mix Dependency Submission" 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | 8 | # The API requires write permission on the repository to submit dependencies 9 | permissions: 10 | contents: write 11 | 12 | jobs: 13 | report_mix_deps: 14 | name: "Report Mix Dependencies" 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: erlef/mix-dependency-submission@v1 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | jsv-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | 28 | .env.test -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "markdown.extension.toc.slugifyMode": "github", 3 | "markdown.extension.toc.levels": "2..3" 4 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Ludovic Demblans 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSV 2 | 3 | 8 | [![hex.pm Version](https://img.shields.io/hexpm/v/jsv?color=4e2a8e)](https://hex.pm/packages/jsv) 9 | [![Build Status](https://img.shields.io/github/actions/workflow/status/lud/jsv/elixir.yaml?label=CI&branch=main)](https://github.com/lud/jsv/actions/workflows/elixir.yaml?query=branch%3Amain) 10 | [![License](https://img.shields.io/hexpm/l/jsv.svg)](https://hex.pm/packages/jsv) 11 | 12 | 13 | JSV is a JSON Schema Validation library for Elixir with full support for the latest JSON Schema specification. 14 | 15 | 16 | ## Documentation 17 | 18 | [API documentation is available on hexdocs.pm](https://hexdocs.pm/jsv/). 19 | 20 | 21 | ## Installation 22 | 23 | 24 | ```elixir 25 | def deps do 26 | [ 27 | {:jsv, "~> 0.7"}, 28 | ] 29 | end 30 | ``` 31 | 32 | 33 | Additional dependencies can be added to support more features: 34 | 35 | ```elixir 36 | def deps do 37 | [ 38 | # Optional libraries for enhanced format validation like URI, IRI, email 39 | # address, JSON-pointer, etc. 40 | {:abnf_parsec, "~> 1.0"}, 41 | 42 | # JSV Supports Decimal and will validate Decimal structs as numbers. 43 | {:decimal, "~> 2.0"}, 44 | 45 | # Optional libraries for decoding schemas resolved via HTTP 46 | # (required for Elixir versions prior to 1.18) 47 | {:jason, "~> 1.0"}, 48 | # OR 49 | {:poison, "~> 6.0 or ~> 5.0"}, 50 | ] 51 | end 52 | ``` 53 | 54 | 55 | ## Basic Usage 56 | 57 | Here is an example of how to use the library: 58 | 59 | ```elixir 60 | schema = %{ 61 | type: :object, 62 | properties: %{ 63 | name: %{type: :string} 64 | }, 65 | required: [:name] 66 | } 67 | 68 | root = JSV.build!(schema) 69 | 70 | case JSV.validate(%{"name" => "Alice"}, root) do 71 | {:ok, data} -> 72 | {:ok, data} 73 | 74 | # Errors can be converted into JSON-compatible structures for API responses 75 | # or logging. 76 | {:error, validation_error} -> 77 | {:error, JSON.encode!(JSV.normalize_error(validation_error))} 78 | end 79 | ``` 80 | 81 | JSV offers many additional features! Check the documentation for more details. 82 | 83 | 84 | ## Contributing 85 | 86 | Pull requests are welcome, provided they include appropriate tests and documentation. 87 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | if config_env() in [:dev] do 4 | import_config "#{config_env()}.exs" 5 | end 6 | -------------------------------------------------------------------------------- /config/dev.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | config :readmix, generators: [jsv: JSV.DocGen.Generator] 4 | -------------------------------------------------------------------------------- /dev/update_jsts_ref.ex: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.Specs 2 | # credo:disable-for-this-file Credo.Check.Readability.ModuleDoc 3 | defmodule Mix.Tasks.Jsv.UpdateJstsRef do 4 | use Mix.Task 5 | 6 | @dep_dir "deps/json_schema_test_suite" 7 | 8 | def run(_argv) do 9 | IO.puts("pulling main on #{@dep_dir}") 10 | 11 | current_ref = current_ref() 12 | {_, 0} = git(~w(reset --hard HEAD)) 13 | {_, 0} = git(~w(checkout main)) 14 | {_, 0} = git(~w(pull)) 15 | {new_ref, 0} = git(~w(rev-parse HEAD)) 16 | new_ref = String.trim(new_ref) 17 | 18 | if new_ref == current_ref do 19 | Mix.Shell.IO.error("JSON Schema Test Suite already up-to-date on #{new_ref}") 20 | System.halt(1) 21 | end 22 | 23 | {log, 0} = git(~w(log #{current_ref}..#{new_ref})) 24 | IO.puts([IO.ANSI.faint(), log, IO.ANSI.reset()]) 25 | 26 | IO.puts("updating mix.exs") 27 | 28 | "mix.exs" 29 | |> File.read!() 30 | |> String.replace(~r/@jsts_ref "[^"]+"/, ~s(@jsts_ref "#{new_ref}")) 31 | |> then(&File.write!("mix.exs", &1)) 32 | 33 | IO.puts("done") 34 | end 35 | 36 | defp current_ref do 37 | Mix.Project.config() 38 | |> Keyword.fetch!(:deps) 39 | |> List.keyfind!(:json_schema_test_suite, 0) 40 | |> elem(1) 41 | |> Keyword.fetch!(:ref) 42 | end 43 | 44 | defp git(argv) do 45 | System.cmd("git", argv, cd: @dep_dir) 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | gen-test-suite: 2 | mix compile 3 | mix jsv.gen_test_suite draft2020-12 4 | mix jsv.gen_test_suite draft7 5 | # mix format --check-formatted 6 | # git status --porcelain | rg "test/generated" --count && mix test || true 7 | 8 | update-test-suite: deps 9 | mix deps.get 10 | mix jsv.update_jsts_ref 11 | mix deps.get 12 | just gen-test-suite 13 | mix test 14 | just _git_status 15 | 16 | deps: 17 | mix deps.get 18 | 19 | test: 20 | mix test 21 | 22 | lint: 23 | mix compile --force --warnings-as-errors 24 | mix credo 25 | 26 | dialyzer: 27 | mix dialyzer --format dialyzer 28 | 29 | _mix_format: 30 | mix format 31 | 32 | _mix_check: 33 | mix check 34 | 35 | _git_status: 36 | git status 37 | 38 | docs: 39 | mix docs 40 | mix rdmx.update README.md 41 | rg rdmx guides -l0 | xargs -0 -n 1 mix rdmx.update 42 | 43 | changelog: 44 | git cliff -o CHANGELOG.md 45 | 46 | check: deps _mix_format _mix_check docs _git_status 47 | 48 | -------------------------------------------------------------------------------- /lib/jsv/boolean_schema.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.BooleanSchema do 2 | alias JSV.Builder 3 | 4 | @moduledoc """ 5 | Represents a boolean schema. Boolean schemas accept or reject any data 6 | according to their boolean value. 7 | 8 | This is very often used with the `additionalProperties` keyword. 9 | """ 10 | 11 | @enforce_keys [:valid?, :schema_path] 12 | defstruct @enforce_keys 13 | 14 | @type t :: %__MODULE__{valid?: boolean, schema_path: [Builder.path_segment()]} 15 | 16 | @doc """ 17 | Returns a `#{inspect(__MODULE__)}` struct wrapping the given boolean. 18 | """ 19 | @spec of(boolean, [Builder.path_segment()]) :: t 20 | def of(valid?, schema_path) when is_boolean(valid?) do 21 | %__MODULE__{valid?: valid?, schema_path: schema_path} 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/jsv/build_error.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.BuildError do 2 | @moduledoc """ 3 | A simple wrapper for errors returned from `JSV.build/2`. 4 | """ 5 | 6 | @enforce_keys [:reason, :action, :build_path] 7 | defexception @enforce_keys 8 | 9 | @doc """ 10 | Wraps the given term as the `reason` in a `#{inspect(__MODULE__)}` struct. 11 | 12 | The `action` should be a `{module, function, [arg1, arg2, ..., argN]}` tuple or 13 | a mfa tuple whenever possible. 14 | """ 15 | 16 | @spec of(term, term, build_path :: nil | String.t()) :: Exception.t() 17 | def of(reason, action, build_path \\ nil) do 18 | %__MODULE__{reason: reason, action: action, build_path: build_path} 19 | end 20 | 21 | @impl true 22 | def message(%{reason: reason, action: {m, f, a}}) when is_atom(m) and is_atom(f) and (is_list(a) or is_integer(a)) do 23 | """ 24 | could not build JSON schema 25 | 26 | REASON 27 | #{inspect(reason, pretty: true)} 28 | 29 | action 30 | #{Exception.format_mfa(m, f, a)} 31 | """ 32 | end 33 | 34 | def message(e) do 35 | "could not build JSON schema got error: #{inspect(e.reason)} in context #{inspect(e.action)}" 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/jsv/cast.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Cast do 2 | import JSV 3 | 4 | @moduledoc false 5 | 6 | defcast string_to_integer(data) do 7 | with true <- is_binary(data), 8 | {int, ""} <- Integer.parse(data) do 9 | {:ok, int} 10 | else 11 | _ -> {:error, "invalid integer representation"} 12 | end 13 | end 14 | 15 | defcast string_to_float(data) do 16 | with true <- is_binary(data), 17 | {float, ""} <- Float.parse(data) do 18 | {:ok, float} 19 | else 20 | _ -> {:error, "invalid floating point number representation"} 21 | end 22 | end 23 | 24 | defcast string_to_number(data) do 25 | with true <- is_binary(data), 26 | {:ok, number} <- parse_number(data) do 27 | {:ok, number} 28 | else 29 | _ -> {:error, "invalid number representation"} 30 | end 31 | end 32 | 33 | defp parse_number(data) do 34 | case Float.parse(data) do 35 | {float, ""} -> 36 | {:ok, float} 37 | 38 | _ -> 39 | case Integer.parse(data) do 40 | {int, ""} -> {:ok, int} 41 | _ -> :error 42 | end 43 | end 44 | end 45 | 46 | defcast string_to_boolean(data) do 47 | case data do 48 | "true" -> {:ok, true} 49 | "false" -> {:ok, false} 50 | _ -> {:error, "invalid boolean representation"} 51 | end 52 | end 53 | 54 | defcast string_to_existing_atom(data) do 55 | {:ok, String.to_existing_atom(data)} 56 | rescue 57 | ArgumentError -> {:error, "not an existing atom representation"} 58 | end 59 | 60 | defcast string_to_atom(data) do 61 | if is_binary(data) do 62 | {:ok, String.to_atom(data)} 63 | else 64 | {:error, "not an atom representation"} 65 | end 66 | end 67 | 68 | @doc false 69 | @spec format_error(term, term, term) :: binary 70 | def format_error(_, message, _) do 71 | message 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /lib/jsv/codec/jason_codec.ex: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.Specs 2 | 3 | if Code.ensure_loaded?(Jason) do 4 | defmodule JSV.Codec.JasonCodec do 5 | alias JSV.Helpers.Traverse 6 | 7 | @moduledoc false 8 | 9 | def supports_formatting? do 10 | true 11 | end 12 | 13 | def supports_ordered_formatting? do 14 | true 15 | end 16 | 17 | def decode!(json) do 18 | Jason.decode!(json) 19 | end 20 | 21 | def decode(json) do 22 | Jason.decode(json) 23 | end 24 | 25 | def encode_to_iodata!(data) do 26 | Jason.encode_to_iodata!(data) 27 | end 28 | 29 | def format_to_iodata!(data) do 30 | Jason.encode_to_iodata!(data, pretty: true) 31 | end 32 | 33 | def to_ordered_data(data, key_sorter) do 34 | Traverse.postwalk(data, fn 35 | {:val, map} when is_map(map) -> 36 | map 37 | |> Map.to_list() 38 | |> Enum.sort(fn {ka, _}, {kb, _} -> key_sorter.(ka, kb) end) 39 | |> Jason.OrderedObject.new() 40 | 41 | {:val, v} -> 42 | v 43 | 44 | {:key, k} -> 45 | k 46 | 47 | {:struct, struct, _cont} -> 48 | raise ArgumentError, "ordered JSON encoding does not support structs, got: #{inspect(struct)}" 49 | end) 50 | end 51 | end 52 | 53 | defimpl Jason.Encoder, for: JSV.ValidationError do 54 | def encode(err, opts) do 55 | err 56 | |> JSV.normalize_error() 57 | |> Jason.Encoder.Map.encode(opts) 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/jsv/codec/poison_codec.ex: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.Specs 2 | 3 | if Code.ensure_loaded?(Poison) do 4 | defmodule JSV.Codec.PoisonCodec do 5 | @moduledoc false 6 | 7 | def supports_formatting? do 8 | true 9 | end 10 | 11 | def supports_ordered_formatting? do 12 | false 13 | end 14 | 15 | def decode!(json) do 16 | Poison.decode!(json) 17 | end 18 | 19 | def decode(json) do 20 | Poison.decode(json) 21 | end 22 | 23 | def encode_to_iodata!(data) do 24 | Poison.encode_to_iodata!(data, strict_keys: true) 25 | end 26 | 27 | def format_to_iodata!(data) do 28 | Poison.encode_to_iodata!(data, strict_keys: true, pretty: true) 29 | end 30 | 31 | @spec to_ordered_data(term, term) :: no_return() 32 | def to_ordered_data(_data, _key_sorter) do 33 | raise "ordered JSON encoding requires Jason" 34 | end 35 | end 36 | 37 | defimpl Poison.Encoder, for: JSV.ValidationError do 38 | def encode(err, opts) do 39 | err 40 | |> JSV.normalize_error() 41 | |> Poison.Encoder.Map.encode(opts) 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/jsv/format_validator.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.FormatValidator do 2 | @moduledoc """ 3 | Behaviour for format validator implementations. 4 | 5 | Such implementations must be given to `JSV.build/2` in the `:formats` option: 6 | 7 | JSV.build!(raw_schema, 8 | resolver: resolver, 9 | formats: [MyModule | JSV.default_format_validator_modules()] 10 | ) 11 | 12 | Each given module is interrogated for format support when a schema is built. 13 | Modules earlier in the list take precedence and if a format is found in the 14 | returned value of the `c:supported_formats/0` callback, the module is selected 15 | for compilation and no other module will be tried. 16 | 17 | A module can declare multiple formats. 18 | """ 19 | 20 | @type format :: String.t() 21 | 22 | @doc """ 23 | Returns the list of the supported formats, as strings. 24 | """ 25 | @callback supported_formats :: [format] 26 | 27 | @doc """ 28 | Receives the schema format as string, and the data as a string. 29 | 30 | Returns a result tuple with data optionally casted to a more meaningful data 31 | structure (for instance returning a `Date` struct instead of the string 32 | representation of the date). 33 | """ 34 | @callback validate_cast(format, data :: String.t()) :: {:ok, term} | {:error, term} 35 | end 36 | -------------------------------------------------------------------------------- /lib/jsv/format_validator/default/optional.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.FormatValidator.Default.Optional do 2 | @moduledoc false 3 | 4 | @doc false 5 | @spec optional_support(binary, boolean) :: [binary] 6 | def optional_support(format, supported?) when is_boolean(supported?) do 7 | if supported? do 8 | List.wrap(format) 9 | else 10 | [] 11 | end 12 | end 13 | 14 | @doc false 15 | @spec mod_exists?(module) :: boolean 16 | def mod_exists?(module) do 17 | case Code.ensure_loaded(module) do 18 | {:module, ^module} -> true 19 | {:error, _} -> false 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/jsv/format_validator/default/optional/email_address.ex: -------------------------------------------------------------------------------- 1 | require JSV.FormatValidator.Default.Optional 2 | 3 | if JSV.FormatValidator.Default.Optional.mod_exists?(AbnfParsec) do 4 | defmodule JSV.FormatValidator.Default.Optional.EmailAddress do 5 | @moduledoc false 6 | @external_resource "priv/grammars/email-address.abnf" 7 | use AbnfParsec, 8 | abnf_file: "priv/grammars/email-address.abnf", 9 | unbox: [], 10 | ignore: [] 11 | 12 | @doc false 13 | @spec parse_email_address(binary) :: {:ok, URI.t()} | {:error, term} 14 | def parse_email_address(data) do 15 | case email_address(data) do 16 | {:ok, _, "", _, _, _} -> {:ok, data} 17 | _ -> {:error, :invalid_email} 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/jsv/format_validator/default/optional/iri.ex: -------------------------------------------------------------------------------- 1 | require JSV.FormatValidator.Default.Optional 2 | 3 | if JSV.FormatValidator.Default.Optional.mod_exists?(AbnfParsec) do 4 | defmodule JSV.FormatValidator.Default.Optional.IRI do 5 | @moduledoc false 6 | @external_resource "priv/grammars/iri.abnf" 7 | use AbnfParsec, 8 | abnf_file: "priv/grammars/iri.abnf", 9 | unbox: [], 10 | ignore: [] 11 | 12 | @doc false 13 | @spec parse_iri(binary) :: {:ok, URI.t()} | {:error, term} 14 | def parse_iri(data) do 15 | case iri(data) do 16 | {:ok, _, "", _, _, _} -> {:ok, URI.parse(data)} 17 | _ -> {:error, :invalid_IRI} 18 | end 19 | end 20 | 21 | @doc false 22 | @spec parse_iri_reference(binary) :: {:ok, URI.t()} | {:error, term} 23 | def parse_iri_reference(data) do 24 | case iri_reference(data) do 25 | {:ok, _, "", _, _, _} -> {:ok, URI.parse(data)} 26 | _ -> {:error, :invalid_IRI_reference} 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/jsv/format_validator/default/optional/json_pointer.ex: -------------------------------------------------------------------------------- 1 | require JSV.FormatValidator.Default.Optional 2 | 3 | if JSV.FormatValidator.Default.Optional.mod_exists?(AbnfParsec) do 4 | defmodule JSV.FormatValidator.Default.Optional.JSONPointer do 5 | @moduledoc false 6 | @external_resource "priv/grammars/json-pointer.abnf" 7 | 8 | use AbnfParsec, 9 | abnf_file: "priv/grammars/json-pointer.abnf", 10 | unbox: [], 11 | ignore: [] 12 | 13 | @doc false 14 | @spec parse_json_pointer(binary) :: {:ok, binary} | {:error, term} 15 | def parse_json_pointer(data) do 16 | case json_pointer(data) do 17 | {:ok, _, "", _, _, _} -> {:ok, data} 18 | _ -> {:error, :invalid_JSON_pointer} 19 | end 20 | end 21 | 22 | @doc false 23 | @spec parse_relative_json_pointer(binary) :: {:ok, binary} | {:error, term} 24 | def parse_relative_json_pointer(data) do 25 | case relative_json_pointer(data) do 26 | {:ok, _, "", _, _, _} -> {:ok, data} 27 | _ -> {:error, :invalid_relative_JSON_pointer} 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/jsv/format_validator/default/optional/uri.ex: -------------------------------------------------------------------------------- 1 | require JSV.FormatValidator.Default.Optional 2 | 3 | if JSV.FormatValidator.Default.Optional.mod_exists?(AbnfParsec) do 4 | defmodule JSV.FormatValidator.Default.Optional.URI do 5 | @moduledoc false 6 | @external_resource "priv/grammars/uri.abnf" 7 | 8 | use AbnfParsec, 9 | abnf_file: "priv/grammars/uri.abnf", 10 | unbox: [], 11 | ignore: [] 12 | 13 | @doc false 14 | @spec parse_uri(binary) :: {:ok, URI.t()} | {:error, term} 15 | def parse_uri(data) do 16 | case uri(data) do 17 | {:ok, _, "", _, _, _} -> {:ok, URI.parse(data)} 18 | _ -> {:error, :invalid_URI} 19 | end 20 | end 21 | 22 | @doc false 23 | @spec parse_uri_reference(binary) :: {:ok, URI.t()} | {:error, term} 24 | def parse_uri_reference(data) do 25 | case uri_reference(data) do 26 | {:ok, _, "", _, _, _} -> {:ok, URI.parse(data)} 27 | _ -> {:error, :invalid_URI_reference} 28 | end 29 | end 30 | end 31 | else 32 | defmodule JSV.FormatValidator.Default.Optional.URI do 33 | @moduledoc false 34 | @doc false 35 | @spec parse_uri(binary) :: {:ok, URI.t()} | {:error, term} 36 | def parse_uri(data) do 37 | case URI.parse(data) do 38 | %{scheme: nil} -> {:error, :no_uri_scheme} 39 | %{host: nil} -> {:error, :no_uri_host} 40 | uri -> {:ok, uri} 41 | end 42 | end 43 | 44 | @doc false 45 | @spec parse_uri_reference(binary) :: {:ok, URI.t()} | {:error, term} 46 | def parse_uri_reference(data) do 47 | case URI.parse(data) do 48 | %{host: nil, path: path, fragment: frag, query: q} = uri 49 | when is_binary(path) 50 | when is_binary(frag) 51 | when is_binary(q) -> 52 | {:ok, uri} 53 | 54 | %{host: "", path: path, fragment: frag, query: q} = uri 55 | when is_binary(path) 56 | when is_binary(frag) 57 | when is_binary(q) -> 58 | {:ok, uri} 59 | 60 | %{host: nil} -> 61 | {:error, :no_uri_host} 62 | 63 | %{host: ""} -> 64 | {:error, :no_uri_host} 65 | 66 | uri -> 67 | {:ok, uri} 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /lib/jsv/format_validator/default/optional/uri_template.ex: -------------------------------------------------------------------------------- 1 | require JSV.FormatValidator.Default.Optional 2 | 3 | if JSV.FormatValidator.Default.Optional.mod_exists?(AbnfParsec) do 4 | defmodule JSV.FormatValidator.Default.Optional.URITemplate do 5 | @moduledoc false 6 | @external_resource "priv/grammars/uri-template.abnf" 7 | 8 | use AbnfParsec, 9 | abnf_file: "priv/grammars/uri-template.abnf", 10 | unbox: [], 11 | ignore: [] 12 | 13 | @doc false 14 | @spec parse_uri_template(binary) :: {:ok, binary} | {:error, term} 15 | def parse_uri_template(data) do 16 | case uri_template(data) do 17 | {:ok, _, "", _, _, _} -> {:ok, data} 18 | _ -> {:error, :invalid_URI_template} 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/jsv/format_validator/default/optional/uuid.ex: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Refactor.CyclomaticComplexity 2 | 3 | defmodule JSV.FormatValidator.Default.Optional.UUID do 4 | @moduledoc false 5 | defguard is_hex(n) when n in ?0..?9 or n in ?a..?f or n in ?A..?F 6 | 7 | @doc false 8 | @spec parse_uuid(binary) :: {:ok, binary} | {:error, :invalid_uuid_format} 9 | def parse_uuid( 10 | <> = data 12 | ) 13 | when is_hex(a1) and 14 | is_hex(a2) and 15 | is_hex(a3) and 16 | is_hex(a4) and 17 | is_hex(a5) and 18 | is_hex(a6) and 19 | is_hex(a7) and 20 | is_hex(a8) and 21 | is_hex(b1) and 22 | is_hex(b2) and 23 | is_hex(b3) and 24 | is_hex(b4) and 25 | is_hex(c1) and 26 | is_hex(c2) and 27 | is_hex(c3) and 28 | is_hex(c4) and 29 | is_hex(d1) and 30 | is_hex(d2) and 31 | is_hex(d3) and 32 | is_hex(d4) and 33 | is_hex(e1) and 34 | is_hex(e2) and 35 | is_hex(e3) and 36 | is_hex(e4) and 37 | is_hex(e5) and 38 | is_hex(e6) and 39 | is_hex(e7) and 40 | is_hex(e8) and 41 | is_hex(e9) and 42 | is_hex(e10) and 43 | is_hex(e11) and 44 | is_hex(e12) do 45 | {:ok, data} 46 | end 47 | 48 | # 49 | def parse_uuid(_) do 50 | {:error, :invalid_uuid_format} 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/jsv/helpers/enum_ext.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Helpers.EnumExt do 2 | @type result :: {:ok, term} | {:error, term} 3 | @type result(t) :: {:ok, t} | {:error, term} 4 | import Kernel, except: [trunc: 1] 5 | 6 | @moduledoc false 7 | 8 | @doc false 9 | @spec reduce_ok(Enumerable.t(), term, (term, term -> result)) :: result 10 | def reduce_ok(enum, initial, f) when is_function(f, 2) do 11 | Enum.reduce_while(enum, {:ok, initial}, fn item, {:ok, acc} -> 12 | case f.(item, acc) do 13 | {:ok, new_acc} -> {:cont, {:ok, new_acc}} 14 | {:error, _} = err -> {:halt, err} 15 | other -> raise ArgumentError, "bad return from reduce_ok callback: #{inspect(other)}" 16 | end 17 | end) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/jsv/helpers/map_ext.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Helpers.MapExt do 2 | @moduledoc """ 3 | Helpers to work with maps. 4 | """ 5 | 6 | @doc """ 7 | Returns the given struct without its `:__struct__` key and any key whose value 8 | is `nil`. 9 | """ 10 | @spec from_struct_no_nils(struct) :: map 11 | def from_struct_no_nils(%_{} = struct) do 12 | struct 13 | |> Map.from_struct() 14 | |> Map.filter(fn {_, v} -> v != nil end) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/jsv/helpers/math.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Helpers.Math do 2 | @moduledoc false 3 | 4 | # This will not work with large numbers 5 | @spec fractional_is_zero?(float) :: boolean 6 | def fractional_is_zero?(n) when is_float(n) do 7 | diff = n - Kernel.trunc(n) 8 | diff === 0.0 || diff === -0.0 9 | end 10 | 11 | # This will not work with large numbers 12 | @spec trunc(number) :: integer 13 | def trunc(n) when is_float(n) do 14 | Kernel.trunc(n) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/jsv/helpers/string_ext.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Helpers.StringExt do 2 | @moduledoc false 3 | 4 | @doc """ 5 | Returns the given string converted to an atom as a result tuple. 6 | """ 7 | @spec safe_string_to_existing_module(String.t()) :: {:ok, atom} | {:error, {:unknown_module, String.t()}} 8 | def safe_string_to_existing_module(string) do 9 | module = String.to_existing_atom(string) 10 | Code.ensure_loaded!(module) 11 | {:ok, module} 12 | rescue 13 | _ in ArgumentError -> {:error, {:unknown_module, string}} 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/jsv/normalizer/normalize.ex: -------------------------------------------------------------------------------- 1 | defprotocol JSV.Normalizer.Normalize do 2 | @moduledoc """ 3 | Protocol used by `JSV.Normalizer` to transform structs into JSON-compatible 4 | data structures when normalizing a schema. 5 | 6 | When implementing this protocol you do not need to run any specific 7 | normalization by yourself, but rather just return a map with all or a 8 | selection of keys. Keys can be atoms or binaries, and values will be 9 | normalized recursively. 10 | """ 11 | @spec normalize(term) :: term 12 | def normalize(t) 13 | end 14 | -------------------------------------------------------------------------------- /lib/jsv/resolver/embedded.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.Embedded do 2 | alias JSV.Resolver.Internal 3 | 4 | @behaviour JSV.Resolver 5 | 6 | mapping = %{ 7 | "http://json-schema.org/draft-07/schema" => __MODULE__.Draft7.Schema, 8 | "https://json-schema.org/draft/2020-12/schema" => __MODULE__.Draft202012.Schema, 9 | "https://json-schema.org/draft/2020-12/meta/core" => __MODULE__.Draft202012.Meta.Core, 10 | "https://json-schema.org/draft/2020-12/meta/validation" => __MODULE__.Draft202012.Meta.Validation, 11 | "https://json-schema.org/draft/2020-12/meta/applicator" => __MODULE__.Draft202012.Meta.Applicator, 12 | "https://json-schema.org/draft/2020-12/meta/unevaluated" => __MODULE__.Draft202012.Meta.Unevaluated, 13 | "https://json-schema.org/draft/2020-12/meta/meta-data" => __MODULE__.Draft202012.Meta.MetaData, 14 | "https://json-schema.org/draft/2020-12/meta/format-annotation" => __MODULE__.Draft202012.Meta.FormatAnnotation, 15 | "https://json-schema.org/draft/2020-12/meta/content" => __MODULE__.Draft202012.Meta.Content 16 | } 17 | 18 | ids_list = mapping |> Map.keys() |> Enum.sort(:desc) 19 | 20 | @moduledoc """ 21 | A `JSV.Resolver` implementation that resolves known schemas shipped as part of 22 | the `JSV` library. 23 | 24 | Internal URIs such as `jsv:module:` are delegated to the 25 | #{inspect(Internal)} resolver. 26 | 27 | ### Embedded schemas 28 | 29 | #{Enum.map(ids_list, &["* ", &1, "\n"])} 30 | """ 31 | 32 | @impl true 33 | def resolve(url, opts) 34 | 35 | Enum.each(mapping, fn {url, module} -> 36 | def resolve(unquote(url), _) do 37 | {:normal, unquote(module).schema()} 38 | end 39 | end) 40 | 41 | def resolve(other, _) do 42 | {:error, {:not_embedded, other}} 43 | end 44 | 45 | @doc """ 46 | Returns the list of meta schemas embedded in this resolver. The IDs are given 47 | in normalized form, _i.e._ URLs without fragments. 48 | """ 49 | 50 | @spec embedded_normalized_ids :: [String.t()] 51 | def embedded_normalized_ids do 52 | unquote(ids_list) 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/jsv/resolver/embedded/draft202012/meta/applicator.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.Embedded.Draft202012.Meta.Applicator do 2 | @moduledoc false 3 | 4 | @spec schema :: map 5 | def schema do 6 | %{ 7 | "$defs" => %{ 8 | "schemaArray" => %{ 9 | "items" => %{"$dynamicRef" => "#meta"}, 10 | "minItems" => 1, 11 | "type" => "array" 12 | } 13 | }, 14 | "$dynamicAnchor" => "meta", 15 | "$id" => "https://json-schema.org/draft/2020-12/meta/applicator", 16 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 17 | "properties" => %{ 18 | "additionalProperties" => %{"$dynamicRef" => "#meta"}, 19 | "allOf" => %{"$ref" => "#/$defs/schemaArray"}, 20 | "anyOf" => %{"$ref" => "#/$defs/schemaArray"}, 21 | "contains" => %{"$dynamicRef" => "#meta"}, 22 | "dependentSchemas" => %{ 23 | "additionalProperties" => %{"$dynamicRef" => "#meta"}, 24 | "default" => %{}, 25 | "type" => "object" 26 | }, 27 | "else" => %{"$dynamicRef" => "#meta"}, 28 | "if" => %{"$dynamicRef" => "#meta"}, 29 | "items" => %{"$dynamicRef" => "#meta"}, 30 | "not" => %{"$dynamicRef" => "#meta"}, 31 | "oneOf" => %{"$ref" => "#/$defs/schemaArray"}, 32 | "patternProperties" => %{ 33 | "additionalProperties" => %{"$dynamicRef" => "#meta"}, 34 | "default" => %{}, 35 | "propertyNames" => %{"format" => "regex"}, 36 | "type" => "object" 37 | }, 38 | "prefixItems" => %{"$ref" => "#/$defs/schemaArray"}, 39 | "properties" => %{ 40 | "additionalProperties" => %{"$dynamicRef" => "#meta"}, 41 | "default" => %{}, 42 | "type" => "object" 43 | }, 44 | "propertyNames" => %{"$dynamicRef" => "#meta"}, 45 | "then" => %{"$dynamicRef" => "#meta"} 46 | }, 47 | "title" => "Applicator vocabulary meta-schema", 48 | "type" => ["object", "boolean"] 49 | } 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/jsv/resolver/embedded/draft202012/meta/content.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.Embedded.Draft202012.Meta.Content do 2 | @moduledoc false 3 | 4 | @spec schema :: map 5 | def schema do 6 | %{ 7 | "$dynamicAnchor" => "meta", 8 | "$id" => "https://json-schema.org/draft/2020-12/meta/content", 9 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 10 | "properties" => %{ 11 | "contentEncoding" => %{"type" => "string"}, 12 | "contentMediaType" => %{"type" => "string"}, 13 | "contentSchema" => %{"$dynamicRef" => "#meta"} 14 | }, 15 | "title" => "Content vocabulary meta-schema", 16 | "type" => ["object", "boolean"] 17 | } 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/jsv/resolver/embedded/draft202012/meta/core.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.Embedded.Draft202012.Meta.Core do 2 | @moduledoc false 3 | 4 | @spec schema :: map 5 | def schema do 6 | %{ 7 | "$defs" => %{ 8 | "anchorString" => %{ 9 | "pattern" => "^[A-Za-z_][-A-Za-z0-9._]*$", 10 | "type" => "string" 11 | }, 12 | "uriReferenceString" => %{"format" => "uri-reference", "type" => "string"}, 13 | "uriString" => %{"format" => "uri", "type" => "string"} 14 | }, 15 | "$dynamicAnchor" => "meta", 16 | "$id" => "https://json-schema.org/draft/2020-12/meta/core", 17 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 18 | "properties" => %{ 19 | "$anchor" => %{"$ref" => "#/$defs/anchorString"}, 20 | "$comment" => %{"type" => "string"}, 21 | "$defs" => %{ 22 | "additionalProperties" => %{"$dynamicRef" => "#meta"}, 23 | "type" => "object" 24 | }, 25 | "$dynamicAnchor" => %{"$ref" => "#/$defs/anchorString"}, 26 | "$dynamicRef" => %{"$ref" => "#/$defs/uriReferenceString"}, 27 | "$id" => %{ 28 | "$comment" => "Non-empty fragments not allowed.", 29 | "$ref" => "#/$defs/uriReferenceString", 30 | "pattern" => "^[^#]*#?$" 31 | }, 32 | "$ref" => %{"$ref" => "#/$defs/uriReferenceString"}, 33 | "$schema" => %{"$ref" => "#/$defs/uriString"}, 34 | "$vocabulary" => %{ 35 | "additionalProperties" => %{"type" => "boolean"}, 36 | "propertyNames" => %{"$ref" => "#/$defs/uriString"}, 37 | "type" => "object" 38 | } 39 | }, 40 | "title" => "Core vocabulary meta-schema", 41 | "type" => ["object", "boolean"] 42 | } 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/jsv/resolver/embedded/draft202012/meta/format_annotation.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.Embedded.Draft202012.Meta.FormatAnnotation do 2 | @moduledoc false 3 | 4 | @spec schema :: map 5 | def schema do 6 | %{ 7 | "$dynamicAnchor" => "meta", 8 | "$id" => "https://json-schema.org/draft/2020-12/meta/format-annotation", 9 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 10 | "properties" => %{"format" => %{"type" => "string"}}, 11 | "title" => "Format vocabulary meta-schema for annotation results", 12 | "type" => ["object", "boolean"] 13 | } 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/jsv/resolver/embedded/draft202012/meta/meta_data.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.Embedded.Draft202012.Meta.MetaData do 2 | @moduledoc false 3 | 4 | @spec schema :: map 5 | def schema do 6 | %{ 7 | "$dynamicAnchor" => "meta", 8 | "$id" => "https://json-schema.org/draft/2020-12/meta/meta-data", 9 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 10 | "properties" => %{ 11 | "default" => true, 12 | "deprecated" => %{"default" => false, "type" => "boolean"}, 13 | "description" => %{"type" => "string"}, 14 | "examples" => %{"items" => true, "type" => "array"}, 15 | "readOnly" => %{"default" => false, "type" => "boolean"}, 16 | "title" => %{"type" => "string"}, 17 | "writeOnly" => %{"default" => false, "type" => "boolean"} 18 | }, 19 | "title" => "Meta-data vocabulary meta-schema", 20 | "type" => ["object", "boolean"] 21 | } 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/jsv/resolver/embedded/draft202012/meta/unevaluated.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.Embedded.Draft202012.Meta.Unevaluated do 2 | @moduledoc false 3 | 4 | @spec schema :: map 5 | def schema do 6 | %{ 7 | "$dynamicAnchor" => "meta", 8 | "$id" => "https://json-schema.org/draft/2020-12/meta/unevaluated", 9 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 10 | "properties" => %{ 11 | "unevaluatedItems" => %{"$dynamicRef" => "#meta"}, 12 | "unevaluatedProperties" => %{"$dynamicRef" => "#meta"} 13 | }, 14 | "title" => "Unevaluated applicator vocabulary meta-schema", 15 | "type" => ["object", "boolean"] 16 | } 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/jsv/resolver/internal.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.Internal do 2 | alias JSV.Helpers.StringExt 3 | 4 | @behaviour JSV.Resolver 5 | 6 | @moduledoc """ 7 | A `JSV.Resolver` implementation that resolves URIs pointing to the application 8 | code base or JSV code base. 9 | 10 | A custom resolver implementation should delegate `jsv:` prefixed URIs to this 11 | module to enable support of the internal resolutions features. 12 | 13 | ### Module based schemas 14 | 15 | This resolver will resolve `jsv:module:MODULE` URIs where `MODULE` is a string 16 | representation of an Elixir module. Modules pointed at with such references 17 | MUST export a `schema/0` function that returns a normalized (with binary keys 18 | and values) JSON schema. 19 | """ 20 | 21 | @uri_prefix "jsv:module:" 22 | 23 | @impl true 24 | def resolve(url, opts) 25 | 26 | def resolve(@uri_prefix <> module_string, _) do 27 | case StringExt.safe_string_to_existing_module(module_string) do 28 | {:ok, module} -> {:ok, module.schema()} 29 | {:error, reason} -> {:error, reason} 30 | end 31 | rescue 32 | e -> {:error, {:invalid_schema_module, e}} 33 | end 34 | 35 | def resolve(other, _) do 36 | {:error, {:unsupported, other}} 37 | end 38 | 39 | @doc """ 40 | Returns a JSV internal URI for the given module. 41 | 42 | ### Example 43 | 44 | iex> module_to_uri(Inspect.Opts) 45 | "jsv:module:Elixir.Inspect.Opts" 46 | """ 47 | @spec module_to_uri(module) :: binary 48 | def module_to_uri(module) when is_atom(module) do 49 | @uri_prefix <> Atom.to_string(module) 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/jsv/root.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Root do 2 | alias JSV.Validator 3 | 4 | @moduledoc """ 5 | Internal representation of a JSON schema built with `JSV.build/2`. 6 | 7 | The original schema, in its string-keys form, can be retrieved in the `:raw` 8 | key of the struct. 9 | """ 10 | 11 | defstruct validators: %{}, 12 | root_key: nil, 13 | raw: nil 14 | 15 | @type t :: %__MODULE__{raw: map | boolean | nil, validators: Validator.validators()} 16 | end 17 | -------------------------------------------------------------------------------- /lib/jsv/subschema.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Subschema do 2 | alias JSV.Vocabulary 3 | @enforce_keys [:validators, :schema_path] 4 | defstruct @enforce_keys 5 | 6 | @moduledoc """ 7 | Build result for a raw map schema. 8 | """ 9 | 10 | @type validators :: [{module, Vocabulary.collection()}] 11 | 12 | @type t :: %__MODULE__{validators: validators, schema_path: [String.t()]} 13 | end 14 | -------------------------------------------------------------------------------- /lib/jsv/validation_error.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.ValidationError do 2 | alias JSV.ErrorFormatter 3 | 4 | @moduledoc """ 5 | The data structure returned by `JSV.validate/3` when validation fails. 6 | """ 7 | 8 | @enforce_keys [:errors] 9 | defexception errors: [] 10 | 11 | @type t :: %__MODULE__{errors: [JSV.Validator.Error.t()]} 12 | 13 | @doc """ 14 | Wraps the given `JSV.Validator.Error` list into an `#{inspect(__MODULE__)}` 15 | exception. 16 | """ 17 | @spec of([JSV.Validator.Error.t()]) :: t 18 | def of(errors) when is_list(errors) do 19 | %__MODULE__{errors: errors} 20 | end 21 | 22 | @impl true 23 | def message(e) do 24 | %{valid: false, details: units} = ErrorFormatter.normalize_error(e) 25 | units_fmt = format_units(units, 0) 26 | top_message = "json schema validation failed" 27 | message = [top_message, "\n\n" | units_fmt] 28 | IO.iodata_to_binary(message) 29 | end 30 | 31 | defp format_units(units, indent) do 32 | Enum.map_intersperse(units, "\n\n", &format_unit(&1, indent)) 33 | end 34 | 35 | defp format_unit(unit, indent) do 36 | %{ 37 | valid: valid?, 38 | schemaLocation: schema_location, 39 | instanceLocation: instance_location 40 | } = unit 41 | 42 | show_valid = 43 | case valid? do 44 | true -> [indent(indent), "valid: true", "\n"] 45 | false -> [] 46 | end 47 | 48 | errors_annots = 49 | case unit do 50 | %{errors: list} -> 51 | annots = Enum.map_intersperse(list, "\n", &format_annot(&1, indent + 1)) 52 | [indent(indent), "errors:\n" | annots] 53 | 54 | _ -> 55 | [] 56 | end 57 | 58 | [ 59 | [indent(indent), "at: ", inspect(instance_location), "\n"], 60 | [indent(indent), "by: ", inspect(schema_location), "\n"], 61 | show_valid, 62 | errors_annots 63 | ] 64 | end 65 | 66 | defp format_annot(err, indent) do 67 | case err do 68 | %{details: sub_units} -> 69 | [ 70 | "#{indent(indent)}- (", 71 | Atom.to_string(err.kind), 72 | ") ", 73 | err.message, 74 | "\n\n", 75 | format_units(sub_units, indent + 1) 76 | ] 77 | 78 | _ -> 79 | ["#{indent(indent)}- (", Atom.to_string(err.kind), ") ", err.message] 80 | end 81 | end 82 | 83 | defp indent(n) when n > 1 do 84 | [indent(1), indent(n - 1)] 85 | end 86 | 87 | defp indent(1) do 88 | " " 89 | end 90 | 91 | defp indent(0) do 92 | [] 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /lib/jsv/validator/error.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Validator.Error do 2 | @moduledoc """ 3 | Representation of an error encountered during validation. 4 | """ 5 | 6 | @enforce_keys [:kind, :data, :args, :formatter, :data_path, :eval_path, :schema_path] 7 | defstruct @enforce_keys 8 | 9 | @opaque t :: %__MODULE__{} 10 | end 11 | -------------------------------------------------------------------------------- /lib/jsv/vocabulary/cast.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Vocabulary.Cast do 2 | alias JSV.Helpers.StringExt 3 | alias JSV.Validator 4 | use JSV.Vocabulary, priority: 900 5 | 6 | @moduledoc false 7 | 8 | @impl true 9 | def init_validators([]) do 10 | %{} 11 | end 12 | 13 | take_keyword :"jsv-cast", [module_str, arg], vds, builder, _ do 14 | module = unwrap_ok(StringExt.safe_string_to_existing_module(module_str)) 15 | {Map.put(vds, :"jsv-cast", {module, arg}), builder} 16 | end 17 | 18 | ignore_any_keyword() 19 | 20 | @impl true 21 | def finalize_validators(map) do 22 | case map_size(map) do 23 | 0 -> :ignore 24 | _ -> map 25 | end 26 | end 27 | 28 | @impl true 29 | 30 | def validate(data, %{"jsv-cast": {module, arg}}, vctx) do 31 | cond do 32 | Validator.error?(vctx) -> 33 | {:ok, data, vctx} 34 | 35 | vctx.opts[:cast] -> 36 | call_cast(module, arg, data, vctx) 37 | 38 | :other -> 39 | {:ok, data, vctx} 40 | end 41 | end 42 | 43 | defp call_cast(module, arg, data, vctx) do 44 | case module.__jsv__(arg, data) do 45 | {:ok, new_data} -> 46 | {:ok, new_data, vctx} 47 | 48 | {:error, reason} -> 49 | {:error, 50 | JSV.Validator.__with_error__(__MODULE__, vctx, :"jsv-cast", data, module: module, reason: reason, arg: arg)} 51 | end 52 | rescue 53 | e in [UndefinedFunctionError, FunctionClauseError] -> 54 | case e do 55 | %{module: ^module, function: :__jsv__} -> 56 | {:error, 57 | JSV.Validator.__with_error__(__MODULE__, vctx, :"bad-cast", data, module: module, reason: e, arg: arg)} 58 | 59 | _ -> 60 | reraise e, __STACKTRACE__ 61 | end 62 | end 63 | 64 | @impl true 65 | def format_error(:"jsv-cast", args, data) do 66 | if function_exported?(args.module, :format_error, 3) do 67 | case args.module.format_error(args.arg, args.reason, data) do 68 | message when is_binary(message) -> {:cast, message} 69 | other -> other 70 | end 71 | else 72 | {:cast, "cast failed"} 73 | end 74 | end 75 | 76 | def format_error(:"bad-cast", _args, _data) do 77 | {:cast, "invalid cast"} 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /lib/jsv/vocabulary/v202012/content.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Vocabulary.V202012.Content do 2 | use JSV.Vocabulary, priority: 300 3 | 4 | @moduledoc """ 5 | Placeholder implementation for the 6 | `https://json-schema.org/draft/2020-12/vocab/content` vocabulary. No 7 | validation is performed. 8 | """ 9 | 10 | @impl true 11 | def init_validators(_) do 12 | [] 13 | end 14 | 15 | @impl true 16 | consume_keyword :contentMediaType 17 | consume_keyword :contentEncoding 18 | consume_keyword :contentSchema 19 | ignore_any_keyword() 20 | 21 | @impl true 22 | def finalize_validators([]) do 23 | :ignore 24 | end 25 | 26 | @impl true 27 | @spec validate(term, term, term) :: no_return() 28 | def validate(_data, _validators, _context) do 29 | raise "should not be called" 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/jsv/vocabulary/v202012/meta_data.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Vocabulary.V202012.MetaData do 2 | use JSV.Vocabulary, priority: 300 3 | 4 | @moduledoc """ 5 | Implementation for the `https://json-schema.org/draft/2020-12/vocab/meta-data` 6 | vocabulary. 7 | """ 8 | @impl true 9 | def init_validators(_) do 10 | [] 11 | end 12 | 13 | @impl true 14 | consume_keyword :deprecated 15 | consume_keyword :description 16 | consume_keyword :default 17 | consume_keyword :title 18 | consume_keyword :readOnly 19 | consume_keyword :writeOnly 20 | consume_keyword :examples 21 | 22 | ignore_any_keyword() 23 | 24 | @impl true 25 | def finalize_validators(_) do 26 | :ignore 27 | end 28 | 29 | @impl true 30 | @spec validate(term, term, term) :: no_return() 31 | def validate(_data, _validators, _context) do 32 | raise "should not be called" 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/jsv/vocabulary/v7/content.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Vocabulary.V7.Content do 2 | alias JSV.Vocabulary.V202012.Content, as: Fallback 3 | use JSV.Vocabulary, priority: 300 4 | 5 | @moduledoc """ 6 | Implementation of the content vocabulary with draft 7 sepecifiticies. No 7 | validation is performed. 8 | """ 9 | 10 | @impl true 11 | defdelegate init_validators(opts), to: Fallback 12 | 13 | @impl true 14 | ignore_keyword(:contentSchema) 15 | 16 | defdelegate handle_keyword(kw_tuple, acc, builder, raw_schema), to: Fallback 17 | 18 | @impl true 19 | defdelegate finalize_validators(acc), to: Fallback 20 | 21 | @impl true 22 | @spec validate(term, term, term) :: no_return() 23 | def validate(_data, _validators, _context) do 24 | raise "should not be called" 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/jsv/vocabulary/v7/core.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Vocabulary.V7.Core do 2 | alias JSV.Ref 3 | alias JSV.Vocabulary.V202012.Core, as: Fallback 4 | use JSV.Vocabulary, priority: 100 5 | 6 | @moduledoc """ 7 | Implementation of the core vocabulary with draft 7 sepecifiticies. 8 | """ 9 | 10 | @impl true 11 | defdelegate init_validators(opts), to: Fallback 12 | 13 | @impl true 14 | take_keyword :"$ref", raw_ref, _acc, builder, raw_schema do 15 | ref_relative_to_ns = 16 | case {raw_schema, builder} do 17 | # The ref is not relative to the current $id if defined at the same 18 | # level and there is a parent $id. 19 | # 20 | # Parent cannot be :root because a ref cannot target :root, it must be a 21 | # defined $id. 22 | {%{"$id" => _}, %{ns: _, parent_ns: parent}} when parent != :root -> 23 | parent 24 | 25 | # Otherwise take the $id at the same level or higher 26 | {_, %{ns: current_ns}} -> 27 | current_ns 28 | end 29 | 30 | ref = unwrap_ok(Ref.parse(raw_ref, ref_relative_to_ns)) 31 | Fallback.put_ref(ref, :"$ref", [], builder) 32 | end 33 | 34 | consume_keyword :definitions 35 | 36 | # $ref overrides any other keyword in Draft7 37 | def handle_keyword(_kw_tuple, acc, builder, raw_schema) when is_map_key(raw_schema, "$ref") do 38 | {acc, builder} 39 | end 40 | 41 | defdelegate handle_keyword(kw_tuple, acc, builder, raw_schema), to: Fallback 42 | 43 | @impl true 44 | defdelegate finalize_validators(acc), to: Fallback 45 | 46 | @impl true 47 | defdelegate validate(data, vds, vctx), to: Fallback 48 | end 49 | -------------------------------------------------------------------------------- /lib/jsv/vocabulary/v7/format.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Vocabulary.V7.Format do 2 | alias JSV.Vocabulary.V202012.Format, as: Fallback 3 | use JSV.Vocabulary, priority: 300 4 | 5 | @moduledoc """ 6 | Implementation of the format vocabulary with draft 7 sepecifiticies. 7 | """ 8 | 9 | defdelegate init_validators(opts), to: Fallback 10 | 11 | defdelegate handle_keyword(kw_tuple, acc, builder, raw_schema), to: Fallback 12 | 13 | defdelegate finalize_validators(acc), to: Fallback 14 | 15 | defdelegate validate(data, vds, vctx), to: Fallback 16 | end 17 | -------------------------------------------------------------------------------- /lib/jsv/vocabulary/v7/meta_data.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Vocabulary.V7.MetaData do 2 | alias JSV.Vocabulary.V202012.MetaData, as: Fallback 3 | use JSV.Vocabulary, priority: 300 4 | 5 | @moduledoc """ 6 | Implementation of the meta-data vocabulary with draft 7 sepecifiticies. 7 | """ 8 | 9 | @impl true 10 | defdelegate init_validators(opts), to: Fallback 11 | 12 | @impl true 13 | defdelegate handle_keyword(kw_tuple, acc, builder, raw_schema), to: Fallback 14 | 15 | @impl true 16 | defdelegate finalize_validators(acc), to: Fallback 17 | 18 | @impl true 19 | @spec validate(term, term, term) :: no_return() 20 | def validate(_data, _validators, _context) do 21 | raise "should not be called" 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/jsv/vocabulary/v7/validation.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.Vocabulary.V7.Validation do 2 | alias JSV.Vocabulary.V202012.Validation, as: Fallback 3 | use JSV.Vocabulary, priority: 300 4 | 5 | @moduledoc """ 6 | Implementation of the validation vocabulary with draft 7 sepecifiticies. 7 | """ 8 | 9 | defdelegate init_validators(opts), to: Fallback 10 | 11 | defdelegate handle_keyword(kw_tuple, acc, builder, raw_schema), to: Fallback 12 | 13 | defdelegate finalize_validators(acc), to: Fallback 14 | 15 | defdelegate validate(data, vds, vctx), to: Fallback 16 | end 17 | -------------------------------------------------------------------------------- /priv/grammars/json-pointer.abnf: -------------------------------------------------------------------------------- 1 | json-pointer = *( "/" reference-token ) 2 | reference-token = *( unescaped / escaped ) 3 | unescaped = %x00-2E / %x30-7D / %x7F-10FFFF 4 | ; %x2F ('/') and %x7E ('~') are excluded from 'unescaped' 5 | escaped = "~" ( "0" / "1" ) 6 | ; representing '~' and '/', respectively 7 | 8 | relative-json-pointer = (non-negative-integer "#") / (non-negative-integer json-pointer) 9 | non-negative-integer = %x30 / %x31-39 *( %x30-39 ) 10 | ; "0", or digits without a leading "0" -------------------------------------------------------------------------------- /priv/grammars/uri-template.abnf: -------------------------------------------------------------------------------- 1 | ALPHA = %x41-5A / %x61-7A ; A-Z / a-z 2 | DIGIT = %x30-39 ; 0-9 3 | HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" 4 | ; case-insensitive 5 | 6 | pct-encoded = "%" HEXDIG HEXDIG 7 | unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 8 | reserved = gen-delims / sub-delims 9 | gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" 10 | sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 11 | / "*" / "+" / "," / ";" / "=" 12 | 13 | ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF 14 | / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD 15 | / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD 16 | / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD 17 | / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD 18 | / %xD0000-DFFFD / %xE1000-EFFFD 19 | 20 | iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD 21 | 22 | URI-Template = *( literals / expression ) 23 | 24 | literals = %x21 / %x23-24 / %x26 / %x28-3B / %x3D / %x3F-5B 25 | / %x5D / %x5F / %x61-7A / %x7E / ucschar / iprivate 26 | / pct-encoded 27 | ; any Unicode character except: CTL, SP, 28 | ; DQUOTE, "'", "%" (aside from pct-encoded), 29 | ; "<", ">", "\", "^", "`", "{", "|", "}" 30 | 31 | expression = "{" [ operator ] variable-list "}" 32 | operator = op-level2 / op-level3 / op-reserve 33 | op-level2 = "+" / "#" 34 | op-level3 = "." / "/" / ";" / "?" / "&" 35 | op-reserve = "=" / "," / "!" / "@" / "|" 36 | 37 | variable-list = varspec *( "," varspec ) 38 | varspec = varname [ modifier-level4 ] 39 | varname = varchar *( ["."] varchar ) 40 | varchar = ALPHA / DIGIT / "_" / pct-encoded 41 | 42 | modifier-level4 = prefix / explode 43 | 44 | prefix = ":" max-length 45 | max-length = %x31-39 0*3DIGIT ; positive integer < 10000 46 | 47 | explode = "*" -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/defs_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.DefsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/defs.json 10 | """ 11 | 12 | describe "validate definition against metaschema" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "https://json-schema.org/draft/2020-12/schema", 16 | "$ref": "https://json-schema.org/draft/2020-12/schema" 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "valid definition schema", x do 24 | data = %{"$defs" => %{"foo" => %{"type" => "integer"}}} 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "invalid definition schema", x do 30 | data = %{"$defs" => %{"foo" => %{"type" => 1}}} 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/exclusive_maximum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.ExclusiveMaximumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/exclusiveMaximum.json 10 | """ 11 | 12 | describe "exclusiveMaximum validation" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "https://json-schema.org/draft/2020-12/schema", 16 | exclusiveMaximum: 3.0 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "below the exclusiveMaximum is valid", x do 24 | data = 2.2 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "boundary point is invalid", x do 30 | data = 3.0 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | 35 | test "above the exclusiveMaximum is invalid", x do 36 | data = 3.5 37 | expected_valid = false 38 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 39 | end 40 | 41 | test "ignores non-numbers", x do 42 | data = "x" 43 | expected_valid = true 44 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/exclusive_minimum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.ExclusiveMinimumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/exclusiveMinimum.json 10 | """ 11 | 12 | describe "exclusiveMinimum validation" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "https://json-schema.org/draft/2020-12/schema", 16 | exclusiveMinimum: 1.1 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "above the exclusiveMinimum is valid", x do 24 | data = 1.2 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "boundary point is invalid", x do 30 | data = 1.1 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | 35 | test "below the exclusiveMinimum is invalid", x do 36 | data = 0.6 37 | expected_valid = false 38 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 39 | end 40 | 41 | test "ignores non-numbers", x do 42 | data = "x" 43 | expected_valid = true 44 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/infinite_loop_detection_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.InfiniteLoopDetectionTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/infinite-loop-detection.json 10 | """ 11 | 12 | describe "evaluating the same schema location against the same data location twice is not a sign of an infinite loop" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "https://json-schema.org/draft/2020-12/schema", 16 | "$defs": %{int: %JSV.Schema{type: "integer"}}, 17 | allOf: [ 18 | %JSV.Schema{properties: %{foo: %JSV.Schema{"$ref": "#/$defs/int"}}}, 19 | %JSV.Schema{additionalProperties: %JSV.Schema{"$ref": "#/$defs/int"}} 20 | ] 21 | } 22 | 23 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 24 | {:ok, json_schema: json_schema, schema: schema} 25 | end 26 | 27 | test "passing case", x do 28 | data = %{"foo" => 1} 29 | expected_valid = true 30 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 31 | end 32 | 33 | test "failing case", x do 34 | data = %{"foo" => "a string"} 35 | expected_valid = false 36 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/min_items_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.MinItemsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/minItems.json 10 | """ 11 | 12 | describe "minItems validation" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "https://json-schema.org/draft/2020-12/schema", 16 | minItems: 1 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "longer is valid", x do 24 | data = [1, 2] 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "exact length is valid", x do 30 | data = [1] 31 | expected_valid = true 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | 35 | test "too short is invalid", x do 36 | data = [] 37 | expected_valid = false 38 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 39 | end 40 | 41 | test "ignores non-arrays", x do 42 | data = "" 43 | expected_valid = true 44 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 45 | end 46 | end 47 | 48 | describe "minItems validation with a decimal" do 49 | setup do 50 | json_schema = %JSV.Schema{ 51 | "$schema": "https://json-schema.org/draft/2020-12/schema", 52 | minItems: 1.0 53 | } 54 | 55 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 56 | {:ok, json_schema: json_schema, schema: schema} 57 | end 58 | 59 | test "longer is valid", x do 60 | data = [1, 2] 61 | expected_valid = true 62 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 63 | end 64 | 65 | test "too short is invalid", x do 66 | data = [] 67 | expected_valid = false 68 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/optional/anchor_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.Optional.AnchorTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/anchor.json 10 | """ 11 | 12 | describe "$anchor inside an enum is not a real identifier" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "https://json-schema.org/draft/2020-12/schema", 16 | "$defs": %{ 17 | anchor_in_enum: %JSV.Schema{ 18 | enum: [%JSV.Schema{"$anchor": "my_anchor", type: "null"}] 19 | }, 20 | real_identifier_in_schema: %JSV.Schema{ 21 | "$anchor": "my_anchor", 22 | type: "string" 23 | }, 24 | zzz_anchor_in_const: %{ 25 | const: %JSV.Schema{"$anchor": "my_anchor", type: "null"} 26 | } 27 | }, 28 | anyOf: [ 29 | %JSV.Schema{"$ref": "#/$defs/anchor_in_enum"}, 30 | %JSV.Schema{"$ref": "#my_anchor"} 31 | ] 32 | } 33 | 34 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 35 | {:ok, json_schema: json_schema, schema: schema} 36 | end 37 | 38 | test "exact match to enum, and type matches", x do 39 | data = %{"$anchor" => "my_anchor", "type" => "null"} 40 | expected_valid = true 41 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 42 | end 43 | 44 | test "in implementations that strip $anchor, this may match either $def", x do 45 | data = %{"type" => "null"} 46 | expected_valid = false 47 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 48 | end 49 | 50 | test "match $ref to $anchor", x do 51 | data = "a string to match #/$defs/anchor_in_enum" 52 | expected_valid = true 53 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 54 | end 55 | 56 | test "no match on enum or $ref to $anchor", x do 57 | data = 1 58 | expected_valid = false 59 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/optional/dynamic_ref_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.Optional.DynamicRefTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/dynamicRef.json 10 | """ 11 | 12 | describe "$dynamicRef skips over intermediate resources - pointer reference across resource boundary" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "https://json-schema.org/draft/2020-12/schema", 16 | "$id": "https://test.json-schema.org/dynamic-ref-skips-intermediate-resource/optional/main", 17 | "$defs": %{ 18 | bar: %JSV.Schema{ 19 | "$id": "bar", 20 | "$defs": %{ 21 | content: %JSV.Schema{"$dynamicAnchor": "content", type: "string"}, 22 | item: %JSV.Schema{ 23 | "$id": "item", 24 | "$defs": %{ 25 | defaultContent: %JSV.Schema{ 26 | "$dynamicAnchor": "content", 27 | type: "integer" 28 | } 29 | }, 30 | type: "object", 31 | properties: %{content: %JSV.Schema{"$dynamicRef": "#content"}} 32 | } 33 | }, 34 | type: "array", 35 | items: %JSV.Schema{"$ref": "item"} 36 | } 37 | }, 38 | type: "object", 39 | properties: %{"bar-item": %JSV.Schema{"$ref": "bar#/$defs/item"}} 40 | } 41 | 42 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 43 | {:ok, json_schema: json_schema, schema: schema} 44 | end 45 | 46 | test "integer property passes", x do 47 | data = %{"bar-item" => %{"content" => 42}} 48 | expected_valid = true 49 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 50 | end 51 | 52 | test "string property fails", x do 53 | data = %{"bar-item" => %{"content" => "value"}} 54 | expected_valid = false 55 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/optional/format_assertion_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.Optional.FormatAssertionTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format-assertion.json 10 | """ 11 | 12 | describe "schema that uses custom metaschema with format-assertion: false" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "http://localhost:1234/draft2020-12/format-assertion-false.json", 16 | "$id": "https://schema/using/format-assertion/false", 17 | format: "ipv4" 18 | } 19 | 20 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 21 | {:ok, json_schema: json_schema, schema: schema} 22 | end 23 | 24 | test "format-assertion: false: valid string", x do 25 | data = "127.0.0.1" 26 | expected_valid = true 27 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 28 | end 29 | 30 | test "format-assertion: false: invalid string", x do 31 | data = "not-an-ipv4" 32 | expected_valid = false 33 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 34 | end 35 | end 36 | 37 | describe "schema that uses custom metaschema with format-assertion: true" do 38 | setup do 39 | json_schema = %JSV.Schema{ 40 | "$schema": "http://localhost:1234/draft2020-12/format-assertion-true.json", 41 | "$id": "https://schema/using/format-assertion/true", 42 | format: "ipv4" 43 | } 44 | 45 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 46 | {:ok, json_schema: json_schema, schema: schema} 47 | end 48 | 49 | test "format-assertion: true: valid string", x do 50 | data = "127.0.0.1" 51 | expected_valid = true 52 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 53 | end 54 | 55 | test "format-assertion: true: invalid string", x do 56 | data = "not-an-ipv4" 57 | expected_valid = false 58 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/optional/no_schema_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.Optional.NoSchemaTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/no-schema.json 10 | """ 11 | 12 | describe "validation without $schema" do 13 | setup do 14 | json_schema = %JSV.Schema{minLength: 2} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "a 3-character string is valid", x do 20 | data = "foo" 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "a 1-character string is not valid", x do 26 | data = "a" 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "a non-string is valid", x do 32 | data = 5 33 | expected_valid = true 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/atom_keys/unknown_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.AtomKeys.UnknownTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/unknown.json 10 | """ 11 | 12 | describe "unknown format" do 13 | setup do 14 | json_schema = %JSV.Schema{ 15 | "$schema": "https://json-schema.org/draft/2020-12/schema", 16 | format: "unknown" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "unknown formats ignore integers", x do 29 | data = 12 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | 34 | test "unknown formats ignore floats", x do 35 | data = 13.7 36 | expected_valid = true 37 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 38 | end 39 | 40 | test "unknown formats ignore objects", x do 41 | data = %{} 42 | expected_valid = true 43 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 44 | end 45 | 46 | test "unknown formats ignore arrays", x do 47 | data = [] 48 | expected_valid = true 49 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 50 | end 51 | 52 | test "unknown formats ignore booleans", x do 53 | data = false 54 | expected_valid = true 55 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 56 | end 57 | 58 | test "unknown formats ignore nulls", x do 59 | data = nil 60 | expected_valid = true 61 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 62 | end 63 | 64 | test "unknown formats ignore strings", x do 65 | data = "string" 66 | expected_valid = true 67 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/defs_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.DefsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/defs.json 10 | """ 11 | 12 | describe "validate definition against metaschema" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "$ref" => "https://json-schema.org/draft/2020-12/schema" 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "valid definition schema", x do 24 | data = %{"$defs" => %{"foo" => %{"type" => "integer"}}} 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "invalid definition schema", x do 30 | data = %{"$defs" => %{"foo" => %{"type" => 1}}} 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/exclusive_maximum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.ExclusiveMaximumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/exclusiveMaximum.json 10 | """ 11 | 12 | describe "exclusiveMaximum validation" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "exclusiveMaximum" => 3.0 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "below the exclusiveMaximum is valid", x do 24 | data = 2.2 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "boundary point is invalid", x do 30 | data = 3.0 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | 35 | test "above the exclusiveMaximum is invalid", x do 36 | data = 3.5 37 | expected_valid = false 38 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 39 | end 40 | 41 | test "ignores non-numbers", x do 42 | data = "x" 43 | expected_valid = true 44 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/exclusive_minimum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.ExclusiveMinimumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/exclusiveMinimum.json 10 | """ 11 | 12 | describe "exclusiveMinimum validation" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "exclusiveMinimum" => 1.1 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "above the exclusiveMinimum is valid", x do 24 | data = 1.2 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "boundary point is invalid", x do 30 | data = 1.1 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | 35 | test "below the exclusiveMinimum is invalid", x do 36 | data = 0.6 37 | expected_valid = false 38 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 39 | end 40 | 41 | test "ignores non-numbers", x do 42 | data = "x" 43 | expected_valid = true 44 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/infinite_loop_detection_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.InfiniteLoopDetectionTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/infinite-loop-detection.json 10 | """ 11 | 12 | describe "evaluating the same schema location against the same data location twice is not a sign of an infinite loop" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "$defs" => %{"int" => %{"type" => "integer"}}, 17 | "allOf" => [ 18 | %{"properties" => %{"foo" => %{"$ref" => "#/$defs/int"}}}, 19 | %{"additionalProperties" => %{"$ref" => "#/$defs/int"}} 20 | ] 21 | } 22 | 23 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 24 | {:ok, json_schema: json_schema, schema: schema} 25 | end 26 | 27 | test "passing case", x do 28 | data = %{"foo" => 1} 29 | expected_valid = true 30 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 31 | end 32 | 33 | test "failing case", x do 34 | data = %{"foo" => "a string"} 35 | expected_valid = false 36 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/max_items_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.MaxItemsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/maxItems.json 10 | """ 11 | 12 | describe "maxItems validation" do 13 | setup do 14 | json_schema = %{"$schema" => "https://json-schema.org/draft/2020-12/schema", "maxItems" => 2} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "shorter is valid", x do 20 | data = [1] 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "exact length is valid", x do 26 | data = [1, 2] 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "too long is invalid", x do 32 | data = [1, 2, 3] 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-arrays", x do 38 | data = "foobar" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | 44 | describe "maxItems validation with a decimal" do 45 | setup do 46 | json_schema = %{ 47 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 48 | "maxItems" => 2.0 49 | } 50 | 51 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 52 | {:ok, json_schema: json_schema, schema: schema} 53 | end 54 | 55 | test "shorter is valid", x do 56 | data = [1] 57 | expected_valid = true 58 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 59 | end 60 | 61 | test "too long is invalid", x do 62 | data = [1, 2, 3] 63 | expected_valid = false 64 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/min_items_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.MinItemsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/minItems.json 10 | """ 11 | 12 | describe "minItems validation" do 13 | setup do 14 | json_schema = %{"$schema" => "https://json-schema.org/draft/2020-12/schema", "minItems" => 1} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "longer is valid", x do 20 | data = [1, 2] 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "exact length is valid", x do 26 | data = [1] 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "too short is invalid", x do 32 | data = [] 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-arrays", x do 38 | data = "" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | 44 | describe "minItems validation with a decimal" do 45 | setup do 46 | json_schema = %{ 47 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 48 | "minItems" => 1.0 49 | } 50 | 51 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 52 | {:ok, json_schema: json_schema, schema: schema} 53 | end 54 | 55 | test "longer is valid", x do 56 | data = [1, 2] 57 | expected_valid = true 58 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 59 | end 60 | 61 | test "too short is invalid", x do 62 | data = [] 63 | expected_valid = false 64 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/optional/anchor_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.Optional.AnchorTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/anchor.json 10 | """ 11 | 12 | describe "$anchor inside an enum is not a real identifier" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "$defs" => %{ 17 | "anchor_in_enum" => %{ 18 | "enum" => [%{"$anchor" => "my_anchor", "type" => "null"}] 19 | }, 20 | "real_identifier_in_schema" => %{ 21 | "$anchor" => "my_anchor", 22 | "type" => "string" 23 | }, 24 | "zzz_anchor_in_const" => %{ 25 | "const" => %{"$anchor" => "my_anchor", "type" => "null"} 26 | } 27 | }, 28 | "anyOf" => [%{"$ref" => "#/$defs/anchor_in_enum"}, %{"$ref" => "#my_anchor"}] 29 | } 30 | 31 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 32 | {:ok, json_schema: json_schema, schema: schema} 33 | end 34 | 35 | test "exact match to enum, and type matches", x do 36 | data = %{"$anchor" => "my_anchor", "type" => "null"} 37 | expected_valid = true 38 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 39 | end 40 | 41 | test "in implementations that strip $anchor, this may match either $def", x do 42 | data = %{"type" => "null"} 43 | expected_valid = false 44 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 45 | end 46 | 47 | test "match $ref to $anchor", x do 48 | data = "a string to match #/$defs/anchor_in_enum" 49 | expected_valid = true 50 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 51 | end 52 | 53 | test "no match on enum or $ref to $anchor", x do 54 | data = 1 55 | expected_valid = false 56 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/optional/dynamic_ref_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.Optional.DynamicRefTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/dynamicRef.json 10 | """ 11 | 12 | describe "$dynamicRef skips over intermediate resources - pointer reference across resource boundary" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "$id" => "https://test.json-schema.org/dynamic-ref-skips-intermediate-resource/optional/main", 17 | "$defs" => %{ 18 | "bar" => %{ 19 | "$id" => "bar", 20 | "$defs" => %{ 21 | "content" => %{"$dynamicAnchor" => "content", "type" => "string"}, 22 | "item" => %{ 23 | "$id" => "item", 24 | "$defs" => %{ 25 | "defaultContent" => %{ 26 | "$dynamicAnchor" => "content", 27 | "type" => "integer" 28 | } 29 | }, 30 | "type" => "object", 31 | "properties" => %{"content" => %{"$dynamicRef" => "#content"}} 32 | } 33 | }, 34 | "type" => "array", 35 | "items" => %{"$ref" => "item"} 36 | } 37 | }, 38 | "type" => "object", 39 | "properties" => %{"bar-item" => %{"$ref" => "bar#/$defs/item"}} 40 | } 41 | 42 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 43 | {:ok, json_schema: json_schema, schema: schema} 44 | end 45 | 46 | test "integer property passes", x do 47 | data = %{"bar-item" => %{"content" => 42}} 48 | expected_valid = true 49 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 50 | end 51 | 52 | test "string property fails", x do 53 | data = %{"bar-item" => %{"content" => "value"}} 54 | expected_valid = false 55 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/optional/format_assertion_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.Optional.FormatAssertionTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format-assertion.json 10 | """ 11 | 12 | describe "schema that uses custom metaschema with format-assertion: false" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "http://localhost:1234/draft2020-12/format-assertion-false.json", 16 | "$id" => "https://schema/using/format-assertion/false", 17 | "format" => "ipv4" 18 | } 19 | 20 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 21 | {:ok, json_schema: json_schema, schema: schema} 22 | end 23 | 24 | test "format-assertion: false: valid string", x do 25 | data = "127.0.0.1" 26 | expected_valid = true 27 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 28 | end 29 | 30 | test "format-assertion: false: invalid string", x do 31 | data = "not-an-ipv4" 32 | expected_valid = false 33 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 34 | end 35 | end 36 | 37 | describe "schema that uses custom metaschema with format-assertion: true" do 38 | setup do 39 | json_schema = %{ 40 | "$schema" => "http://localhost:1234/draft2020-12/format-assertion-true.json", 41 | "$id" => "https://schema/using/format-assertion/true", 42 | "format" => "ipv4" 43 | } 44 | 45 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 46 | {:ok, json_schema: json_schema, schema: schema} 47 | end 48 | 49 | test "format-assertion: true: valid string", x do 50 | data = "127.0.0.1" 51 | expected_valid = true 52 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 53 | end 54 | 55 | test "format-assertion: true: invalid string", x do 56 | data = "not-an-ipv4" 57 | expected_valid = false 58 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/optional/id_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.Optional.IdTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/id.json 10 | """ 11 | 12 | describe "$id inside an enum is not a real identifier" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "$defs" => %{ 17 | "id_in_enum" => %{ 18 | "enum" => [ 19 | %{ 20 | "$id" => "https://localhost:1234/draft2020-12/id/my_identifier.json", 21 | "type" => "null" 22 | } 23 | ] 24 | }, 25 | "real_id_in_schema" => %{ 26 | "$id" => "https://localhost:1234/draft2020-12/id/my_identifier.json", 27 | "type" => "string" 28 | }, 29 | "zzz_id_in_const" => %{ 30 | "const" => %{ 31 | "$id" => "https://localhost:1234/draft2020-12/id/my_identifier.json", 32 | "type" => "null" 33 | } 34 | } 35 | }, 36 | "anyOf" => [ 37 | %{"$ref" => "#/$defs/id_in_enum"}, 38 | %{"$ref" => "https://localhost:1234/draft2020-12/id/my_identifier.json"} 39 | ] 40 | } 41 | 42 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 43 | {:ok, json_schema: json_schema, schema: schema} 44 | end 45 | 46 | test "exact match to enum, and type matches", x do 47 | data = %{ 48 | "$id" => "https://localhost:1234/draft2020-12/id/my_identifier.json", 49 | "type" => "null" 50 | } 51 | 52 | expected_valid = true 53 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 54 | end 55 | 56 | test "match $ref to $id", x do 57 | data = "a string to match #/$defs/id_in_enum" 58 | expected_valid = true 59 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 60 | end 61 | 62 | test "no match on enum or $ref to $id", x do 63 | data = 1 64 | expected_valid = false 65 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/optional/no_schema_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.Optional.NoSchemaTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/no-schema.json 10 | """ 11 | 12 | describe "validation without $schema" do 13 | setup do 14 | json_schema = %{"minLength" => 2} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "a 3-character string is valid", x do 20 | data = "foo" 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "a 1-character string is not valid", x do 26 | data = "a" 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "a non-string is valid", x do 32 | data = 5 33 | expected_valid = true 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/binary_keys/unknown_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.BinaryKeys.UnknownTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/unknown.json 10 | """ 11 | 12 | describe "unknown format" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "unknown" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "unknown formats ignore integers", x do 29 | data = 12 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | 34 | test "unknown formats ignore floats", x do 35 | data = 13.7 36 | expected_valid = true 37 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 38 | end 39 | 40 | test "unknown formats ignore objects", x do 41 | data = %{} 42 | expected_valid = true 43 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 44 | end 45 | 46 | test "unknown formats ignore arrays", x do 47 | data = [] 48 | expected_valid = true 49 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 50 | end 51 | 52 | test "unknown formats ignore booleans", x do 53 | data = false 54 | expected_valid = true 55 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 56 | end 57 | 58 | test "unknown formats ignore nulls", x do 59 | data = nil 60 | expected_valid = true 61 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 62 | end 63 | 64 | test "unknown formats ignore strings", x do 65 | data = "string" 66 | expected_valid = true 67 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/any_of_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.AnyOfTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/anyOf.json 10 | """ 11 | 12 | describe "anyOf" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "anyOf" => [%{"type" => "integer"}, %{"minimum" => 2}] 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "second anyOf valid", x do 24 | data = Decimal.new("2.5") 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "neither anyOf valid", x do 30 | data = Decimal.new("1.5") 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/date_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.DateTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/date.json 10 | """ 11 | 12 | describe "validation of date strings" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "date" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/date_time_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.DateTimeTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/date-time.json 10 | """ 11 | 12 | describe "validation of date-time strings" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "date-time" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/duration_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.DurationTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/duration.json 10 | """ 11 | 12 | if JsonSchemaSuite.version_check("~> 1.17") do 13 | describe "validation of duration strings" do 14 | setup do 15 | json_schema = %{ 16 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 17 | "format" => "duration" 18 | } 19 | 20 | schema = 21 | JsonSchemaSuite.build_schema(json_schema, 22 | default_meta: "https://json-schema.org/draft/2020-12/schema", 23 | formats: true 24 | ) 25 | 26 | {:ok, json_schema: json_schema, schema: schema} 27 | end 28 | 29 | test "all string formats ignore floats", x do 30 | data = Decimal.new("13.7") 31 | expected_valid = true 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/email_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.EmailTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/email.json 10 | """ 11 | 12 | describe "validation of e-mail addresses" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "email" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/exclusive_maximum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.ExclusiveMaximumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/exclusiveMaximum.json 10 | """ 11 | 12 | describe "exclusiveMaximum validation" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "exclusiveMaximum" => 3.0 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "below the exclusiveMaximum is valid", x do 24 | data = Decimal.new("2.2") 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "boundary point is invalid", x do 30 | data = Decimal.new("3.0") 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | 35 | test "above the exclusiveMaximum is invalid", x do 36 | data = Decimal.new("3.5") 37 | expected_valid = false 38 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/exclusive_minimum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.ExclusiveMinimumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/exclusiveMinimum.json 10 | """ 11 | 12 | describe "exclusiveMinimum validation" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "exclusiveMinimum" => 1.1 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "above the exclusiveMinimum is valid", x do 24 | data = Decimal.new("1.2") 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "boundary point is invalid", x do 30 | data = Decimal.new("1.1") 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | 35 | test "below the exclusiveMinimum is invalid", x do 36 | data = Decimal.new("0.6") 37 | expected_valid = false 38 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/hostname_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.HostnameTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/hostname.json 10 | """ 11 | 12 | describe "validation of host names" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "hostname" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/ipv4_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.Ipv4Test do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/ipv4.json 10 | """ 11 | 12 | describe "validation of IP addresses" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "ipv4" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/ipv6_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.Ipv6Test do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/ipv6.json 10 | """ 11 | 12 | describe "validation of IPv6 addresses" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "ipv6" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/iri_reference_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.IriReferenceTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/iri-reference.json 10 | """ 11 | 12 | describe "validation of IRI References" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "iri-reference" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/iri_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.IriTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/iri.json 10 | """ 11 | 12 | describe "validation of IRIs" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "iri" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/json_pointer_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.JsonPointerTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/json-pointer.json 10 | """ 11 | 12 | describe "validation of JSON-pointers (JSON String Representation)" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "json-pointer" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/minimum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.MinimumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/minimum.json 10 | """ 11 | 12 | describe "minimum validation" do 13 | setup do 14 | json_schema = %{"$schema" => "https://json-schema.org/draft/2020-12/schema", "minimum" => 1.1} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "above the minimum is valid", x do 20 | data = Decimal.new("2.6") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is valid", x do 26 | data = Decimal.new("1.1") 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "below the minimum is invalid", x do 32 | data = Decimal.new("0.6") 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | end 37 | 38 | describe "minimum validation with signed integer" do 39 | setup do 40 | json_schema = %{"$schema" => "https://json-schema.org/draft/2020-12/schema", "minimum" => -2} 41 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 42 | {:ok, json_schema: json_schema, schema: schema} 43 | end 44 | 45 | test "boundary point with float is valid", x do 46 | data = Decimal.new("-2.0") 47 | expected_valid = true 48 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 49 | end 50 | 51 | test "float below the minimum is invalid", x do 52 | data = Decimal.new("-2.0001") 53 | expected_valid = false 54 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/one_of_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.OneOfTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/oneOf.json 10 | """ 11 | 12 | describe "oneOf" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "oneOf" => [%{"type" => "integer"}, %{"minimum" => 2}] 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "second oneOf valid", x do 24 | data = Decimal.new("2.5") 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | 29 | test "neither oneOf valid", x do 30 | data = Decimal.new("1.5") 31 | expected_valid = false 32 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/optional/bignum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.Optional.BignumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/bignum.json 10 | """ 11 | 12 | describe "float comparison with high precision" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "exclusiveMaximum" => 9.727837981879871e26 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "comparison works for high numbers", x do 24 | data = Decimal.new("972783798187987123879878123.188781371") 25 | expected_valid = false 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | end 29 | 30 | describe "float comparison with high precision on negative numbers" do 31 | setup do 32 | json_schema = %{ 33 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 34 | "exclusiveMinimum" => -9.727837981879871e26 35 | } 36 | 37 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 38 | {:ok, json_schema: json_schema, schema: schema} 39 | end 40 | 41 | test "comparison works for very negative numbers", x do 42 | data = Decimal.new("-972783798187987123879878123.188781371") 43 | expected_valid = false 44 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/pattern_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.PatternTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/pattern.json 10 | """ 11 | 12 | describe "pattern validation" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "pattern" => "^a*$" 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "ignores floats", x do 24 | data = Decimal.new("1.0") 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/regex_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.RegexTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/regex.json 10 | """ 11 | 12 | describe "validation of regular expressions" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "regex" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/relative_json_pointer_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.RelativeJsonPointerTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/relative-json-pointer.json 10 | """ 11 | 12 | describe "validation of Relative JSON Pointers (RJP)" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "relative-json-pointer" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/time_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.TimeTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/time.json 10 | """ 11 | 12 | describe "validation of time strings" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "time" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/unevaluated_items_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.UnevaluatedItemsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/unevaluatedItems.json 10 | """ 11 | 12 | describe "non-array instances are valid" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "unevaluatedItems" => false 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "ignores floats", x do 24 | data = Decimal.new("1.0") 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/unevaluated_properties_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.UnevaluatedPropertiesTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/unevaluatedProperties.json 10 | """ 11 | 12 | describe "non-object instances are valid" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "unevaluatedProperties" => false 17 | } 18 | 19 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "https://json-schema.org/draft/2020-12/schema") 20 | {:ok, json_schema: json_schema, schema: schema} 21 | end 22 | 23 | test "ignores floats", x do 24 | data = Decimal.new("1.0") 25 | expected_valid = true 26 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/unknown_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.UnknownTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/unknown.json 10 | """ 11 | 12 | describe "unknown format" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "unknown" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "unknown formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/uri_reference_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.UriReferenceTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/uri-reference.json 10 | """ 11 | 12 | describe "validation of URI References" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "uri-reference" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/uri_template_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.UriTemplateTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/uri-template.json 10 | """ 11 | 12 | describe "format: uri-template" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "uri-template" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/uri_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.UriTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/uri.json 10 | """ 11 | 12 | describe "validation of URIs" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "uri" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft202012/decimal_values/uuid_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft202012.DecimalValues.UuidTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft2020-12/optional/format/uuid.json 10 | """ 11 | 12 | describe "uuid format" do 13 | setup do 14 | json_schema = %{ 15 | "$schema" => "https://json-schema.org/draft/2020-12/schema", 16 | "format" => "uuid" 17 | } 18 | 19 | schema = 20 | JsonSchemaSuite.build_schema(json_schema, 21 | default_meta: "https://json-schema.org/draft/2020-12/schema", 22 | formats: true 23 | ) 24 | 25 | {:ok, json_schema: json_schema, schema: schema} 26 | end 27 | 28 | test "all string formats ignore floats", x do 29 | data = Decimal.new("13.7") 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/atom_keys/definitions_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.AtomKeys.DefinitionsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/definitions.json 10 | """ 11 | 12 | describe "validate definition against metaschema" do 13 | setup do 14 | json_schema = %JSV.Schema{"$ref": "http://json-schema.org/draft-07/schema#"} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "valid definition schema", x do 20 | data = %{"definitions" => %{"foo" => %{"type" => "integer"}}} 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "invalid definition schema", x do 26 | data = %{"definitions" => %{"foo" => %{"type" => 1}}} 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/atom_keys/exclusive_maximum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.AtomKeys.ExclusiveMaximumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/exclusiveMaximum.json 10 | """ 11 | 12 | describe "exclusiveMaximum validation" do 13 | setup do 14 | json_schema = %JSV.Schema{exclusiveMaximum: 3.0} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "below the exclusiveMaximum is valid", x do 20 | data = 2.2 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is invalid", x do 26 | data = 3.0 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "above the exclusiveMaximum is invalid", x do 32 | data = 3.5 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-numbers", x do 38 | data = "x" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/atom_keys/exclusive_minimum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.AtomKeys.ExclusiveMinimumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/exclusiveMinimum.json 10 | """ 11 | 12 | describe "exclusiveMinimum validation" do 13 | setup do 14 | json_schema = %JSV.Schema{exclusiveMinimum: 1.1} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "above the exclusiveMinimum is valid", x do 20 | data = 1.2 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is invalid", x do 26 | data = 1.1 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "below the exclusiveMinimum is invalid", x do 32 | data = 0.6 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-numbers", x do 38 | data = "x" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/atom_keys/infinite_loop_detection_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.AtomKeys.InfiniteLoopDetectionTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/infinite-loop-detection.json 10 | """ 11 | 12 | describe "evaluating the same schema location against the same data location twice is not a sign of an infinite loop" do 13 | setup do 14 | json_schema = %{ 15 | definitions: %{int: %JSV.Schema{type: "integer"}}, 16 | allOf: [ 17 | %JSV.Schema{properties: %{foo: %JSV.Schema{"$ref": "#/definitions/int"}}}, 18 | %JSV.Schema{additionalProperties: %JSV.Schema{"$ref": "#/definitions/int"}} 19 | ] 20 | } 21 | 22 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 23 | {:ok, json_schema: json_schema, schema: schema} 24 | end 25 | 26 | test "passing case", x do 27 | data = %{"foo" => 1} 28 | expected_valid = true 29 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 30 | end 31 | 32 | test "failing case", x do 33 | data = %{"foo" => "a string"} 34 | expected_valid = false 35 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/atom_keys/max_items_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.AtomKeys.MaxItemsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/maxItems.json 10 | """ 11 | 12 | describe "maxItems validation" do 13 | setup do 14 | json_schema = %JSV.Schema{maxItems: 2} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "shorter is valid", x do 20 | data = [1] 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "exact length is valid", x do 26 | data = [1, 2] 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "too long is invalid", x do 32 | data = [1, 2, 3] 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-arrays", x do 38 | data = "foobar" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | 44 | describe "maxItems validation with a decimal" do 45 | setup do 46 | json_schema = %JSV.Schema{maxItems: 2.0} 47 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 48 | {:ok, json_schema: json_schema, schema: schema} 49 | end 50 | 51 | test "shorter is valid", x do 52 | data = [1] 53 | expected_valid = true 54 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 55 | end 56 | 57 | test "too long is invalid", x do 58 | data = [1, 2, 3] 59 | expected_valid = false 60 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/atom_keys/min_items_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.AtomKeys.MinItemsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/minItems.json 10 | """ 11 | 12 | describe "minItems validation" do 13 | setup do 14 | json_schema = %JSV.Schema{minItems: 1} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "longer is valid", x do 20 | data = [1, 2] 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "exact length is valid", x do 26 | data = [1] 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "too short is invalid", x do 32 | data = [] 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-arrays", x do 38 | data = "" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | 44 | describe "minItems validation with a decimal" do 45 | setup do 46 | json_schema = %JSV.Schema{minItems: 1.0} 47 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 48 | {:ok, json_schema: json_schema, schema: schema} 49 | end 50 | 51 | test "longer is valid", x do 52 | data = [1, 2] 53 | expected_valid = true 54 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 55 | end 56 | 57 | test "too short is invalid", x do 58 | data = [] 59 | expected_valid = false 60 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/atom_keys/unknown_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.AtomKeys.UnknownTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/unknown.json 10 | """ 11 | 12 | describe "unknown format" do 13 | setup do 14 | json_schema = %JSV.Schema{format: "unknown"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "unknown formats ignore integers", x do 23 | data = 12 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | 28 | test "unknown formats ignore floats", x do 29 | data = 13.7 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | 34 | test "unknown formats ignore objects", x do 35 | data = %{} 36 | expected_valid = true 37 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 38 | end 39 | 40 | test "unknown formats ignore arrays", x do 41 | data = [] 42 | expected_valid = true 43 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 44 | end 45 | 46 | test "unknown formats ignore booleans", x do 47 | data = false 48 | expected_valid = true 49 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 50 | end 51 | 52 | test "unknown formats ignore nulls", x do 53 | data = nil 54 | expected_valid = true 55 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 56 | end 57 | 58 | test "unknown formats ignore strings", x do 59 | data = "string" 60 | expected_valid = true 61 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/definitions_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.DefinitionsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/definitions.json 10 | """ 11 | 12 | describe "validate definition against metaschema" do 13 | setup do 14 | json_schema = %{"$ref" => "http://json-schema.org/draft-07/schema#"} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "valid definition schema", x do 20 | data = %{"definitions" => %{"foo" => %{"type" => "integer"}}} 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "invalid definition schema", x do 26 | data = %{"definitions" => %{"foo" => %{"type" => 1}}} 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/exclusive_maximum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.ExclusiveMaximumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/exclusiveMaximum.json 10 | """ 11 | 12 | describe "exclusiveMaximum validation" do 13 | setup do 14 | json_schema = %{"exclusiveMaximum" => 3.0} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "below the exclusiveMaximum is valid", x do 20 | data = 2.2 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is invalid", x do 26 | data = 3.0 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "above the exclusiveMaximum is invalid", x do 32 | data = 3.5 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-numbers", x do 38 | data = "x" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/exclusive_minimum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.ExclusiveMinimumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/exclusiveMinimum.json 10 | """ 11 | 12 | describe "exclusiveMinimum validation" do 13 | setup do 14 | json_schema = %{"exclusiveMinimum" => 1.1} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "above the exclusiveMinimum is valid", x do 20 | data = 1.2 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is invalid", x do 26 | data = 1.1 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "below the exclusiveMinimum is invalid", x do 32 | data = 0.6 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-numbers", x do 38 | data = "x" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/infinite_loop_detection_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.InfiniteLoopDetectionTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/infinite-loop-detection.json 10 | """ 11 | 12 | describe "evaluating the same schema location against the same data location twice is not a sign of an infinite loop" do 13 | setup do 14 | json_schema = %{ 15 | "definitions" => %{"int" => %{"type" => "integer"}}, 16 | "allOf" => [ 17 | %{"properties" => %{"foo" => %{"$ref" => "#/definitions/int"}}}, 18 | %{"additionalProperties" => %{"$ref" => "#/definitions/int"}} 19 | ] 20 | } 21 | 22 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 23 | {:ok, json_schema: json_schema, schema: schema} 24 | end 25 | 26 | test "passing case", x do 27 | data = %{"foo" => 1} 28 | expected_valid = true 29 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 30 | end 31 | 32 | test "failing case", x do 33 | data = %{"foo" => "a string"} 34 | expected_valid = false 35 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/max_items_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.MaxItemsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/maxItems.json 10 | """ 11 | 12 | describe "maxItems validation" do 13 | setup do 14 | json_schema = %{"maxItems" => 2} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "shorter is valid", x do 20 | data = [1] 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "exact length is valid", x do 26 | data = [1, 2] 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "too long is invalid", x do 32 | data = [1, 2, 3] 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-arrays", x do 38 | data = "foobar" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | 44 | describe "maxItems validation with a decimal" do 45 | setup do 46 | json_schema = %{"maxItems" => 2.0} 47 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 48 | {:ok, json_schema: json_schema, schema: schema} 49 | end 50 | 51 | test "shorter is valid", x do 52 | data = [1] 53 | expected_valid = true 54 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 55 | end 56 | 57 | test "too long is invalid", x do 58 | data = [1, 2, 3] 59 | expected_valid = false 60 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/max_length_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.MaxLengthTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/maxLength.json 10 | """ 11 | 12 | describe "maxLength validation" do 13 | setup do 14 | json_schema = %{"maxLength" => 2} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "shorter is valid", x do 20 | data = "f" 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "exact length is valid", x do 26 | data = "fo" 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "too long is invalid", x do 32 | data = "foo" 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-strings", x do 38 | data = 100 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | 43 | test "two graphemes is long enough", x do 44 | data = "💩💩" 45 | expected_valid = true 46 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 47 | end 48 | end 49 | 50 | describe "maxLength validation with a decimal" do 51 | setup do 52 | json_schema = %{"maxLength" => 2.0} 53 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 54 | {:ok, json_schema: json_schema, schema: schema} 55 | end 56 | 57 | test "shorter is valid", x do 58 | data = "f" 59 | expected_valid = true 60 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 61 | end 62 | 63 | test "too long is invalid", x do 64 | data = "foo" 65 | expected_valid = false 66 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/min_items_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.MinItemsTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/minItems.json 10 | """ 11 | 12 | describe "minItems validation" do 13 | setup do 14 | json_schema = %{"minItems" => 1} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "longer is valid", x do 20 | data = [1, 2] 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "exact length is valid", x do 26 | data = [1] 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "too short is invalid", x do 32 | data = [] 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-arrays", x do 38 | data = "" 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | end 43 | 44 | describe "minItems validation with a decimal" do 45 | setup do 46 | json_schema = %{"minItems" => 1.0} 47 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 48 | {:ok, json_schema: json_schema, schema: schema} 49 | end 50 | 51 | test "longer is valid", x do 52 | data = [1, 2] 53 | expected_valid = true 54 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 55 | end 56 | 57 | test "too short is invalid", x do 58 | data = [] 59 | expected_valid = false 60 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/min_length_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.MinLengthTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/minLength.json 10 | """ 11 | 12 | describe "minLength validation" do 13 | setup do 14 | json_schema = %{"minLength" => 2} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "longer is valid", x do 20 | data = "foo" 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "exact length is valid", x do 26 | data = "fo" 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "too short is invalid", x do 32 | data = "f" 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | 37 | test "ignores non-strings", x do 38 | data = 1 39 | expected_valid = true 40 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 41 | end 42 | 43 | test "one grapheme is not long enough", x do 44 | data = "💩" 45 | expected_valid = false 46 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 47 | end 48 | end 49 | 50 | describe "minLength validation with a decimal" do 51 | setup do 52 | json_schema = %{"minLength" => 2.0} 53 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 54 | {:ok, json_schema: json_schema, schema: schema} 55 | end 56 | 57 | test "longer is valid", x do 58 | data = "foo" 59 | expected_valid = true 60 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 61 | end 62 | 63 | test "too short is invalid", x do 64 | data = "f" 65 | expected_valid = false 66 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/binary_keys/unknown_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.BinaryKeys.UnknownTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/unknown.json 10 | """ 11 | 12 | describe "unknown format" do 13 | setup do 14 | json_schema = %{"format" => "unknown"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "unknown formats ignore integers", x do 23 | data = 12 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | 28 | test "unknown formats ignore floats", x do 29 | data = 13.7 30 | expected_valid = true 31 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 32 | end 33 | 34 | test "unknown formats ignore objects", x do 35 | data = %{} 36 | expected_valid = true 37 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 38 | end 39 | 40 | test "unknown formats ignore arrays", x do 41 | data = [] 42 | expected_valid = true 43 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 44 | end 45 | 46 | test "unknown formats ignore booleans", x do 47 | data = false 48 | expected_valid = true 49 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 50 | end 51 | 52 | test "unknown formats ignore nulls", x do 53 | data = nil 54 | expected_valid = true 55 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 56 | end 57 | 58 | test "unknown formats ignore strings", x do 59 | data = "string" 60 | expected_valid = true 61 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/any_of_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.AnyOfTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/anyOf.json 10 | """ 11 | 12 | describe "anyOf" do 13 | setup do 14 | json_schema = %{"anyOf" => [%{"type" => "integer"}, %{"minimum" => 2}]} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "second anyOf valid", x do 20 | data = Decimal.new("2.5") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "neither anyOf valid", x do 26 | data = Decimal.new("1.5") 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/date_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.DateTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/date.json 10 | """ 11 | 12 | describe "validation of date strings" do 13 | setup do 14 | json_schema = %{"format" => "date"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/date_time_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.DateTimeTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/date-time.json 10 | """ 11 | 12 | describe "validation of date-time strings" do 13 | setup do 14 | json_schema = %{"format" => "date-time"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/email_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.EmailTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/email.json 10 | """ 11 | 12 | describe "validation of e-mail addresses" do 13 | setup do 14 | json_schema = %{"format" => "email"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/exclusive_maximum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.ExclusiveMaximumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/exclusiveMaximum.json 10 | """ 11 | 12 | describe "exclusiveMaximum validation" do 13 | setup do 14 | json_schema = %{"exclusiveMaximum" => 3.0} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "below the exclusiveMaximum is valid", x do 20 | data = Decimal.new("2.2") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is invalid", x do 26 | data = Decimal.new("3.0") 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "above the exclusiveMaximum is invalid", x do 32 | data = Decimal.new("3.5") 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/exclusive_minimum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.ExclusiveMinimumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/exclusiveMinimum.json 10 | """ 11 | 12 | describe "exclusiveMinimum validation" do 13 | setup do 14 | json_schema = %{"exclusiveMinimum" => 1.1} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "above the exclusiveMinimum is valid", x do 20 | data = Decimal.new("1.2") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is invalid", x do 26 | data = Decimal.new("1.1") 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "below the exclusiveMinimum is invalid", x do 32 | data = Decimal.new("0.6") 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/hostname_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.HostnameTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/hostname.json 10 | """ 11 | 12 | describe "validation of host names" do 13 | setup do 14 | json_schema = %{"format" => "hostname"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/ipv4_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.Ipv4Test do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/ipv4.json 10 | """ 11 | 12 | describe "validation of IP addresses" do 13 | setup do 14 | json_schema = %{"format" => "ipv4"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/ipv6_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.Ipv6Test do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/ipv6.json 10 | """ 11 | 12 | describe "validation of IPv6 addresses" do 13 | setup do 14 | json_schema = %{"format" => "ipv6"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/iri_reference_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.IriReferenceTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/iri-reference.json 10 | """ 11 | 12 | describe "validation of IRI References" do 13 | setup do 14 | json_schema = %{"format" => "iri-reference"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/iri_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.IriTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/iri.json 10 | """ 11 | 12 | describe "validation of IRIs" do 13 | setup do 14 | json_schema = %{"format" => "iri"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/json_pointer_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.JsonPointerTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/json-pointer.json 10 | """ 11 | 12 | describe "validation of JSON-pointers (JSON String Representation)" do 13 | setup do 14 | json_schema = %{"format" => "json-pointer"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/maximum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.MaximumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/maximum.json 10 | """ 11 | 12 | describe "maximum validation" do 13 | setup do 14 | json_schema = %{"maximum" => 3.0} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "below the maximum is valid", x do 20 | data = Decimal.new("2.6") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is valid", x do 26 | data = Decimal.new("3.0") 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "above the maximum is invalid", x do 32 | data = Decimal.new("3.5") 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | end 37 | 38 | describe "maximum validation with unsigned integer" do 39 | setup do 40 | json_schema = %{"maximum" => 300} 41 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 42 | {:ok, json_schema: json_schema, schema: schema} 43 | end 44 | 45 | test "below the maximum is invalid", x do 46 | data = Decimal.new("299.97") 47 | expected_valid = true 48 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 49 | end 50 | 51 | test "boundary point float is valid", x do 52 | data = Decimal.new("300.00") 53 | expected_valid = true 54 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 55 | end 56 | 57 | test "above the maximum is invalid", x do 58 | data = Decimal.new("300.5") 59 | expected_valid = false 60 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/minimum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.MinimumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/minimum.json 10 | """ 11 | 12 | describe "minimum validation" do 13 | setup do 14 | json_schema = %{"minimum" => 1.1} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "above the minimum is valid", x do 20 | data = Decimal.new("2.6") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "boundary point is valid", x do 26 | data = Decimal.new("1.1") 27 | expected_valid = true 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | 31 | test "below the minimum is invalid", x do 32 | data = Decimal.new("0.6") 33 | expected_valid = false 34 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 35 | end 36 | end 37 | 38 | describe "minimum validation with signed integer" do 39 | setup do 40 | json_schema = %{"minimum" => -2} 41 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 42 | {:ok, json_schema: json_schema, schema: schema} 43 | end 44 | 45 | test "boundary point with float is valid", x do 46 | data = Decimal.new("-2.0") 47 | expected_valid = true 48 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 49 | end 50 | 51 | test "float below the minimum is invalid", x do 52 | data = Decimal.new("-2.0001") 53 | expected_valid = false 54 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/multiple_of_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.MultipleOfTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/multipleOf.json 10 | """ 11 | 12 | describe "by number" do 13 | setup do 14 | json_schema = %{"multipleOf" => 1.5} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "4.5 is multiple of 1.5", x do 20 | data = Decimal.new("4.5") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | end 25 | 26 | describe "by small number" do 27 | setup do 28 | json_schema = %{"multipleOf" => 0.0001} 29 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 30 | {:ok, json_schema: json_schema, schema: schema} 31 | end 32 | 33 | test "0.0075 is multiple of 0.0001", x do 34 | data = Decimal.new("0.0075") 35 | expected_valid = true 36 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 37 | end 38 | 39 | test "0.00751 is not multiple of 0.0001", x do 40 | data = Decimal.new("0.00751") 41 | expected_valid = false 42 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 43 | end 44 | end 45 | 46 | describe "float division = inf" do 47 | setup do 48 | json_schema = %{"type" => "integer", "multipleOf" => 0.123456789} 49 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 50 | {:ok, json_schema: json_schema, schema: schema} 51 | end 52 | 53 | test "always invalid, but naive implementations may raise an overflow error", x do 54 | data = Decimal.new("1.0E+308") 55 | expected_valid = false 56 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/one_of_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.OneOfTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/oneOf.json 10 | """ 11 | 12 | describe "oneOf" do 13 | setup do 14 | json_schema = %{"oneOf" => [%{"type" => "integer"}, %{"minimum" => 2}]} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "second oneOf valid", x do 20 | data = Decimal.new("2.5") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | 25 | test "neither oneOf valid", x do 26 | data = Decimal.new("1.5") 27 | expected_valid = false 28 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/optional/bignum_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.Optional.BignumTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/bignum.json 10 | """ 11 | 12 | describe "float comparison with high precision" do 13 | setup do 14 | json_schema = %{"exclusiveMaximum" => 9.727837981879871e26} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "comparison works for high numbers", x do 20 | data = Decimal.new("972783798187987123879878123.188781371") 21 | expected_valid = false 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | end 25 | 26 | describe "float comparison with high precision on negative numbers" do 27 | setup do 28 | json_schema = %{"exclusiveMinimum" => -9.727837981879871e26} 29 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 30 | {:ok, json_schema: json_schema, schema: schema} 31 | end 32 | 33 | test "comparison works for very negative numbers", x do 34 | data = Decimal.new("-972783798187987123879878123.188781371") 35 | expected_valid = false 36 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/pattern_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.PatternTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/pattern.json 10 | """ 11 | 12 | describe "pattern validation" do 13 | setup do 14 | json_schema = %{"pattern" => "^a*$"} 15 | schema = JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema") 16 | {:ok, json_schema: json_schema, schema: schema} 17 | end 18 | 19 | test "ignores floats", x do 20 | data = Decimal.new("1.0") 21 | expected_valid = true 22 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/regex_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.RegexTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/regex.json 10 | """ 11 | 12 | describe "validation of regular expressions" do 13 | setup do 14 | json_schema = %{"format" => "regex"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/relative_json_pointer_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.RelativeJsonPointerTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/relative-json-pointer.json 10 | """ 11 | 12 | describe "validation of Relative JSON Pointers (RJP)" do 13 | setup do 14 | json_schema = %{"format" => "relative-json-pointer"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/time_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.TimeTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/time.json 10 | """ 11 | 12 | describe "validation of time strings" do 13 | setup do 14 | json_schema = %{"format" => "time"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/unknown_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.UnknownTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/unknown.json 10 | """ 11 | 12 | describe "unknown format" do 13 | setup do 14 | json_schema = %{"format" => "unknown"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "unknown formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/uri_reference_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.UriReferenceTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/uri-reference.json 10 | """ 11 | 12 | describe "validation of URI References" do 13 | setup do 14 | json_schema = %{"format" => "uri-reference"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/uri_template_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.UriTemplateTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/uri-template.json 10 | """ 11 | 12 | describe "format: uri-template" do 13 | setup do 14 | json_schema = %{"format" => "uri-template"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/generated/draft7/decimal_values/uri_test.exs: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.LargeNumbers 2 | # credo:disable-for-this-file Credo.Check.Readability.StringSigils 3 | 4 | defmodule JSV.Generated.Draft7.DecimalValues.UriTest do 5 | alias JSV.Test.JsonSchemaSuite 6 | use ExUnit.Case, async: true 7 | 8 | @moduledoc """ 9 | Test generated from deps/json_schema_test_suite/tests/draft7/optional/format/uri.json 10 | """ 11 | 12 | describe "validation of URIs" do 13 | setup do 14 | json_schema = %{"format" => "uri"} 15 | 16 | schema = 17 | JsonSchemaSuite.build_schema(json_schema, default_meta: "http://json-schema.org/draft-07/schema", formats: true) 18 | 19 | {:ok, json_schema: json_schema, schema: schema} 20 | end 21 | 22 | test "all string formats ignore floats", x do 23 | data = Decimal.new("13.7") 24 | expected_valid = true 25 | JsonSchemaSuite.run_test(x.json_schema, x.schema, data, expected_valid, print_errors: false) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/jsv/helpers/enum_ext_test.exs: -------------------------------------------------------------------------------- 1 | defmodule JSV.Helpers.EnumExtTest do 2 | use ExUnit.Case, async: true 3 | alias JSV.Helpers.EnumExt 4 | 5 | describe "reduce_ok/3" do 6 | test "reduces successfully" do 7 | input = [1, 2, 3, 4] 8 | result = EnumExt.reduce_ok(input, [], &{:ok, [&1 | &2]}) 9 | assert result == {:ok, [4, 3, 2, 1]} 10 | end 11 | 12 | test "stops on first error" do 13 | input = [1, 2, 3, 4] 14 | 15 | result = 16 | EnumExt.reduce_ok(input, [], fn 17 | 2, acc -> {:error, [2 | acc]} 18 | x, acc -> {:ok, [x | acc]} 19 | end) 20 | 21 | assert result == {:error, [2, 1]} 22 | end 23 | 24 | test "allows to return errors as values" do 25 | errors = [ 26 | {:error, 1}, 27 | {:error, 2}, 28 | {:error, 4}, 29 | {:error, 3}, 30 | {:error, 0} 31 | ] 32 | 33 | assert {:ok, {:error, 4}} = EnumExt.reduce_ok(errors, {:error, -1}, fn item, best -> {:ok, max(item, best)} end) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /test/jsv/macrogen_test.exs: -------------------------------------------------------------------------------- 1 | defmodule JSV.MacrogenTest do 2 | use ExUnit.Case, async: true 3 | 4 | test "no module should define take_keyword anymore" do 5 | # take_keyword is a macro that should define handle_keyword/4 6 | {:ok, mods} = :application.get_key(:jsv, :modules) 7 | 8 | Enum.each(mods, fn mod -> 9 | Code.ensure_loaded!(mod) 10 | refute {:take_keyword, 3} in mod.module_info(:exports), "module #{inspect(mod)} exports take_keyword/3" 11 | refute {:take_keyword, 4} in mod.module_info(:exports), "module #{inspect(mod)} exports take_keyword/3" 12 | end) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /test/jsv/resolver/httpc_test.exs: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.HttpcTest do 2 | alias JSV.Codec 3 | alias JSV.Resolver.Embedded 4 | alias JSV.Resolver.Httpc 5 | use ExUnit.Case, async: false 6 | 7 | use Patch 8 | 9 | test "will not resolve an URL if the prefix is not allowed" do 10 | assert {:error, {:restricted_url, _}} = 11 | Httpc.resolve("http://example.com/schema", allowed_prefixes: []) 12 | end 13 | 14 | @tag :skip 15 | test "will download from a remote endpoint" do 16 | # :inets, :ssl and :crypto are started by the tests or a common library ... so this 17 | # will always work. 18 | assert {:normal, %{"slideshow" => _}} = 19 | Httpc.resolve("https://httpbin.org/json", 20 | cache_dir: false, 21 | allowed_prefixes: ["https://httpbin.org/"] 22 | ) 23 | end 24 | 25 | test "will use a directory cache" do 26 | url = "http://some-host/some/path" 27 | unique_id = System.system_time(:microsecond) 28 | cached_schema = %{"id" => "jsv://test/#{unique_id}"} 29 | 30 | # Define a cache directory for the test that we will give to the resolver 31 | cache_dir = Briefly.create!(directory: true, prefix: "jsv") 32 | 33 | # The Httpc module conveniently allows the test to know the cache path from 34 | # the URL in advance 35 | cached_path = Httpc.url_to_cache_path(url, cache_dir) 36 | 37 | # Prefill the cache. Cache is stored as plain json, not http responses 38 | # objects. 39 | cached_json = Codec.encode!(cached_schema) 40 | :ok = File.mkdir_p!(Path.dirname(cached_path)) 41 | :ok = File.write!(cached_path, cached_json) 42 | 43 | # If the cache exists, it is returned 44 | assert {:normal, ^cached_schema} = Httpc.resolve(url, allowed_prefixes: [url], cache_dir: cache_dir) 45 | end 46 | 47 | test "uses the embedded resolver for well known URIs resolver" do 48 | patch(Embedded, :resolve, fn uri, opts -> {:normal, %{"uri_called" => uri, "opts_called" => opts}} end) 49 | 50 | assert {:normal, 51 | %{ 52 | # The URL should be given to the Embedded resolver 53 | "uri_called" => "https://json-schema.org/draft/2020-12/schema", 54 | # Options should not be forwarded 55 | "opts_called" => [] 56 | }} == 57 | Httpc.resolve("https://json-schema.org/draft/2020-12/schema", 58 | cache_dir: false, 59 | 60 | # The prefix is not needed 61 | allowed_prefixes: [] 62 | ) 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /test/jsv/resolver/internal_test.exs: -------------------------------------------------------------------------------- 1 | defmodule JSV.Resolver.InternalTest do 2 | alias JSV.Resolver.Internal 3 | use ExUnit.Case, async: true 4 | 5 | test "will not resolve an unexisting module" do 6 | assert {:error, {:unknown_module, "unexisting_module"}} = 7 | Internal.resolve("jsv:module:unexisting_module", []) 8 | 9 | uri = Internal.module_to_uri(UnknownModule) 10 | 11 | assert {:error, {:unknown_module, "Elixir.UnknownModule"}} = Internal.resolve(uri, []) 12 | end 13 | 14 | test "will not resolve a module not exporting schema" do 15 | defmodule EmptyModule do 16 | end 17 | 18 | uri = Internal.module_to_uri(EmptyModule) 19 | 20 | assert {:error, {:invalid_schema_module, e}} = Internal.resolve(uri, []) 21 | assert %UndefinedFunctionError{arity: 0, function: :schema, module: EmptyModule} = e 22 | end 23 | 24 | test "will resolve a module with the proper callback" do 25 | defmodule CorrectModule do 26 | @spec schema :: term 27 | def schema do 28 | %{type: :integer} 29 | end 30 | end 31 | 32 | uri = Internal.module_to_uri(CorrectModule) 33 | assert {:ok, %{type: :integer}} == Internal.resolve(uri, []) 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /test/jsv/rns_test.exs: -------------------------------------------------------------------------------- 1 | defmodule JSV.RNSTest do 2 | alias JSV.RNS 3 | use ExUnit.Case, async: true 4 | 5 | describe "derive from fully qualified" do 6 | test "derive path" do 7 | assert {:ok, "http://example.com/a/b"} = RNS.derive("http://example.com", "/a/b") 8 | assert {:ok, "http://example.com/b"} = RNS.derive("http://example.com/a", "b") 9 | assert {:ok, "http://example.com/a/b"} = RNS.derive("http://example.com/a/", "b") 10 | end 11 | 12 | test "replace everything" do 13 | assert {:ok, "http://second.host/xxx/yyy"} = RNS.derive("http://example.com/a/", "http://second.host/xxx/yyy") 14 | end 15 | 16 | test "fragment does not belong to the RNS" do 17 | assert {:ok, "http://example.com/a"} = RNS.derive("http://example.com/", "/a#some_fragment") 18 | end 19 | 20 | test "keep qs" do 21 | assert {:ok, "http://example.com/a/b?a=1&b=2"} = RNS.derive("http://example.com", "/a/b?a=1&b=2") 22 | end 23 | end 24 | 25 | describe "derive from root" do 26 | test "accepts and returns root" do 27 | assert {:ok, :root} = RNS.derive(:root, "#some_fragment") 28 | assert {:error, _} = RNS.derive(:root, "some_path#some_fragment") 29 | end 30 | end 31 | 32 | describe "URNs" do 33 | test "derive an URN" do 34 | assert {:ok, "urn:isbn:1234?a=1"} = RNS.derive("urn:isbn:1234?a=1", "#some_fragment") 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/jsv_test.exs: -------------------------------------------------------------------------------- 1 | defmodule JSVTest do 2 | use ExUnit.Case, async: true 3 | doctest JSV 4 | end 5 | -------------------------------------------------------------------------------- /test/support/example_modules.ex: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.Specs 2 | # credo:disable-for-this-file Credo.Check.Readability.ModuleDoc 3 | 4 | defmodule MyApp.UserSchema do 5 | require JSV 6 | 7 | JSV.defschema(%{ 8 | type: :object, 9 | properties: %{ 10 | name: %{type: :string, default: ""}, 11 | age: %{type: :integer, default: 0} 12 | } 13 | }) 14 | end 15 | 16 | defmodule MyApp.CompanySchema do 17 | require JSV 18 | 19 | JSV.defschema(%{ 20 | type: :object, 21 | properties: %{ 22 | name: %{type: :string}, 23 | owner: MyApp.UserSchema 24 | } 25 | }) 26 | end 27 | 28 | defmodule MyApp.LocalResolver do 29 | require JSV 30 | use JSV.Resolver.Local, source: __ENV__.file |> Path.dirname() |> Path.join("schemas") 31 | end 32 | 33 | defmodule MyApp.Organization do 34 | defstruct [:name, :id] 35 | end 36 | 37 | defmodule MyApp.OrganizationSchema do 38 | require JSV 39 | 40 | JSV.defschema_for(MyApp.Organization, %{ 41 | type: :object, 42 | properties: %{ 43 | id: %{type: :string, format: :uuid}, 44 | name: %{type: :string} 45 | } 46 | }) 47 | end 48 | 49 | defmodule CustomSchemaStruct do 50 | defstruct [:type, :description] 51 | end 52 | 53 | defmodule Elixir.ASchemaExportingModule do 54 | def schema do 55 | %{} 56 | end 57 | end 58 | 59 | defmodule AModuleWithoutExportedSchema do 60 | def hello do 61 | "world" 62 | end 63 | end 64 | 65 | defmodule MyApp.Cast do 66 | import JSV 67 | 68 | defcast :to_integer 69 | defcast "to_integer_if_string", :to_integer 70 | 71 | defp to_integer(data) when is_binary(data) do 72 | case Integer.parse(data) do 73 | {int, ""} -> {:ok, int} 74 | _ -> {:error, "invalid"} 75 | end 76 | end 77 | 78 | defp to_integer(_) do 79 | {:error, "invalid"} 80 | end 81 | 82 | defcast to_existing_atom(data) do 83 | {:ok, String.to_existing_atom(data)} 84 | rescue 85 | ArgumentError -> {:error, "bad atom"} 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /test/support/schemas/user-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$id": "myapp:user-0.0.1", 3 | "type": "object", 4 | "properties": { 5 | "username": { 6 | "type": "string" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /test/support/test_helpers.ex: -------------------------------------------------------------------------------- 1 | defmodule JSV.TestHelpers do 2 | @moduledoc false 3 | defmacro env_mod(kind \\ []) do 4 | line = __CALLER__.line 5 | {fun, _} = __CALLER__.function 6 | 7 | test_name = 8 | fun 9 | |> Atom.to_string() 10 | |> String.replace(" ", "_") 11 | |> Macro.camelize() 12 | 13 | rand = "L#{line}" 14 | 15 | quote bind_quoted: binding() do 16 | Module.concat(:lists.flatten([kind, test_name, rand])) 17 | end 18 | end 19 | 20 | defmacro mock_for(behaviour) do 21 | quote do 22 | behaviour_name = unquote(behaviour) |> Module.split() |> List.last() 23 | 24 | mod = env_mod(["Mocks", behaviour_name]) 25 | 26 | defmock(mod, for: unquote(behaviour)) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/support/test_resolver.ex: -------------------------------------------------------------------------------- 1 | # credo:disable-for-this-file Credo.Check.Readability.Specs 2 | defmodule JSV.Test.TestResolver do 3 | alias JSV.Codec 4 | alias JSV.Resolver.Embedded 5 | 6 | @moduledoc false 7 | 8 | @suite_dir Path.join([File.cwd!(), "deps", "json_schema_test_suite", "remotes"]) 9 | 10 | def resolve("http://localhost:1234/" <> _ = url, _) do 11 | uri = URI.parse(url) 12 | return_local_file(uri.path) 13 | end 14 | 15 | def resolve(url, _opts) do 16 | Embedded.resolve(url, []) 17 | end 18 | 19 | defp return_local_file(path) do 20 | full_path = Path.join(@suite_dir, path) 21 | 22 | case File.read(full_path) do 23 | {:ok, json} -> Codec.decode(json) 24 | {:error, :enoent} -> {:error, {:local_not_found, path}} 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /tools/check-docs-format.exs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env elixir 2 | defmodule Tool do 3 | def run do 4 | Path.wildcard(Path.join(File.cwd!(), "guides/**/*.md")) 5 | |> Enum.filter(&File.regular?/1) 6 | |> Enum.each(&check_file/1) 7 | end 8 | 9 | defp check_file(path) do 10 | path 11 | |> File.stream!() 12 | |> Stream.map(&String.trim_trailing(&1, "\n")) 13 | |> Stream.with_index(1) 14 | # Filter out TOCs and links 15 | |> Stream.reject(fn {text, _} -> String.contains?(text, "](#") || String.contains?(text, "](http") end) 16 | 17 | # Filter out generated content 18 | |> Stream.transform([], fn {text, line}, block_nesting -> 19 | case transform_lines(text, block_nesting) do 20 | {:keep, new_block_nesting} -> {[{text, line}], new_block_nesting} 21 | {:discard, new_block_nesting} -> {[], new_block_nesting} 22 | end 23 | end) 24 | |> Stream.map(fn {text, line} -> {String.length(text), line} end) 25 | |> Stream.filter(fn {len, _} -> len > 80 end) 26 | |> Enum.sort_by(fn {_, line} -> line end, :desc) 27 | |> Enum.each(fn {len, line} -> 28 | IO.puts("#{path}:#{line} line is #{len} chars long.") 29 | end) 30 | end 31 | 32 | # start a generated block, prepend :generated in the nested block types. This will only happen at the top level 33 | defp transform_lines(<<"