From c1df9be9bf5e61946bf13ba0a53cc76e676469f6 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Fri, 30 Apr 2021 15:39:14 +0200 Subject: [PATCH] test(reference): add tests for OAS 3.1 external resolution Along with tests multiple bug fixes and smaller refactors have been introduced. Closes #307 --- .../strategies/openapi-3-1/visitor.ts | 38 +- .../resolve/strategies/openapi-3-1/util.ts | 37 ++ .../resolve/strategies/openapi-3-1/visitor.ts | 10 +- .../openapi-3-1/schema-object/index.ts | 21 + .../asyncapi-2-0/reference-object/index.ts | 29 +- .../openapi-3-1/reference-object/index.ts | 29 +- .../fixtures/$anchor-external/ex.json | 15 + .../fixtures/$anchor-external/root.json | 21 + .../fixtures/$anchor-internal/root.json | 32 ++ .../fixtures/$anchor-not-found/root.json | 21 + .../fixtures/$id-unresolvable/root.json | 23 + .../fixtures/$id-uri-direct/nested/ex.json | 8 + .../fixtures/$id-uri-direct/root.json | 22 + .../fixtures/$id-uri-enclosing/nested/ex.json | 8 + .../fixtures/$id-uri-enclosing/root.json | 22 + .../fixtures/$id-uri-external/nested/ex.json | 8 + .../$id-uri-external/nested/nested/ex.json | 8 + .../fixtures/$id-uri-external/root.json | 21 + .../fixtures/$schema-defined/root.json | 31 ++ .../fixtures/$schema-enclosing/root.json | 30 ++ .../fixtures/$schema-mixed/root.json | 31 ++ .../fixtures/$schema-undefined/root.json | 29 ++ .../fixtures/$schema-unrecognized/root.json | 31 ++ .../fixtures/cycle-external/ex.json | 11 + .../fixtures/cycle-external/root.json | 15 + .../fixtures/cycle-internal-external/ex.json | 11 + .../cycle-internal-external/root.json | 16 + .../fixtures/cycle-internal/root.json | 15 + .../fixtures/direct-external-circular/ex.json | 7 + .../direct-external-circular/root.json | 10 + .../direct-internal-circular/root.json | 10 + .../fixtures/external-indirections/ex1.json | 7 + .../fixtures/external-indirections/ex2.json | 7 + .../fixtures/external-indirections/ex3.json | 8 + .../fixtures/external-indirections/root.json | 10 + .../fixtures/external-only/ex.json | 16 + .../fixtures/external-only/root.json | 15 + .../fixtures/ignore-external/ex.json | 8 + .../fixtures/ignore-external/root.json | 26 + .../indirect-external-circular/ex1.json | 7 + .../indirect-external-circular/ex2.json | 7 + .../indirect-external-circular/ex3.json | 7 + .../indirect-external-circular/root.json | 10 + .../indirect-internal-circular/root.json | 19 + .../fixtures/infinite-recursion/root.json | 15 + .../fixtures/internal-external/ex.json | 12 + .../fixtures/internal-external/root.json | 29 ++ .../fixtures/internal-only/root.json | 29 ++ .../fixtures/invalid-pointer/root.json | 11 + .../schema-object/fixtures/max-depth/ex1.json | 8 + .../schema-object/fixtures/max-depth/ex2.json | 8 + .../schema-object/fixtures/max-depth/ex3.json | 3 + .../fixtures/max-depth/root.json | 11 + .../fixtures/unresolvable-reference/root.json | 14 + .../openapi-3-1/schema-object/index.ts | 455 ++++++++++++++++++ 55 files changed, 1320 insertions(+), 42 deletions(-) create mode 100644 apidom/packages/apidom-reference/src/resolve/strategies/openapi-3-1/util.ts create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-external/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-external/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-internal/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-not-found/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-unresolvable/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-direct/nested/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-direct/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-enclosing/nested/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-enclosing/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/nested/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/nested/nested/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-defined/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-enclosing/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-mixed/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-undefined/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-unrecognized/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-external/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-external/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal-external/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal-external/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-external-circular/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-external-circular/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-internal-circular/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex1.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex2.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex3.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-only/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-only/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/ignore-external/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/ignore-external/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex1.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex2.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex3.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-internal-circular/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/infinite-recursion/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-external/ex.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-external/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-only/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/invalid-pointer/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex1.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex2.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex3.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/unresolvable-reference/root.json create mode 100644 apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/index.ts diff --git a/apidom/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts b/apidom/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts index e7fcaba459..4cad4c0818 100644 --- a/apidom/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts +++ b/apidom/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts @@ -1,5 +1,5 @@ import stampit from 'stampit'; -import { hasIn, pathSatisfies, propEq, reduceRight } from 'ramda'; +import { hasIn, pathSatisfies, propEq } from 'ramda'; import { isNotUndefined } from 'ramda-adjunct'; import { isPrimitiveElement, isStringElement, visit, Element } from 'apidom'; import { @@ -19,42 +19,14 @@ import { MaximumDereferenceDepthError, MaximumResolverDepthError } from '../../. import * as url from '../../../util/url'; import parse from '../../../parse'; import Reference from '../../../Reference'; +import { + resolveInherited$id, + refractToSchemaElement, +} from '../../../resolve/strategies/openapi-3-1/util'; // @ts-ignore const visitAsync = visit[Symbol.for('nodejs.util.promisify.custom')]; -/** - * Cached version of SchemaElement.refract. - */ -export const refractToSchemaElement = (element: T) => { - if (refractToSchemaElement.cache.has(element)) { - return refractToSchemaElement.cache.get(element); - } - - const refracted = SchemaElement.refract(element); - refractToSchemaElement.cache.set(element, refracted); - return refracted; -}; -refractToSchemaElement.cache = new WeakMap(); - -/** - * Folding of inherited$id list from right to left using - * URL resolving mechanism. - */ -export const resolveInherited$id = (schemaElement: SchemaElement) => - reduceRight( - ($id: string, acc: string): string => { - const uriWithoutHash = url.stripHash($id); - const sanitizedURI = url.isFileSystemPath(uriWithoutHash) - ? url.fromFileSystemPath(uriWithoutHash) - : uriWithoutHash; - - return url.resolve(sanitizedURI, acc); - }, - schemaElement.$ref?.toValue(), - schemaElement.meta.get('inherited$id').toValue(), - ); - const OpenApi3_1DereferenceVisitor = stampit({ props: { indirections: null, diff --git a/apidom/packages/apidom-reference/src/resolve/strategies/openapi-3-1/util.ts b/apidom/packages/apidom-reference/src/resolve/strategies/openapi-3-1/util.ts new file mode 100644 index 0000000000..235eaf119a --- /dev/null +++ b/apidom/packages/apidom-reference/src/resolve/strategies/openapi-3-1/util.ts @@ -0,0 +1,37 @@ +import { reduceRight } from 'ramda'; +import { Element } from 'apidom'; +import { SchemaElement } from 'apidom-ns-openapi-3-1'; + +import * as url from '../../../util/url'; + +/** + * Folding of inherited$id list from right to left using + * URL resolving mechanism. + */ +export const resolveInherited$id = (schemaElement: SchemaElement) => + reduceRight( + ($id: string, acc: string): string => { + const uriWithoutHash = url.stripHash($id); + const sanitizedURI = url.isFileSystemPath(uriWithoutHash) + ? url.fromFileSystemPath(uriWithoutHash) + : uriWithoutHash; + + return url.resolve(sanitizedURI, acc); + }, + schemaElement.$ref?.toValue(), + schemaElement.meta.get('inherited$id').toValue(), + ); + +/** + * Cached version of SchemaElement.refract. + */ +export const refractToSchemaElement = (element: T) => { + if (refractToSchemaElement.cache.has(element)) { + return refractToSchemaElement.cache.get(element); + } + + const refracted = SchemaElement.refract(element); + refractToSchemaElement.cache.set(element, refracted); + return refracted; +}; +refractToSchemaElement.cache = new WeakMap(); diff --git a/apidom/packages/apidom-reference/src/resolve/strategies/openapi-3-1/visitor.ts b/apidom/packages/apidom-reference/src/resolve/strategies/openapi-3-1/visitor.ts index 78c898c6fb..5a6fb434be 100644 --- a/apidom/packages/apidom-reference/src/resolve/strategies/openapi-3-1/visitor.ts +++ b/apidom/packages/apidom-reference/src/resolve/strategies/openapi-3-1/visitor.ts @@ -20,10 +20,7 @@ import * as url from '../../../util/url'; import parse from '../../../parse'; import Reference from '../../../Reference'; import { evaluate as jsonPointerEvaluate, uriToPointer } from '../../../selectors/json-pointer'; -import { - refractToSchemaElement, - resolveInherited$id, -} from '../../../dereference/strategies/openapi-3-1/visitor'; +import { refractToSchemaElement, resolveInherited$id } from './util'; import { evaluate as $anchorEvaluate, isAnchor, @@ -78,7 +75,10 @@ const OpenApi3_1ResolveVisitor = stampit({ return refSet.find(propEq('uri', baseURI)); } - const parseResult = await parse(baseURI, this.options); + const parseResult = await parse(baseURI, { + ...this.options, + parse: { ...this.options.parse, mediaType: 'text/plain' }, + }); // register new Reference with ReferenceSet const reference = Reference({ diff --git a/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/schema-object/index.ts b/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/schema-object/index.ts index 5d55d6f2b6..3c88d9cfac 100644 --- a/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/schema-object/index.ts +++ b/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/schema-object/index.ts @@ -7,6 +7,7 @@ import { dereference } from '../../../../../src'; import { DereferenceError, MaximumDereferenceDepthError, + MaximumResolverDepthError, ResolverError, } from '../../../../../src/util/errors'; import { loadJsonFile } from '../../../../helpers'; @@ -472,6 +473,26 @@ describe('dereference', function () { }); }); + context('given Reference Objects and maxDepth of resolution', function () { + const fixturePath = path.join(rootFixturePath, 'max-depth'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + + try { + await dereference(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + resolve: { maxDepth: 2 }, + }); + assert.fail('should throw MaximumResolverDepthError'); + } catch (error) { + assert.instanceOf(error, DereferenceError); + assert.instanceOf(error.cause.cause, MaximumResolverDepthError); + assert.match(error.cause.cause.message, /fixtures\/max-depth\/ex2.json"$/); + } + }); + }); + context('given Schema Objects with unresolvable reference', function () { const fixturePath = path.join(rootFixturePath, 'unresolvable-reference'); diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/asyncapi-2-0/reference-object/index.ts b/apidom/packages/apidom-reference/test/resolve/strategies/asyncapi-2-0/reference-object/index.ts index f1c1b99c87..a936376843 100644 --- a/apidom/packages/apidom-reference/test/resolve/strategies/asyncapi-2-0/reference-object/index.ts +++ b/apidom/packages/apidom-reference/test/resolve/strategies/asyncapi-2-0/reference-object/index.ts @@ -1,8 +1,13 @@ import path from 'path'; import { assert } from 'chai'; -import { resolve } from '../../../../../src'; -import { MaximumResolverDepthError, ResolverError } from '../../../../../src/util/errors'; +import { dereference, resolve } from '../../../../../src'; +import { + DereferenceError, + MaximumDereferenceDepthError, + MaximumResolverDepthError, + ResolverError, +} from '../../../../../src/util/errors'; const rootFixturePath = path.join(__dirname, 'fixtures'); @@ -179,6 +184,26 @@ describe('resolve', function () { }); }); + context('given Reference Objects and maxDepth of dereference', function () { + const fixturePath = path.join(rootFixturePath, 'max-depth'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + + try { + await dereference(rootFilePath, { + parse: { mediaType: 'application/vnd.aai.asyncapi+json;version=2.0.0' }, + dereference: { maxDepth: 2 }, + }); + assert.fail('should throw MaximumDereferenceDepthError'); + } catch (error) { + assert.instanceOf(error, DereferenceError); + assert.instanceOf(error.cause.cause, MaximumDereferenceDepthError); + assert.match(error.cause.cause.message, /fixtures\/max-depth\/ex2.json"$/); + } + }); + }); + context('given Reference Objects and maxDepth of resolution', function () { const fixturePath = path.join(rootFixturePath, 'max-depth'); diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/reference-object/index.ts b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/reference-object/index.ts index a7d2a336e2..5a3b3e9479 100644 --- a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/reference-object/index.ts +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/reference-object/index.ts @@ -1,8 +1,13 @@ import path from 'path'; import { assert } from 'chai'; -import { resolve } from '../../../../../src'; -import { MaximumResolverDepthError, ResolverError } from '../../../../../src/util/errors'; +import { dereference, resolve } from '../../../../../src'; +import { + MaximumResolverDepthError, + MaximumDereferenceDepthError, + ResolverError, + DereferenceError, +} from '../../../../../src/util/errors'; const rootFixturePath = path.join(__dirname, 'fixtures'); @@ -179,6 +184,26 @@ describe('resolve', function () { }); }); + context('given Reference Objects and maxDepth of dereference', function () { + const fixturePath = path.join(rootFixturePath, 'max-depth'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + + try { + await dereference(rootFilePath, { + parse: { mediaType: 'application/vnd.aai.asyncapi+json;version=2.0.0' }, + dereference: { maxDepth: 2 }, + }); + assert.fail('should throw MaximumDereferenceDepthError'); + } catch (error) { + assert.instanceOf(error, DereferenceError); + assert.instanceOf(error.cause.cause, MaximumDereferenceDepthError); + assert.match(error.cause.cause.message, /fixtures\/max-depth\/ex2.json"$/); + } + }); + }); + context('given Reference Objects and maxDepth of resolution', function () { const fixturePath = path.join(rootFixturePath, 'max-depth'); diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-external/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-external/ex.json new file mode 100644 index 0000000000..b32830bdc4 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-external/ex.json @@ -0,0 +1,15 @@ +{ + "$defs": { + "UserProfile": { + "$anchor": "user-profile", + "properties": { + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-external/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-external/root.json new file mode 100644 index 0000000000..5f55276688 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-external/root.json @@ -0,0 +1,21 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "./ex.json#user-profile" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-internal/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-internal/root.json new file mode 100644 index 0000000000..f9a30fb1ca --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-internal/root.json @@ -0,0 +1,32 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "#user-profile" + } + } + }, + "UserProfile": { + "$anchor": "user-profile", + "properties": { + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-not-found/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-not-found/root.json new file mode 100644 index 0000000000..f0f2dce912 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$anchor-not-found/root.json @@ -0,0 +1,21 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "#user-profile" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-unresolvable/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-unresolvable/root.json new file mode 100644 index 0000000000..a8a8381127 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-unresolvable/root.json @@ -0,0 +1,23 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$id": "./schemas/", + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$id": "./nested/", + "$ref": "./ex.json" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-direct/nested/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-direct/nested/ex.json new file mode 100644 index 0000000000..b7f7f6299c --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-direct/nested/ex.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-direct/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-direct/root.json new file mode 100644 index 0000000000..2c9fd869f7 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-direct/root.json @@ -0,0 +1,22 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$id": "./nested/", + "$ref": "./ex.json" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-enclosing/nested/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-enclosing/nested/ex.json new file mode 100644 index 0000000000..b7f7f6299c --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-enclosing/nested/ex.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-enclosing/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-enclosing/root.json new file mode 100644 index 0000000000..4c3fa339ca --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-enclosing/root.json @@ -0,0 +1,22 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$id": "./nested/", + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "./ex.json" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/nested/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/nested/ex.json new file mode 100644 index 0000000000..d5a6ae02c1 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/nested/ex.json @@ -0,0 +1,8 @@ +{ + "$defs": { + "UserProfile": { + "$id": "./nested/", + "$ref": "./ex.json" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/nested/nested/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/nested/nested/ex.json new file mode 100644 index 0000000000..b7f7f6299c --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/nested/nested/ex.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/root.json new file mode 100644 index 0000000000..ede427d60e --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$id-uri-external/root.json @@ -0,0 +1,21 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "./nested/ex.json#/$defs/UserProfile" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-defined/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-defined/root.json new file mode 100644 index 0000000000..34af5e8ce4 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-defined/root.json @@ -0,0 +1,31 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$schema": "https://spec.openapis.org/oas/3.1/dialect/base", + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + }, + "UserProfile": { + "$schema": "https://spec.openapis.org/oas/3.1/dialect/base", + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-enclosing/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-enclosing/root.json new file mode 100644 index 0000000000..2d4f976f0a --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-enclosing/root.json @@ -0,0 +1,30 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + }, + "UserProfile": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-mixed/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-mixed/root.json new file mode 100644 index 0000000000..dd3b4c451b --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-mixed/root.json @@ -0,0 +1,31 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + }, + "UserProfile": { + "$schema": "https://spec.openapis.org/oas/3.1/dialect/base", + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-undefined/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-undefined/root.json new file mode 100644 index 0000000000..0360dcac66 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-undefined/root.json @@ -0,0 +1,29 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + }, + "UserProfile": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-unrecognized/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-unrecognized/root.json new file mode 100644 index 0000000000..2eb3753431 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/$schema-unrecognized/root.json @@ -0,0 +1,31 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$schema": "https://www.google.com/", + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + }, + "UserProfile": { + "$schema": "https://www.google.com/", + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-external/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-external/ex.json new file mode 100644 index 0000000000..3867c3eeb0 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-external/ex.json @@ -0,0 +1,11 @@ +{ + "$defs": { + "UserProfile": { + "properties": { + "parent": { + "$ref": "#/$defs/UserProfile" + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-external/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-external/root.json new file mode 100644 index 0000000000..15ee3edf1c --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-external/root.json @@ -0,0 +1,15 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "profile": { + "$ref": "./ex.json#/$defs/UserProfile" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal-external/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal-external/ex.json new file mode 100644 index 0000000000..9251c7a6f9 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal-external/ex.json @@ -0,0 +1,11 @@ +{ + "$defs": { + "UserProfile": { + "properties": { + "user": { + "$ref": "./root.json#/components/schemas/User" + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal-external/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal-external/root.json new file mode 100644 index 0000000000..00f24682e8 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal-external/root.json @@ -0,0 +1,16 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "x-track": "1", + "properties": { + "profile": { + "$ref": "./ex.json#/$defs/UserProfile" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal/root.json new file mode 100644 index 0000000000..badb77703d --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/cycle-internal/root.json @@ -0,0 +1,15 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "parent": { + "$ref": "#/components/schemas/User" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-external-circular/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-external-circular/ex.json new file mode 100644 index 0000000000..33dfbc1e5d --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-external-circular/ex.json @@ -0,0 +1,7 @@ +{ + "$defs": { + "User": { + "$ref": "./root.json#/components/schemas/User" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-external-circular/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-external-circular/root.json new file mode 100644 index 0000000000..a5138ec7bc --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-external-circular/root.json @@ -0,0 +1,10 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$ref": "./ex.json#/$defs/User" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-internal-circular/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-internal-circular/root.json new file mode 100644 index 0000000000..fedad74def --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/direct-internal-circular/root.json @@ -0,0 +1,10 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$ref": "#/components/schemas/User" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex1.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex1.json new file mode 100644 index 0000000000..b36a740b4a --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex1.json @@ -0,0 +1,7 @@ +{ + "$defs": { + "Indirection": { + "$ref": "./ex2.json#/$defs/Indirection" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex2.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex2.json new file mode 100644 index 0000000000..fde1576500 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex2.json @@ -0,0 +1,7 @@ +{ + "$defs": { + "Indirection": { + "$ref": "./ex3.json" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex3.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex3.json new file mode 100644 index 0000000000..c27dc30383 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/ex3.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "properties": { + "prop1": { + "type": "string" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/root.json new file mode 100644 index 0000000000..c4b862d724 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-indirections/root.json @@ -0,0 +1,10 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "Indirection": { + "$ref": "./ex1.json#/$defs/Indirection" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-only/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-only/ex.json new file mode 100644 index 0000000000..c115310b05 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-only/ex.json @@ -0,0 +1,16 @@ +{ + "type": "object", + "$defs": { + "UserProfile": { + "type": "object", + "properties": { + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-only/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-only/root.json new file mode 100644 index 0000000000..15ee3edf1c --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/external-only/root.json @@ -0,0 +1,15 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "profile": { + "$ref": "./ex.json#/$defs/UserProfile" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/ignore-external/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/ignore-external/ex.json new file mode 100644 index 0000000000..fc8a07edcd --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/ignore-external/ex.json @@ -0,0 +1,8 @@ +{ + "externalParameter": { + "name": "externalParameter", + "in": "query", + "description": "this is parameter stored in external file", + "required": true + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/ignore-external/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/ignore-external/root.json new file mode 100644 index 0000000000..b58b884fd6 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/ignore-external/root.json @@ -0,0 +1,26 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + }, + "UserProfile": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } + }, + "Order": { + "$ref": "./ex.json" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex1.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex1.json new file mode 100644 index 0000000000..cb58d6153f --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex1.json @@ -0,0 +1,7 @@ +{ + "$defs": { + "User": { + "$ref": "./ex2.json#/$defs/User" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex2.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex2.json new file mode 100644 index 0000000000..556373d11d --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex2.json @@ -0,0 +1,7 @@ +{ + "$defs": { + "User": { + "$ref": "./ex3.json#/$defs/User" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex3.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex3.json new file mode 100644 index 0000000000..33dfbc1e5d --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/ex3.json @@ -0,0 +1,7 @@ +{ + "$defs": { + "User": { + "$ref": "./root.json#/components/schemas/User" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/root.json new file mode 100644 index 0000000000..041b79aa73 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-external-circular/root.json @@ -0,0 +1,10 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$ref": "./ex1.json#/$defs/User" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-internal-circular/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-internal-circular/root.json new file mode 100644 index 0000000000..460612050d --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/indirect-internal-circular/root.json @@ -0,0 +1,19 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "$ref": "#/components/schemas/Indirection1" + }, + "Indirection1": { + "$ref": "#/components/schemas/Indirection2" + }, + "Indirection3": { + "$ref": "#/components/schemas/Indirection3" + }, + "Indirection4": { + "$ref": "#/components/schemas/User" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/infinite-recursion/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/infinite-recursion/root.json new file mode 100644 index 0000000000..145ae4496d --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/infinite-recursion/root.json @@ -0,0 +1,15 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "$ref": "#/components/schemas/UserProfile" + }, + "UserProfile": { + "type": "object", + "$ref": "#/components/schemas/User" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-external/ex.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-external/ex.json new file mode 100644 index 0000000000..8386ec5706 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-external/ex.json @@ -0,0 +1,12 @@ +{ + "$defs": { + "Order": { + "type": "object", + "properties": { + "orderId": { + "type": "number" + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-external/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-external/root.json new file mode 100644 index 0000000000..24c9fa2471 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-external/root.json @@ -0,0 +1,29 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + }, + "UserProfile": { + "type": "object", + "properties": { + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + } + } + }, + "Order": { + "$ref": "./ex.json#/$defs/Order" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-only/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-only/root.json new file mode 100644 index 0000000000..0360dcac66 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/internal-only/root.json @@ -0,0 +1,29 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + }, + "UserProfile": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/invalid-pointer/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/invalid-pointer/root.json new file mode 100644 index 0000000000..4a8c563523 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/invalid-pointer/root.json @@ -0,0 +1,11 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "$ref": "#/components/schemas/invalid-pointer" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex1.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex1.json new file mode 100644 index 0000000000..7de8b6d855 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex1.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "$defs": { + "Indirection": { + "$ref": "./ex2.json#/$defs/Indirection" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex2.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex2.json new file mode 100644 index 0000000000..39ed0289dd --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex2.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "$defs": { + "Indirection": { + "$ref": "./ex3.json" + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex3.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex3.json new file mode 100644 index 0000000000..e6307dc1c6 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/ex3.json @@ -0,0 +1,3 @@ +{ + "type": "object" +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/root.json new file mode 100644 index 0000000000..c20c6b510d --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/max-depth/root.json @@ -0,0 +1,11 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "type": "object", + "$ref": "./ex1.json#/$defs/Indirection" + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/unresolvable-reference/root.json b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/unresolvable-reference/root.json new file mode 100644 index 0000000000..6269b86390 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/fixtures/unresolvable-reference/root.json @@ -0,0 +1,14 @@ +{ + "openapi": "3.1.0", + "components": { + "schemas": { + "User": { + "properties": { + "profile": { + "$ref": "#/components/schemas/UserProfile" + } + } + } + } + } +} diff --git a/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/index.ts b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/index.ts new file mode 100644 index 0000000000..578c580205 --- /dev/null +++ b/apidom/packages/apidom-reference/test/resolve/strategies/openapi-3-1/schema-object/index.ts @@ -0,0 +1,455 @@ +import path from 'path'; +import { assert } from 'chai'; + +import { resolve } from '../../../../../src'; +import { + MaximumDereferenceDepthError, + MaximumResolverDepthError, + ResolverError, +} from '../../../../../src/util/errors'; +import { EvaluationJsonSchema$anchorError } from '../../../../../src/dereference/strategies/openapi-3-1/selectors/errors'; + +const rootFixturePath = path.join(__dirname, 'fixtures'); + +describe('resolve', function () { + context('strategies', function () { + context('openapi-3-1', function () { + context('Schema Object - $ref keyword from core vocabulary', function () { + context('given Reference Objects pointing internally and externally', function () { + const fixturePath = path.join(rootFixturePath, 'internal-external'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 2); + }); + }); + + context('given Schema Objects pointing internally only', function () { + const fixturePath = path.join(rootFixturePath, 'internal-only'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }); + + context('given Schema Objects with internal cycles', function () { + const fixturePath = path.join(rootFixturePath, 'cycle-internal'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }); + + context('given Schema Objects with external cycles', function () { + const fixturePath = path.join(rootFixturePath, 'cycle-external'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 2); + }); + }); + + context('given Schema Objects with internal and external cycles', function () { + const fixturePath = path.join(rootFixturePath, 'cycle-internal-external'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 2); + }); + }); + + context('given Schema Objects with external resolution disabled', function () { + const fixturePath = path.join(rootFixturePath, 'ignore-external'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + resolve: { external: false }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }); + + context('given Schema Objects pointing externally only', function () { + const fixturePath = path.join(rootFixturePath, 'external-only'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 2); + }); + }); + + context('given Schema Objects pointing to external indirections', function () { + const fixturePath = path.join(rootFixturePath, 'external-indirections'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 4); + }); + }); + + context('given Schema Objects with $schema keyword defined', function () { + const fixturePath = path.join(rootFixturePath, '$schema-defined'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }); + + context( + 'given Schema Objects with $schema keyword defined in enclosing Schema Object', + function () { + specify('should resolve', async function () { + const fixturePath = path.join(rootFixturePath, '$schema-enclosing'); + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }, + ); + + context('given Schema Objects with mixed $schema keyword defined', function () { + const fixturePath = path.join(rootFixturePath, '$schema-mixed'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }); + + context('given Schema Objects with undefined $schema keyword', function () { + specify('should resolve', async function () { + const fixturePath = path.join(rootFixturePath, '$schema-undefined'); + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }); + + context('given Schema Objects with unrecognized $schema keyword defined', function () { + const fixturePath = path.join(rootFixturePath, '$schema-unrecognized'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }); + + context( + 'given Schema Objects with $id keyword defined directly in referencing Schema Object', + function () { + const fixturePath = path.join(rootFixturePath, '$id-uri-direct'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 2); + }); + }, + ); + + context( + 'given Schema Objects with $id keyword defined in enclosing Schema Object', + function () { + const fixturePath = path.join(rootFixturePath, '$id-uri-enclosing'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 2); + }); + }, + ); + + context('given Schema Objects with $id keyword pointing to external files', function () { + const fixturePath = path.join(rootFixturePath, '$id-uri-external'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 3); + }); + }); + + context('given Schema Objects with unresolvable $id values', function () { + const fixturePath = path.join(rootFixturePath, '$id-unresolvable'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (error) { + assert.instanceOf(error, ResolverError); + assert.instanceOf(error.cause.cause, ResolverError); + assert.match(error.cause.cause.message, /\/schemas\/nested\/ex\.json"$/); + } + }); + }); + + context( + 'given Schema Objects with $anchor keyword pointing to internal schema', + function () { + const fixturePath = path.join(rootFixturePath, '$anchor-internal'); + + specify('should resolve', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 1); + }); + }, + ); + + context( + 'given Schema Objects with $anchor keyword pointing to external schema', + function () { + const fixturePath = path.join(rootFixturePath, '$anchor-external'); + + specify('should dereference', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const refSet = await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + + assert.strictEqual(refSet.size, 2); + }); + }, + ); + + context('given Schema Objects with not found $anchor', function () { + const fixturePath = path.join(rootFixturePath, '$anchor-not-found'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (error) { + assert.instanceOf(error, ResolverError); + assert.instanceOf(error.cause.cause, EvaluationJsonSchema$anchorError); + } + }); + }); + + context('given Schema Objects and maxDepth of dereference', function () { + const fixturePath = path.join(rootFixturePath, 'max-depth'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + dereference: { maxDepth: 2 }, + }); + assert.fail('should throw MaximumDereferenceDepthError'); + } catch (error) { + assert.instanceOf(error, ResolverError); + assert.instanceOf(error.cause.cause, MaximumDereferenceDepthError); + assert.match(error.cause.cause.message, /fixtures\/max-depth\/ex2.json"$/); + } + }); + }); + + context('given Reference Objects and maxDepth of resolution', function () { + const fixturePath = path.join(rootFixturePath, 'max-depth'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + resolve: { maxDepth: 2 }, + }); + assert.fail('should throw MaximumResolverDepthError'); + } catch (error) { + assert.instanceOf(error, ResolverError); + assert.instanceOf(error.cause.cause, MaximumResolverDepthError); + assert.match(error.cause.cause.message, /fixtures\/max-depth\/ex2.json"$/); + } + }); + }); + + context('given Schema Objects with unresolvable reference', function () { + const fixturePath = path.join(rootFixturePath, 'unresolvable-reference'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (e) { + assert.instanceOf(e, ResolverError); + } + }); + }); + + context('given Schema Objects with invalid JSON Pointer', function () { + const fixturePath = path.join(rootFixturePath, 'invalid-pointer'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (e) { + assert.instanceOf(e, ResolverError); + } + }); + }); + + context('given Schema Objects with infinite recursion', function () { + const fixturePath = path.join(rootFixturePath, 'infinite-recursion'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (e) { + assert.instanceOf(e, ResolverError); + } + }); + }); + + context('given Schema Objects with direct circular external reference', function () { + const fixturePath = path.join(rootFixturePath, 'direct-external-circular'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (e) { + assert.instanceOf(e, ResolverError); + } + }); + }); + + context('given Schema Objects with direct circular internal reference', function () { + const fixturePath = path.join(rootFixturePath, 'direct-internal-circular'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (e) { + assert.instanceOf(e, ResolverError); + } + }); + }); + + context('given Reference Objects with indirect circular external reference', function () { + const fixturePath = path.join(rootFixturePath, 'indirect-external-circular'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (e) { + assert.instanceOf(e, ResolverError); + } + }); + }); + + context('given Reference Objects with indirect circular internal reference', function () { + const fixturePath = path.join(rootFixturePath, 'indirect-internal-circular'); + + specify('should throw error', async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + try { + await resolve(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + assert.fail('should throw ResolverError'); + } catch (e) { + assert.instanceOf(e, ResolverError); + } + }); + }); + }); + }); + }); +});