diff --git a/packages/apidom-ns-openapi-2/src/elements/Header.ts b/packages/apidom-ns-openapi-2/src/elements/Header.ts index 69c990d53a..c228a495b2 100644 --- a/packages/apidom-ns-openapi-2/src/elements/Header.ts +++ b/packages/apidom-ns-openapi-2/src/elements/Header.ts @@ -216,28 +216,6 @@ class Header extends JSONSchemaElement { throw new UnsupportedOperationError('title setter in Header class is not not supported.'); } - get description(): StringElement | undefined { - return this.get('description'); - } - - set description(description: StringElement | undefined) { - this.set('description,', description); - } - - /** - * Semantic validation with "format" - * - * URI: https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-7 - */ - - get format(): StringElement | undefined { - return this.get('format'); - } - - set format(format: StringElement | undefined) { - this.set('format', format); - } - /** * JSON Hyper-Schema * diff --git a/packages/apidom-ns-openapi-2/src/elements/Items.ts b/packages/apidom-ns-openapi-2/src/elements/Items.ts index fca26bdae3..fea7c17bb4 100644 --- a/packages/apidom-ns-openapi-2/src/elements/Items.ts +++ b/packages/apidom-ns-openapi-2/src/elements/Items.ts @@ -219,20 +219,6 @@ class Items extends JSONSchemaElement { throw new UnsupportedOperationError('description setter in Items class is not not supported.'); } - /** - * Semantic validation with "format" - * - * URI: https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-7 - */ - - get format(): StringElement | undefined { - return this.get('format'); - } - - set format(format: StringElement | undefined) { - this.set('format', format); - } - /** * JSON Hyper-Schema * diff --git a/packages/apidom-ns-openapi-2/src/elements/Schema.ts b/packages/apidom-ns-openapi-2/src/elements/Schema.ts index bccefc0311..c1ecbfc0a3 100644 --- a/packages/apidom-ns-openapi-2/src/elements/Schema.ts +++ b/packages/apidom-ns-openapi-2/src/elements/Schema.ts @@ -1,12 +1,156 @@ -import { Attributes, Meta } from '@swagger-api/apidom-core'; -import { JSONSchemaElement } from '@swagger-api/apidom-ns-json-schema-draft-4'; +import { + Attributes, + Meta, + ArrayElement, + BooleanElement, + ObjectElement, + StringElement, +} from '@swagger-api/apidom-core'; +import { UnsupportedOperationError } from '@swagger-api/apidom-error'; +import { + JSONReferenceElement, + JSONSchemaElement, + MediaElement, +} from '@swagger-api/apidom-ns-json-schema-draft-4'; +/* eslint-disable class-methods-use-this */ class Schema extends JSONSchemaElement { constructor(content?: Record, meta?: Meta, attributes?: Attributes) { super(content, meta, attributes); this.element = 'schema'; this.classes.push('json-schema-draft-4'); } + + /** + * Core vocabulary + * + * URI: https://tools.ietf.org/html/draft-wright-json-schema-00 + */ + get idProp(): StringElement | undefined { + throw new UnsupportedOperationError('idProp getter in Schema class is not not supported.'); + } + + set idProp(idProps: StringElement | undefined) { + throw new UnsupportedOperationError('idProp setter in Schema class is not not supported.'); + } + + get $schema(): StringElement | undefined { + throw new UnsupportedOperationError('$schema getter in Schema class is not not supported.'); + } + + set $schema($schema: StringElement | undefined) { + throw new UnsupportedOperationError('$schema setter in Schema class is not not supported.'); + } + + /** + * Validation keywords for arrays + */ + + get additionalItems(): this | JSONReferenceElement | BooleanElement | undefined { + throw new UnsupportedOperationError( + 'additionalItems getter in Schema class is not not supported.', + ); + } + + set additionalItems(additionalItems: this | JSONReferenceElement | BooleanElement | undefined) { + throw new UnsupportedOperationError( + 'additionalItems setter in Schema class is not not supported.', + ); + } + + /** + * Validation keywords for objects + */ + + get patternProperties(): ObjectElement | undefined { + throw new UnsupportedOperationError( + 'patternProperties getter in Schema class is not not supported.', + ); + } + + set patternProperties(patternProperties: ObjectElement | undefined) { + throw new UnsupportedOperationError( + 'patternProperties setter in Schema class is not not supported.', + ); + } + + get dependencies(): ObjectElement | undefined { + throw new UnsupportedOperationError( + 'dependencies getter in Schema class is not not supported.', + ); + } + + set dependencies(dependencies: ObjectElement | undefined) { + throw new UnsupportedOperationError( + 'dependencies setter in Schema class is not not supported.', + ); + } + + /** + * Validation keywords for any instance type + */ + get anyOf(): ArrayElement | undefined { + throw new UnsupportedOperationError('anyOf getter in Schema class is not not supported.'); + } + + set anyOf(anyOf: ArrayElement | undefined) { + throw new UnsupportedOperationError('anyOf setter in Schema class is not not supported.'); + } + + get oneOf(): ArrayElement | undefined { + throw new UnsupportedOperationError('oneOf getter in Schema class is not not supported.'); + } + + set oneOf(oneOf: ArrayElement | undefined) { + throw new UnsupportedOperationError('oneOf setter in Schema class is not not supported.'); + } + + get not(): this | JSONReferenceElement | undefined { + throw new UnsupportedOperationError('not getter in Schema class is not not supported.'); + } + + set not(not: this | JSONReferenceElement | undefined) { + throw new UnsupportedOperationError('not setter in Schema class is not not supported.'); + } + + get definitions(): ObjectElement | undefined { + throw new UnsupportedOperationError('definitions getter in Schema class is not not supported.'); + } + + set definitions(definitions: ObjectElement | undefined) { + throw new UnsupportedOperationError('definitions setter in Schema class is not not supported.'); + } + + /** + * JSON Hyper-Schema + * + * URI: https://datatracker.ietf.org/doc/html/draft-wright-json-schema-hyperschema-00 + */ + + get base(): StringElement | undefined { + throw new UnsupportedOperationError('base getter in Schema class is not not supported.'); + } + + set base(base: StringElement | undefined) { + throw new UnsupportedOperationError('base setter in Schema class is not not supported.'); + } + + get links(): ArrayElement | undefined { + throw new UnsupportedOperationError('links getter in Schema class is not not supported.'); + } + + set links(links: ArrayElement | undefined) { + throw new UnsupportedOperationError('links setter in Schema class is not not supported.'); + } + + get media(): MediaElement | undefined { + throw new UnsupportedOperationError('media getter in Schema class is not not supported.'); + } + + set media(media: MediaElement | undefined) { + throw new UnsupportedOperationError('media setter in Schema class is not not supported.'); + } } +/* eslint-enable class-methods-use-this */ export default Schema; diff --git a/packages/apidom-ns-openapi-2/src/index.ts b/packages/apidom-ns-openapi-2/src/index.ts index 82205fbf63..99920678b6 100644 --- a/packages/apidom-ns-openapi-2/src/index.ts +++ b/packages/apidom-ns-openapi-2/src/index.ts @@ -31,6 +31,7 @@ export { isHeaderElement, isTagElement, isReferenceElement, + isSchemaElement, isXmlElement, isSecurityDefinitionsElement, isSecuritySchemeElement, @@ -53,6 +54,7 @@ export { HeaderElement, TagElement, ReferenceElement, + SchemaElement, XmlElement, SecurityDefinitionsElement, SecuritySchemeElement, diff --git a/packages/apidom-ns-openapi-2/src/namespace.ts b/packages/apidom-ns-openapi-2/src/namespace.ts index 9e27674cfb..6be304bafc 100644 --- a/packages/apidom-ns-openapi-2/src/namespace.ts +++ b/packages/apidom-ns-openapi-2/src/namespace.ts @@ -10,6 +10,7 @@ import ExampleElement from './elements/Example'; import HeadersElement from './elements/Headers'; import HeaderElement from './elements/Header'; import TagElement from './elements/Tag'; +import SchemaElement from './elements/Schema'; import XmlElement from './elements/Xml'; import ReferenceElement from './elements/Reference'; import SecurityDefinitionsElement from './elements/SecurityDefinitions'; @@ -32,6 +33,7 @@ const openApi2 = { base.register('header', HeaderElement); base.register('tag', TagElement); base.register('reference', ReferenceElement); + base.register('schema', SchemaElement); base.register('xml', XmlElement); base.register('securityDefinitions', SecurityDefinitionsElement); base.register('securityScheme', SecuritySchemeElement); diff --git a/packages/apidom-ns-openapi-2/src/predicates.ts b/packages/apidom-ns-openapi-2/src/predicates.ts index 8e39b600f8..c541178850 100644 --- a/packages/apidom-ns-openapi-2/src/predicates.ts +++ b/packages/apidom-ns-openapi-2/src/predicates.ts @@ -11,6 +11,7 @@ import HeadersElement from './elements/Headers'; import HeaderElement from './elements/Header'; import TagElement from './elements/Tag'; import ReferenceElement from './elements/Reference'; +import SchemaElement from './elements/Schema'; import XmlElement from './elements/Xml'; import SecurityDefinitionsElement from './elements/SecurityDefinitions'; import SecuritySchemeElement from './elements/SecurityScheme'; @@ -126,6 +127,16 @@ export const isReferenceElement = createPredicate( }, ); +export const isSchemaElement = createPredicate( + ({ hasBasicElementProps, isElementType, primitiveEq }) => { + return (element: unknown) => + element instanceof SchemaElement || + (hasBasicElementProps(element) && + isElementType('schema', element) && + primitiveEq('object', element)); + }, +); + export const isXmlElement = createPredicate( ({ hasBasicElementProps, isElementType, primitiveEq }) => { return (element: unknown) => diff --git a/packages/apidom-ns-openapi-2/src/refractor/registration.ts b/packages/apidom-ns-openapi-2/src/refractor/registration.ts index 4952752c0b..276bed55b1 100644 --- a/packages/apidom-ns-openapi-2/src/refractor/registration.ts +++ b/packages/apidom-ns-openapi-2/src/refractor/registration.ts @@ -9,6 +9,7 @@ import ExampleElement from '../elements/Example'; import HeaderElement from '../elements/Header'; import TagElement from '../elements/Tag'; import ReferenceElement from '../elements/Reference'; +import SchemaElement from '../elements/Schema'; import XmlElement from '../elements/Xml'; import SecurityDefinitionsElement from '../elements/SecurityDefinitions'; import SecuritySchemeElement from '../elements/SecurityScheme'; @@ -70,6 +71,7 @@ ReferenceElement.refract = createRefractor([ 'Reference', '$visitor', ]); +SchemaElement.refract = createRefractor(['visitors', 'document', 'objects', 'Schema', '$visitor']); XmlElement.refract = createRefractor(['visitors', 'document', 'objects', 'XML', '$visitor']); SecurityDefinitionsElement.refract = createRefractor([ 'visitors', @@ -106,6 +108,7 @@ export { HeaderElement, TagElement, ReferenceElement, + SchemaElement, XmlElement, SecurityDefinitionsElement, SecuritySchemeElement, diff --git a/packages/apidom-ns-openapi-2/src/refractor/specification.ts b/packages/apidom-ns-openapi-2/src/refractor/specification.ts index eb5e118881..611bd77cfa 100644 --- a/packages/apidom-ns-openapi-2/src/refractor/specification.ts +++ b/packages/apidom-ns-openapi-2/src/refractor/specification.ts @@ -15,6 +15,10 @@ import TagVisitor from './visitors/open-api-2/tag'; import ReferenceVisitor from './visitors/open-api-2/reference'; import Reference$RefVisitor from './visitors/open-api-2/reference/$RefVisitor'; import SchemaVisitor from './visitors/open-api-2/schema'; +import SchemaAllOfVisitor from './visitors/open-api-2/schema/AllOfVisitor'; +import SchemaItemsVisitor from './visitors/open-api-2/schema/ItemsVisitor'; +import SchemaPropertiesVisitor from './visitors/open-api-2/schema/PropertiesVisitor'; +import SchemaOrJSONReferenceVisitor from './visitors/open-api-2/schema/SchemaOrJSONReferenceVisitor'; import XmlVisitor from './visitors/open-api-2/xml'; import SecurityDefinitionsVisitor from './visitors/open-api-2/security-definitions'; import SecuritySchemeVisitor from './visitors/open-api-2/security-scheme'; @@ -178,8 +182,50 @@ const specification = { $ref: Reference$RefVisitor, }, }, + JSONReference: JSONSchemaDraft4Specification.visitors.document.objects.JSONReference, + JSONSchema: { + $ref: '#/visitors/document/objects/Schema', + }, Schema: { $visitor: SchemaVisitor, + fixedFields: { + // the following properties are taken directly from the JSON Schema definition and follow the same specifications + format: jsonSchemaFixedFields.format, + title: jsonSchemaFixedFields.title, + description: jsonSchemaFixedFields.description, + default: jsonSchemaFixedFields.default, + multipleOf: jsonSchemaFixedFields.multipleOf, + maximum: jsonSchemaFixedFields.maximum, + exclusiveMaximum: jsonSchemaFixedFields.exclusiveMaximum, + minimum: jsonSchemaFixedFields.minimum, + exclusiveMinimum: jsonSchemaFixedFields.exclusiveMinimum, + maxLength: jsonSchemaFixedFields.maxLength, + minLength: jsonSchemaFixedFields.minLength, + pattern: jsonSchemaFixedFields.pattern, + maxItems: jsonSchemaFixedFields.maxItems, + minItems: jsonSchemaFixedFields.minItems, + uniqueItems: jsonSchemaFixedFields.uniqueItems, + maxProperties: jsonSchemaFixedFields.maxProperties, + minProperties: jsonSchemaFixedFields.minProperties, + required: jsonSchemaFixedFields.required, + enum: jsonSchemaFixedFields.enum, + type: jsonSchemaFixedFields.type, + readOnly: jsonSchemaFixedFields.readOnly, + // the following properties are taken from the JSON Schema definition but their definitions were adjusted to the Swagger Specification + items: SchemaItemsVisitor, + allOf: SchemaAllOfVisitor, + properties: SchemaPropertiesVisitor, + additionalProperties: SchemaOrJSONReferenceVisitor, + // OpenAPI vocabulary + discriminator: FallbackVisitor, + xml: { + $ref: '#/visitors/document/objects/XML', + }, + externalDocs: { + $ref: '#/visitors/document/objects/ExternalDocumentation', + }, + example: FallbackVisitor, + }, }, XML: { $visitor: XmlVisitor, diff --git a/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/AllOfVisitor.ts b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/AllOfVisitor.ts new file mode 100644 index 0000000000..218adb511e --- /dev/null +++ b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/AllOfVisitor.ts @@ -0,0 +1,29 @@ +import stampit from 'stampit'; +import { ArrayElement } from '@swagger-api/apidom-core'; +import { + specificationObj as JSONSchemaDraft4Specification, + isJSONReferenceElement, + JSONReferenceElement, +} from '@swagger-api/apidom-ns-json-schema-draft-4'; + +const { allOf: JSONSchemaAllOfVisitor } = + JSONSchemaDraft4Specification.visitors.document.objects.JSONSchema.fixedFields; + +const AllOfVisitor = stampit(JSONSchemaAllOfVisitor, { + methods: { + ArrayElement(arrayElement: ArrayElement) { + // @ts-ignore + const result = JSONSchemaAllOfVisitor.compose.methods.ArrayElement.call(this, arrayElement); + + this.element + .filter(isJSONReferenceElement) + .forEach((referenceElement: JSONReferenceElement) => { + referenceElement.setMetaProperty('referenced-element', 'schema'); + }); + + return result; + }, + }, +}); + +export default AllOfVisitor; diff --git a/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/ItemsVisitor.ts b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/ItemsVisitor.ts new file mode 100644 index 0000000000..b6e126b329 --- /dev/null +++ b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/ItemsVisitor.ts @@ -0,0 +1,39 @@ +import stampit from 'stampit'; +import { ArrayElement, ObjectElement } from '@swagger-api/apidom-core'; +import { + specificationObj as JSONSchemaDraft4Specification, + JSONReferenceElement, + isJSONReferenceElement, +} from '@swagger-api/apidom-ns-json-schema-draft-4'; + +const { items: JSONSchemaItemsVisitor } = + JSONSchemaDraft4Specification.visitors.document.objects.JSONSchema.fixedFields; + +const ItemsVisitor = stampit(JSONSchemaItemsVisitor, { + methods: { + ObjectElement(objectElement: ObjectElement) { + // @ts-ignore + const result = JSONSchemaItemsVisitor.compose.methods.ObjectElement.call(this, objectElement); + + if (isJSONReferenceElement(this.element)) { + this.element.setMetaProperty('referenced-element', 'schema'); + } + + return result; + }, + ArrayElement(arrayElement: ArrayElement) { + // @ts-ignore + const result = JSONSchemaItemsVisitor.compose.methods.ArrayElement.call(this, arrayElement); + + this.element + .filter(isJSONReferenceElement) + .forEach((referenceElement: JSONReferenceElement) => { + referenceElement.setMetaProperty('referenced-element', 'schema'); + }); + + return result; + }, + }, +}); + +export default ItemsVisitor; diff --git a/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/PropertiesVisitor.ts b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/PropertiesVisitor.ts new file mode 100644 index 0000000000..0326204103 --- /dev/null +++ b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/PropertiesVisitor.ts @@ -0,0 +1,32 @@ +import stampit from 'stampit'; +import { ObjectElement } from '@swagger-api/apidom-core'; +import { + specificationObj as JSONSchemaDraft4Specification, + JSONReferenceElement, + isJSONReferenceElement, +} from '@swagger-api/apidom-ns-json-schema-draft-4'; + +const { properties: JSONSchemaPropertiesVisitor } = + JSONSchemaDraft4Specification.visitors.document.objects.JSONSchema.fixedFields; + +const PropertiesVisitor = stampit(JSONSchemaPropertiesVisitor, { + methods: { + ObjectElement(objectElement: ObjectElement) { + // @ts-ignore + const result = JSONSchemaPropertiesVisitor.compose.methods.ObjectElement.call( + this, + objectElement, + ); + + this.element + .filter(isJSONReferenceElement) + .forEach((referenceElement: JSONReferenceElement) => { + referenceElement.setMetaProperty('referenced-element', 'schema'); + }); + + return result; + }, + }, +}); + +export default PropertiesVisitor; diff --git a/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/SchemaOrJSONReferenceVisitor.ts b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/SchemaOrJSONReferenceVisitor.ts new file mode 100644 index 0000000000..6af2ae57e4 --- /dev/null +++ b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/SchemaOrJSONReferenceVisitor.ts @@ -0,0 +1,28 @@ +import stampit from 'stampit'; +import { ObjectElement } from '@swagger-api/apidom-core'; +import { + specificationObj as JSONSchemaDraft4Specification, + isJSONReferenceElement, +} from '@swagger-api/apidom-ns-json-schema-draft-4'; + +const { JSONSchemaOrJSONReferenceVisitor } = JSONSchemaDraft4Specification.visitors; + +const SchemaOrJSONReferenceVisitor = stampit(JSONSchemaOrJSONReferenceVisitor, { + methods: { + ObjectElement(objectElement: ObjectElement) { + // @ts-ignore + const result = JSONSchemaOrJSONReferenceVisitor.compose.methods.enter.call( + this, + objectElement, + ); + + if (isJSONReferenceElement(this.element)) { + this.element.setMetaProperty('referenced-element', 'schema'); + } + + return result; + }, + }, +}); + +export default SchemaOrJSONReferenceVisitor; diff --git a/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/index.ts b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/index.ts index 4f3e37439a..22432d4ea0 100644 --- a/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/index.ts +++ b/packages/apidom-ns-openapi-2/src/refractor/visitors/open-api-2/schema/index.ts @@ -5,7 +5,7 @@ import SchemaElement from '../../../../elements/Schema'; import FallbackVisitor from '../../FallbackVisitor'; import FixedFieldsVisitor from '../../generics/FixedFieldsVisitor'; -const ParameterVisitor = stampit(FixedFieldsVisitor, FallbackVisitor, { +const SchemaVisitor = stampit(FixedFieldsVisitor, FallbackVisitor, { props: { specPath: always(['document', 'objects', 'Schema']), canSupportSpecificationExtensions: true, @@ -15,4 +15,4 @@ const ParameterVisitor = stampit(FixedFieldsVisitor, FallbackVisitor, { }, }); -export default ParameterVisitor; +export default SchemaVisitor; diff --git a/packages/apidom-ns-openapi-2/src/traversal/visitor.ts b/packages/apidom-ns-openapi-2/src/traversal/visitor.ts index 75fd170945..9ac0308b4f 100644 --- a/packages/apidom-ns-openapi-2/src/traversal/visitor.ts +++ b/packages/apidom-ns-openapi-2/src/traversal/visitor.ts @@ -30,6 +30,7 @@ export const keyMap = { HeaderElement: ['content'], TagElement: ['content'], ReferenceElement: ['content'], + SchemaElement: ['content'], XmlElement: ['content'], SecurityDefinitionsElement: ['content'], SecuritySchemeElement: ['content'], diff --git a/packages/apidom-ns-openapi-2/test/predicates.ts b/packages/apidom-ns-openapi-2/test/predicates.ts index 62eef951c7..97e0af75d2 100644 --- a/packages/apidom-ns-openapi-2/test/predicates.ts +++ b/packages/apidom-ns-openapi-2/test/predicates.ts @@ -12,6 +12,7 @@ import { HeaderElement, TagElement, ReferenceElement, + SchemaElement, XmlElement, SecurityDefinitionsElement, SecuritySchemeElement, @@ -28,6 +29,7 @@ import { isHeaderElement, isTagElement, isReferenceElement, + isSchemaElement, isXmlElement, isSecurityDefinitionsElement, isSecuritySchemeElement, @@ -652,6 +654,62 @@ describe('predicates', function () { }); }); + context('isSchemaElement', function () { + context('given SchemaElement instance value', function () { + specify('should return true', function () { + const element = new SchemaElement(); + + assert.isTrue(isSchemaElement(element)); + }); + }); + + context('given subtype instance value', function () { + specify('should return true', function () { + class SchemaSubElement extends SchemaElement {} + + assert.isTrue(isSchemaElement(new SchemaSubElement())); + }); + }); + + context('given non SchemaSubElement instance value', function () { + specify('should return false', function () { + assert.isFalse(isSchemaElement(1)); + assert.isFalse(isSchemaElement(null)); + assert.isFalse(isSchemaElement(undefined)); + assert.isFalse(isSchemaElement({})); + assert.isFalse(isSchemaElement([])); + assert.isFalse(isSchemaElement('string')); + }); + }); + + specify('should support duck-typing', function () { + const schemaElementDuck = { + _storedElement: 'schema', + _content: [], + primitive() { + return 'object'; + }, + get element() { + return this._storedElement; + }, + }; + + const schemaElementSwan = { + _storedElement: undefined, + _content: undefined, + primitive() { + return 'swan'; + }, + get length() { + return 0; + }, + }; + + assert.isTrue(isSchemaElement(schemaElementDuck)); + assert.isFalse(isSchemaElement(schemaElementSwan)); + }); + }); + context('isXmlElement', function () { context('given XmlElement instance value', function () { specify('should return true', function () { diff --git a/packages/apidom-ns-openapi-2/test/refractor/elements/Schema/__snapshots__/index.ts.snap b/packages/apidom-ns-openapi-2/test/refractor/elements/Schema/__snapshots__/index.ts.snap new file mode 100644 index 0000000000..9070cf498f --- /dev/null +++ b/packages/apidom-ns-openapi-2/test/refractor/elements/Schema/__snapshots__/index.ts.snap @@ -0,0 +1,148 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`refractor elements SchemaElement given allOf keyword with reference should refract to semantic ApiDOM tree 1`] = ` +(SchemaElement + (MemberElement + (StringElement) + (ArrayElement + (JSONReferenceElement + (MemberElement + (StringElement) + (StringElement)))))) +`; + +exports[`refractor elements SchemaElement given embedded SchemaElements should refract to semantic ApiDOM tree 1`] = ` +(SchemaElement + (MemberElement + (StringElement) + (ArrayElement + (SchemaElement + (MemberElement + (StringElement) + (ArrayElement + (SchemaElement))))))) +`; + +exports[`refractor elements SchemaElement given items keyword in form of object should refract to semantic ApiDOM tree 1`] = ` +(SchemaElement + (MemberElement + (StringElement) + (SchemaElement))) +`; + +exports[`refractor elements SchemaElement given properties keyword with reference should refract to semantic ApiDOM tree 1`] = ` +(SchemaElement + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (JSONReferenceElement + (MemberElement + (StringElement) + (StringElement))))))) +`; + +exports[`refractor elements SchemaElement should refract to semantic ApiDOM tree 1`] = ` +(SchemaElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (BooleanElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (BooleanElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (BooleanElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (NumberElement)) + (MemberElement + (StringElement) + (ArrayElement + (StringElement) + (StringElement))) + (MemberElement + (StringElement) + (ArrayElement + (NumberElement) + (StringElement) + (NullElement))) + (MemberElement + (StringElement) + (ArrayElement + (StringElement) + (StringElement))) + (MemberElement + (StringElement) + (BooleanElement)) + (MemberElement + (StringElement) + (ArrayElement + (SchemaElement) + (SchemaElement))) + (MemberElement + (StringElement) + (ArrayElement + (SchemaElement))) + (MemberElement + (StringElement) + (ObjectElement + (MemberElement + (StringElement) + (SchemaElement)))) + (MemberElement + (StringElement) + (SchemaElement)) + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (XmlElement)) + (MemberElement + (StringElement) + (ExternalDocumentationElement)) + (MemberElement + (StringElement) + (NumberElement))) +`; diff --git a/packages/apidom-ns-openapi-2/test/refractor/elements/Schema/index.ts b/packages/apidom-ns-openapi-2/test/refractor/elements/Schema/index.ts new file mode 100644 index 0000000000..4d90dd19e7 --- /dev/null +++ b/packages/apidom-ns-openapi-2/test/refractor/elements/Schema/index.ts @@ -0,0 +1,103 @@ +import { expect, assert } from 'chai'; +import { sexprs, toValue } from '@swagger-api/apidom-core'; + +import { SchemaElement } from '../../../../src'; + +describe('refractor', function () { + context('elements', function () { + context('SchemaElement', function () { + specify('should refract to semantic ApiDOM tree', function () { + const schemaElement = SchemaElement.refract({ + // the following properties are taken directly from the JSON Schema definition and follow the same specifications + format: 'url', + title: 'title', + description: 'description', + default: 3, + multipleOf: 1, + maximum: 2, + exclusiveMaximum: true, + minimum: 4, + exclusiveMinimum: false, + maxLength: 6, + minLength: 7, + pattern: '[a-z]+', + maxItems: 8, + minItems: 9, + uniqueItems: true, + maxProperties: 10, + minProperties: 11, + required: ['prop1', 'prop2'], + enum: [1, '2', null], + type: ['string', 'number'], + readOnly: false, + // the following properties are taken from the JSON Schema definition but their definitions were adjusted to the Swagger Specification + items: [{}, {}], + allOf: [{}], + properties: { prop1: {} }, + additionalProperties: {}, + // OpenAPI vocabulary + discriminator: 'discriminator', + xml: {}, + externalDocs: {}, + example: 1, + }); + + expect(sexprs(schemaElement)).toMatchSnapshot(); + }); + + context('given items keyword in form of object', function () { + specify('should refract to semantic ApiDOM tree', function () { + const schemaElement = SchemaElement.refract({ + items: {}, + }); + + expect(sexprs(schemaElement)).toMatchSnapshot(); + }); + }); + + context('given embedded SchemaElements', function () { + specify('should refract to semantic ApiDOM tree', function () { + const schemaElement = SchemaElement.refract({ + allOf: [{ allOf: [{}] }], + }); + + expect(sexprs(schemaElement)).toMatchSnapshot(); + }); + }); + + context('given allOf keyword with reference', function () { + const schemaElement = SchemaElement.refract({ + allOf: [{ $ref: '#/path/to/schema' }], + }) as SchemaElement; + + specify('should refract to semantic ApiDOM tree', function () { + expect(sexprs(schemaElement)).toMatchSnapshot(); + }); + + specify('should contain referenced-element meta', function () { + const referenceElement = schemaElement.allOf?.get(0); + const referencedElementMeta = referenceElement?.getMetaProperty('referenced-element'); + + assert.strictEqual(toValue(referencedElementMeta), 'schema'); + }); + }); + + context('given properties keyword with reference', function () { + const schemaElement = SchemaElement.refract({ + properties: { prop1: { $ref: '#/path/to/schema' } }, + }) as SchemaElement; + + specify('should refract to semantic ApiDOM tree', function () { + expect(sexprs(schemaElement)).toMatchSnapshot(); + }); + + specify('should contain referenced-element meta', function () { + const referenceElement = schemaElement.properties?.get('prop1'); + const referencedElementMeta = referenceElement?.getMetaProperty('referenced-element'); + + assert.strictEqual(toValue(referencedElementMeta), 'schema'); + }); + }); + }); + }); +});