Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ajv-validator/ajv
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v8.6.3
Choose a base ref
...
head repository: ajv-validator/ajv
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v8.7.0
Choose a head ref
  • 19 commits
  • 16 files changed
  • 6 contributors

Commits on Oct 9, 2021

  1. Copy the full SHA
    58525ef View commit details
  2. Unverified

    The email in this signature doesn’t match the committer email.
    Copy the full SHA
    a3a9d10 View commit details
  3. build(deps-dev): bump @rollup/plugin-commonjs from 20.0.0 to 21.0.0 (#…

    …1778)
    
    Bumps [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/HEAD/packages/commonjs) from 20.0.0 to 21.0.0.
    - [Release notes](https://github.com/rollup/plugins/releases)
    - [Changelog](https://github.com/rollup/plugins/blob/master/packages/commonjs/CHANGELOG.md)
    - [Commits](https://github.com/rollup/plugins/commits/commonjs-v21.0.0/packages/commonjs)
    
    ---
    updated-dependencies:
    - dependency-name: "@rollup/plugin-commonjs"
      dependency-type: direct:development
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Oct 9, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    82ae16a View commit details
  4. Use npm 6-style peer dependency resolution with npm link (#1776)

    * Use npm 6-style peer dependency resolution with `npm link`
    
    * Update build.yml
    
    Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
    eventlistener and epoberezkin authored Oct 9, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    43d6164 View commit details

Commits on Oct 24, 2021

  1. Update typescript.md (#1788)

    * Update typescript.md
    
    Add documentation around timestamp unions for `JTDDataType`.
    
    fixes #1780
    
    * remove line-break
    
    Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
    erikbrinkman and epoberezkin authored Oct 24, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    51f0b84 View commit details
  2. fix type in doc (#1797)

    Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
    Noam3kCH and epoberezkin authored Oct 24, 2021
    Copy the full SHA
    6453ef8 View commit details
  3. retool logo (#1799)

    epoberezkin authored Oct 24, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e6e2fdb View commit details
  4. update image path

    epoberezkin committed Oct 24, 2021
    Copy the full SHA
    4aec4c5 View commit details
  5. update image

    epoberezkin committed Oct 24, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ec44ba7 View commit details

Commits on Nov 2, 2021

  1. update image (#1806)

    epoberezkin authored Nov 2, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    29caf13 View commit details

Commits on Nov 3, 2021

  1. fix website build (#1807)

    * enable website build
    
    * use import with node-fetch
    
    * log npm version
    
    * fix fetch import
    
    * debugging contributors
    
    * disable esling for scripts, only import vuepress in CI
    
    * update build.yml
    epoberezkin authored Nov 3, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fefd2e3 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    749998a View commit details
  3. add tidelift (website)

    epoberezkin committed Nov 3, 2021
    Copy the full SHA
    addc3bc View commit details

Commits on Nov 4, 2021

  1. update logo

    epoberezkin committed Nov 4, 2021
    Copy the full SHA
    7d9af0a View commit details
  2. Copy the full SHA
    01e19bb View commit details
  3. update opencollective

    epoberezkin authored Nov 4, 2021
    Copy the full SHA
    42945d6 View commit details

Commits on Nov 8, 2021

  1. update JSON Schema Test Suite, fix minContains = 0, skip failing tests (

    #1810)
    
    * update JSON Schema Test Suite, skip failing tests
    
    * fix minContains = 0 test
    
    * un-skip refRemote tests
    epoberezkin authored Nov 8, 2021
    Copy the full SHA
    1b45835 View commit details
  2. Copy the full SHA
    d0a928e View commit details
  3. 8.7.0

    epoberezkin committed Nov 8, 2021
    Copy the full SHA
    da46e38 View commit details
16 changes: 8 additions & 8 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [10.x, 12.x, 14.x]
node-version: [12.x, 14.x, 16.x]

steps:
- uses: actions/checkout@v2
@@ -22,13 +22,13 @@ jobs:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: git submodule update --init
# - name: update website
# if: ${{ github.event_name == 'push' && matrix.node-version == '14.x' }}
# run: ./scripts/publish-site
# env:
# GH_TOKEN_PUBLIC: ${{ secrets.GH_TOKEN_PUBLIC }}
# GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}
# GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}
- name: update website
if: ${{ github.event_name == 'push' && matrix.node-version == '14.x' }}
run: ./scripts/publish-site
env:
GH_TOKEN_PUBLIC: ${{ secrets.GH_TOKEN_PUBLIC }}
GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }}
GIT_USER_NAME: ${{ secrets.GIT_USER_NAME }}
- run: npm run build
- run: npm run test-ci
- name: coveralls
24 changes: 6 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -15,27 +15,13 @@ Supports JSON Schema draft-04/06/07/2019-09/2020-12 ([draft-04 support](https://
[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)
[![GitHub Sponsors](https://img.shields.io/badge/$-sponsors-brightgreen)](https://github.com/sponsors/epoberezkin)

## Platinum sponsors
## Ajv sponsors

[<img src="https://ajv.js.org/img/mozilla.svg" width="45%">](https://www.mozilla.org)<img src="https://ajv.js.org/img/gap.svg" width="8%">[<img src="https://ajv.js.org/img/reserved.svg" width="45%">](https://opencollective.com/ajv)
[<img src="https://ajv.js.org/img/mozilla.svg" width="45%" alt="Mozilla">](https://www.mozilla.org)<img src="https://ajv.js.org/img/gap.svg" width="9%">[<img src="https://ajv.js.org/img/reserved.svg" width="45%">](https://opencollective.com/ajv)

## Ajv online event - May 20, 10am PT / 6pm UK
[<img src="https://ajv.js.org/img/microsoft.png" width="31%" alt="Microsoft">](https://opensource.microsoft.com)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/reserved.svg" width="31%">](https://opencollective.com/ajv)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/reserved.svg" width="31%">](https://opencollective.com/ajv)

We will talk about:
- new features of Ajv version 8.
- the improvements sponsored by Mozilla's MOSS grant.
- how Ajv is used in JavaScript applications.

Speakers:
- [Evgeny Poberezkin](https://github.com/epoberezkin), the creator of Ajv.
- [Mehan Jayasuriya](https://github.com/mehan), Program Officer at Mozilla Foundation, leading the [MOSS](https://www.mozilla.org/en-US/moss/) and other programs investing in the open source and community ecosystems.
- [Matteo Collina](https://github.com/mcollina), Technical Director at NearForm and Node.js Technical Steering Committee member, creator of Fastify web framework.
- [Kin Lane](https://github.com/kinlane), Chief Evangelist at Postman. Studying the tech, business & politics of APIs since 2010. Presidential Innovation Fellow during the Obama administration.
- [Ulysse Carion](https://github.com/ucarion), the creator of JSON Type Definition specification.

[Gajus Kuizinas](https://github.com/gajus) will host the event.

Please [register here](https://us02web.zoom.us/webinar/register/2716192553618/WN_erJ_t4ICTHOnGC1SOybNnw).
[<img src="https://ajv.js.org/img/retool.svg" width="22.5%" alt="Retool">](https://retool.com/?utm_source=sponsor&utm_campaign=ajv)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/tidelift.svg" width="22.5%" alt="Tidelift">](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=enterprise)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/reserved.svg" width="22.5%">](https://opencollective.com/ajv)<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/reserved.svg" width="22.5%">](https://opencollective.com/ajv)

## Contributing

@@ -84,6 +70,8 @@ Thank you.
<a href="https://opencollective.com/ajv/organization/7/website"><img src="https://opencollective.com/ajv/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/8/website"><img src="https://opencollective.com/ajv/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/9/website"><img src="https://opencollective.com/ajv/organization/9/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/10/website"><img src="https://opencollective.com/ajv/organization/10/avatar.svg"></a>
<a href="https://opencollective.com/ajv/organization/11/website"><img src="https://opencollective.com/ajv/organization/11/avatar.svg"></a>

## Performance

63 changes: 51 additions & 12 deletions docs/.vuepress/components/Sponsors.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,68 @@
<template>
<div class="sponsors">
<div class="sponsors" :class="level">
<slot />
</div>
</template>

<script>
export default {
props: {
level: {
type: String,
},
},
}
</script>

<style lang="stylus" scoped>
.sponsors
max-width 800px
margin 0 auto
h2
margin-left 0
text-decoration none
a.header-anchor
width auto
margin-right 0
p
font-size 24px
img
width 100%
&.platinum, &.gold, &.bronze
img
width 100%
a
margin-bottom 10px
display inline-block
@media only screen and (min-width: $MQMobileNarrow)
margin-bottom 0
a:last-child
margin-right 0
&.platinum
a
width 100%
display block
@media only screen and (min-width: $MQMobileNarrow)
display inline-block
width 45%
margin-right 8%
a
width 100%
display block
margin-bottom 10px
@media only screen and (min-width: $MQMobileNarrow)
&.gold
a
width 45%
display inline-block
margin-bottom 0
margin-right 4%
@media only screen and (min-width: $MQMobileNarrow)
width 31%
margin-right 2%
&.bronze
a
width 45%
margin-right 4%
@media only screen and (min-width: $MQMobileNarrow)
width 22%
margin-right 3%
a:first-child
margin-right 8%
</style>
Binary file added docs/.vuepress/public/img/microsoft.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/.vuepress/public/img/retool.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/.vuepress/public/img/retool.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions docs/.vuepress/public/img/tidelift.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 20 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -34,14 +34,32 @@ Use JSON Type Definition or JSON Schema
</Feature>
</Features>

<Sponsors>
<Sponsors level="platinum">

Platinum sponsors
## Ajv sponsors

[![mozilla](/img/mozilla.svg)](https://www.mozilla.org)
[![reserved](/img/reserved.svg)](https://opencollective.com/ajv)

</Sponsors>

<Sponsors level="gold">

[![microsoft](/img/microsoft.png)](https://opensource.microsoft.com)
[![reserved](/img/reserved.svg)](https://opencollective.com/ajv)
[![reserved](/img/reserved.svg)](https://opencollective.com/ajv)

</Sponsors>

<Sponsors level="bronze">

[![retool](/img/retool.svg)](https://retool.com/?utm_source=sponsor&utm_campaign=ajv)
[![tidelift](/img/tidelift.svg)](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=npm-ajv&utm_medium=referral&utm_campaign=enterprise)
[![reserved](/img/reserved.svg)](https://opencollective.com/ajv)
[![reserved](/img/reserved.svg)](https://opencollective.com/ajv)

</Sponsors>

</HeroSection>

<HomeSection>
9 changes: 7 additions & 2 deletions docs/guide/typescript.md
Original file line number Diff line number Diff line change
@@ -132,15 +132,20 @@ const validData = {
bar: "abc"
}

if (validate(data)) {
if (validate(validData)) {
// data is MyData here
console.log(data.foo)
console.log(validData.foo)
} else {
console.log(validate.errors)
}
```
</code-block>
</code-group>


::: warning TypeScript limitation
Note that it's currently not possible for `JTDDataType` to know whether the compiler is inferring timestamps as strings or Dates, and so it conservatively types any timestamp as `string | Date`. This is accurate, but often requires extra validation on the part of the user to confirm they're getting the appropriate data type.
:::

## Type-safe error handling

Binary file modified docs/projects/tsed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion lib/vocabularies/applicator/contains.ts
Original file line number Diff line number Diff line change
@@ -65,11 +65,19 @@ const def: CodeKeywordDefinition = {
validateItems(valid, () => gen.if(valid, () => gen.break()))
} else {
gen.let(valid, false)
if (min === 0) {
gen.if(_`${data}.length > 0`, validateItemsWithCount, () => gen.assign(valid, true))
} else {
validateItemsWithCount()
}
}
cxt.result(valid, () => cxt.reset())

function validateItemsWithCount(): void {
const schValid = gen.name("_valid")
const count = gen.let("count", 0)
validateItems(schValid, () => gen.if(schValid, () => checkLimits(count)))
}
cxt.result(valid, () => cxt.reset())

function validateItems(_valid: Name, block: () => void): void {
gen.forRange("i", 0, len, (i) => {
18 changes: 8 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ajv",
"version": "8.6.3",
"version": "8.7.0",
"description": "Another JSON Schema Validator",
"main": "dist/ajv.js",
"types": "dist/ajv.d.ts",
@@ -10,10 +10,10 @@
".runkit_example.js"
],
"scripts": {
"eslint": "eslint \"lib/**/*.ts\" \"spec/**/*.*s\" scripts --ignore-pattern spec/JSON-Schema-Test-Suite",
"eslint": "eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite",
"prettier:write": "prettier --write \"./**/*.{json,yaml,js,ts}\"",
"prettier:check": "prettier --list-different \"./**/*.{json,yaml,js,ts}\"",
"test-spec": "cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot -g \\(.recursiveRef.with.no..recursiveAnchor\\|.dynamicRef.with.no..dynamicAnchor\\).in.the.initial.target.schema.resource -i",
"test-spec": "cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot",
"test-codegen": "nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec",
"test-debug": "npm run test-spec -- --inspect-brk",
"test-cov": "nyc npm run test-spec",
@@ -23,10 +23,10 @@
"test-karma": "karma start",
"test-browser": "rm -rf .browser && npm run bundle && scripts/prepare-tests && karma start",
"test-all": "npm run test-cov && if-node-version 12 npm run test-browser",
"test": "npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link ajv && npm run test-cov",
"test": "npm run json-tests && npm run prettier:check && npm run eslint && npm link && npm link --legacy-peer-deps ajv && npm run test-cov",
"test-ci": "AJV_FULL_TEST=true npm test",
"prepublish": "npm run build",
"benchmark": "npm i && npm run build && npm link && cd ./benchmark && npm link ajv && npm i && node ./jtd",
"benchmark": "npm i && npm run build && npm link && cd ./benchmark && npm link --legacy-peer-deps ajv && npm i && node ./jtd",
"docs:dev": "./scripts/prepare-site && vuepress dev docs",
"docs:build": "./scripts/prepare-site && vuepress build docs"
},
@@ -64,7 +64,7 @@
},
"devDependencies": {
"@ajv-validator/config": "^0.3.0",
"@rollup/plugin-commonjs": "^20.0.0",
"@rollup/plugin-commonjs": "^21.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-typescript": "^8.2.1",
@@ -74,8 +74,7 @@
"@types/require-from-string": "^1.2.0",
"@typescript-eslint/eslint-plugin": "^3.8.0",
"@typescript-eslint/parser": "^3.8.0",
"@vuepress/shared-utils": "^1.8.2",
"ajv-formats": "^2.0.0",
"ajv-formats": "^3.0.0-rc.0",
"chai": "^4.0.1",
"cross-env": "^7.0.2",
"dayjs": "^1.10.4",
@@ -100,8 +99,7 @@
"rollup-plugin-terser": "^7.0.2",
"ts-node": "^10.0.0",
"tsify": "^5.0.2",
"typescript": "^4.2.0",
"vuepress": "^1.8.2"
"typescript": "^4.2.0"
},
"collective": {
"type": "opencollective",
7 changes: 4 additions & 3 deletions scripts/get-contributors.js
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@
// https://github.com/sveltejs/svelte/blob/ce3a5791258ec6ecf8c1ea022cb871afe805a45c/site/scripts/get-contributors.js

const fs = require("fs")
const fetch = require("node-fetch")
const Jimp = require("jimp")

process.chdir(__dirname)
@@ -12,7 +11,11 @@ const {GH_TOKEN_PUBLIC} = process.env

const SIZE = 64

main()

async function main() {
const fetch = (await import("node-fetch")).default

const contributors = []
let page = 1

@@ -53,5 +56,3 @@ async function main() {
`module.exports = ${str}`
)
}

main()
2 changes: 2 additions & 0 deletions scripts/publish-site
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@ set -ex
echo "About to publish $GITHUB_REF to gh-pages..."
rm -rf ../gh-pages

npm install vuepress@1
npm install @vuepress/shared-utils@1
npm run docs:build

git config --global user.name "$GIT_USER_NAME"
2 changes: 1 addition & 1 deletion spec/JSON-Schema-Test-Suite
237 changes: 207 additions & 30 deletions spec/json-schema.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type Ajv from "../dist/core"
import _Ajv from "./ajv"
import _Ajv2019 from "./ajv2019"
import _Ajv2020 from "./ajv2020"
@@ -24,69 +25,211 @@ const remoteRefs = {

const SKIP_FORMATS = ["idn-email", "idn-hostname", "iri", "iri-reference"]
const SKIP_FORMAT_TESTS = SKIP_FORMATS.map((f) => `optional/format/${f}`)
const SKIP_DRAFT7 = ["optional/content", "optional/float-overflow", ...SKIP_FORMAT_TESTS]
const SKIP_DRAFT7 = [
"optional/content",
"optional/float-overflow",
"unknownKeyword",
...SKIP_FORMAT_TESTS,
]

const SKIP = {
6: ["optional/float-overflow"],
7: SKIP_DRAFT7,
2019: SKIP_DRAFT7, // TODO: 2 of 32 tests in recursiveRef fail
2020: SKIP_DRAFT7, // TODO: 2 of 32 tests in dynamicRef fail
}

runTest(
getAjvInstances(_Ajv, options, {
runTest({
instances: getAjvInstances(_Ajv, options, {
meta: false,
strict: false,
ignoreKeywordsWithRef: true,
}),
6,
require("./_json/draft6")
)
draft: 6,
tests: skipTestCases(require("./_json/draft6"), {
ref: {
"$ref prevents a sibling $id from changing the base uri": [
"$ref resolves to /definitions/base_foo, data does not validate",
"$ref resolves to /definitions/base_foo, data validates",
],
},
}),
remotes: {
"http://localhost:1234/ref-and-definitions.json": require("./JSON-Schema-Test-Suite/remotes/ref-and-definitions.json"),
},
skip: ["optional/float-overflow", "unknownKeyword"],
})

runTest(
getAjvInstances(_Ajv, options, {
runTest({
instances: getAjvInstances(_Ajv, options, {
strict: false,
ignoreKeywordsWithRef: true,
formats: toHash(SKIP_FORMATS),
}),
7,
require("./_json/draft7")
)
draft: 7,
tests: skipTestCases(require("./_json/draft7"), {
ref: {
"$ref prevents a sibling $id from changing the base uri": [
"$ref resolves to /definitions/base_foo, data does not validate",
"$ref resolves to /definitions/base_foo, data validates",
],
},
}),
remotes: {
"http://localhost:1234/ref-and-definitions.json": require("./JSON-Schema-Test-Suite/remotes/ref-and-definitions.json"),
},
skip: SKIP_DRAFT7,
})

runTest(
getAjvInstances(_Ajv2019, options, {
runTest({
instances: getAjvInstances(_Ajv2019, options, {
strict: false,
formats: toHash(SKIP_FORMATS),
}),
2019,
require("./_json/draft2019")
)
draft: 2019,
tests: skipTestCases(require("./_json/draft2019"), {
recursiveRef: {
"$recursiveRef with no $recursiveAnchor in the initial target schema resource": [
"leaf node matches: recursion uses the inner schema",
"leaf node does not match: recursion uses the inner schema",
],
},
ref: {
"refs with relative uris and defs": [
"invalid on inner field",
"invalid on outer field",
"valid on both fields",
],
"relative refs with absolute uris and defs": [
"invalid on inner field",
"invalid on outer field",
"valid on both fields",
],
},
unevaluatedProperties: {
"unevaluatedProperties with if/then/else, then not defined": [
"when if is false and has unevaluated properties",
],
},
}),
remotes: {
"http://localhost:1234/ref-and-defs.json": require("./JSON-Schema-Test-Suite/remotes/ref-and-defs.json"),
"http://localhost:1234/draft2019-09/metaschema-no-validation.json": require("./JSON-Schema-Test-Suite/remotes/draft2019-09/metaschema-no-validation.json"),
},
skip: SKIP_DRAFT7,
})

runTest(
getAjvInstances(_Ajv2020, options, {
runTest({
instances: getAjvInstances(_Ajv2020, options, {
strict: false,
formats: toHash(SKIP_FORMATS),
}),
2020,
require("./_json/draft2020")
)
draft: 2020,
tests: skipTestCases(require("./_json/draft2020"), {
dynamicRef: {
"A $dynamicRef to a $dynamicAnchor in the same schema resource should behave like a normal $ref to an $anchor":
["An array of strings is valid"],
"A $dynamicRef to an $anchor in the same schema resource should behave like a normal $ref to an $anchor":
["An array of strings is valid"],
"A $dynamicRef should resolve to the first $dynamicAnchor still in scope that is encountered when the schema is evaluated":
["An array of strings is valid"],
"A $dynamicRef with intermediate scopes that don't include a matching $dynamicAnchor should not affect dynamic scope resolution":
["An array of strings is valid"],
"An $anchor with the same name as a $dynamicAnchor should not be used for dynamic scope resolution":
["Any array is valid"],
"A $dynamicRef without a matching $dynamicAnchor in the same schema resource should behave like a normal $ref to $anchor":
["Any array is valid"],
"A $dynamicRef with a non-matching $dynamicAnchor in the same schema resource should behave like a normal $ref to $anchor":
["Any array is valid"],
"A $dynamicRef that initially resolves to a schema with a matching $dynamicAnchor should resolve to the first $dynamicAnchor in the dynamic scope":
[
"The recursive part is valid against the root",
"The recursive part is not valid against the root",
],
"A $dynamicRef that initially resolves to a schema without a matching $dynamicAnchor should behave like a normal $ref to $anchor":
["The recursive part doesn't need to validate against the root"],
"after leaving a dynamic scope, it should not be used by a $dynamicRef": [
"string matches /$defs/thingy, but the $dynamicRef does not stop here",
"first_scope is not in dynamic scope for the $dynamicRef",
"/then/$defs/thingy is the final stop for the $dynamicRef",
],
"strict-tree schema, guards against misspelled properties": [
"instance with misspelled field",
"instance with correct field",
],
"tests for implementation dynamic anchor and reference link": [
"incorrect parent schema",
"incorrect extended schema",
"correct extended schema",
],
// duplicate
"Tests for implementation dynamic anchor and reference link. Reference should be independent of any possible ordering.":
["incorrect parent schema", "incorrect extended schema", "correct extended schema"],
},
ref: {
"refs with relative uris and defs": [
"invalid on inner field",
"invalid on outer field",
"valid on both fields",
],
"relative refs with absolute uris and defs": [
"invalid on inner field",
"invalid on outer field",
"valid on both fields",
],
},
unevaluatedItems: {
"unevaluatedItems depends on adjacent contains": [
"contains passes, second item is not evaluated",
],
"unevaluatedItems depends on multiple nested contains": [
"7 not evaluated, fails unevaluatedItems",
],
"unevaluatedItems and contains interact to control item dependency relationship": [
"only b's are invalid",
"only c's are invalid",
"only b's and c's are invalid",
"only a's and c's are invalid",
],
},
unevaluatedProperties: {
"unevaluatedProperties with if/then/else, then not defined": [
"when if is false and has unevaluated properties",
],
},
}),
remotes: {
"http://localhost:1234/ref-and-defs.json": require("./JSON-Schema-Test-Suite/remotes/ref-and-defs.json"),
"http://localhost:1234/draft2020-12/format-assertion-false.json": require("./JSON-Schema-Test-Suite/remotes/draft2020-12/format-assertion-false.json"),
"http://localhost:1234/draft2020-12/format-assertion-true.json": require("./JSON-Schema-Test-Suite/remotes/draft2020-12/format-assertion-true.json"),
"http://localhost:1234/draft2020-12/metaschema-no-validation.json": require("./JSON-Schema-Test-Suite/remotes/draft2020-12/metaschema-no-validation.json"),
},
skip: [...SKIP_DRAFT7, "optional/format-assertion"],
})

interface TestSuite {
name: string
test: any[]
}

function runTest(instances, draft: number, tests) {
interface SchemaTest {
instances: Ajv[]
draft: number
tests: TestSuite[]
skip?: string[]
remotes?: Record<string, any>
}

function runTest({instances, draft, tests, skip = [], remotes = {}}: SchemaTest) {
for (const ajv of instances) {
ajv.opts.code.source = true
if (draft === 6) {
ajv.addMetaSchema(draft6MetaSchema)
ajv.opts.defaultMeta = "http://json-schema.org/draft-06/schema#"
}
for (const id in remoteRefs) ajv.addSchema(remoteRefs[id], id)
for (const id in remotes) ajv.addSchema(remotes[id], id)
ajvFormats(ajv)
}

jsonSchemaTest(withStandalone(instances), {
description: `JSON-Schema Test Suite draft-${draft}: ${instances.length} ajv instances with different options`,
suites: {tests},
only: [],
skip: SKIP[draft],
skip,
assert: chai.assert,
afterError,
afterEach,
@@ -95,3 +238,37 @@ function runTest(instances, draft: number, tests) {
timeout: 30000,
})
}

interface SkippedTestCases {
[suite: string]: {
[test: string]: string[] | true
}
}

function skipTestCases(suites: TestSuite[], skipCases: SkippedTestCases): TestSuite[] {
for (const suiteName in skipCases) {
const suite = suites.find(({name}) => name === suiteName)
if (!suite) throw new Error(`test suite ${suiteName} not found`)
for (const testName in skipCases[suiteName]) {
const test = suite.test.find(({description}) => description === testName)
if (!test) {
throw new Error(`test ${testName} not found in suite ${suiteName}`)
}
const skippedCases = skipCases[suiteName][testName]
suite.test.forEach((t) => {
if (t.description === testName) {
if (skippedCases === true) {
t.skip = true
} else {
t.tests.forEach((testCase: any) => {
if (skippedCases.includes(testCase.description)) {
testCase.skip = true
}
})
}
}
})
}
}
return suites
}