-
Notifications
You must be signed in to change notification settings - Fork 1.1k
chore(repository-json-schema): add JSON schema type tests #1323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ import { | |
| } from '../..'; | ||
| import {expect} from '@loopback/testlab'; | ||
| import {MetadataInspector} from '@loopback/context'; | ||
| import * as Ajv from 'ajv'; | ||
|
|
||
| describe('build-schema', () => { | ||
| describe('modelToJsonSchema', () => { | ||
|
|
@@ -25,6 +26,7 @@ describe('build-schema', () => { | |
|
|
||
| const jsonSchema = modelToJsonSchema(TestModel); | ||
| expect(jsonSchema.properties).to.not.have.keys(['nul', 'undef']); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('does not convert properties that have not been decorated', () => { | ||
|
|
@@ -42,11 +44,13 @@ describe('build-schema', () => { | |
| const noPropJson = modelToJsonSchema(NoPropertyMeta); | ||
| const onePropJson = modelToJsonSchema(OnePropertyDecorated); | ||
| expect(noPropJson).to.not.have.key('properties'); | ||
| expectValidJsonSchema(noPropJson); | ||
| expect(onePropJson.properties).to.deepEqual({ | ||
| foo: { | ||
| type: 'string', | ||
| }, | ||
| }); | ||
| expectValidJsonSchema(onePropJson); | ||
| }); | ||
|
|
||
| it('does not convert models that have not been decorated with @model()', () => { | ||
|
|
@@ -56,8 +60,12 @@ describe('build-schema', () => { | |
| bar: number; | ||
| } | ||
|
|
||
| expect(modelToJsonSchema(Empty)).to.eql({}); | ||
| expect(modelToJsonSchema(NoModelMeta)).to.eql({}); | ||
| const emptyJson = modelToJsonSchema(Empty); | ||
| const noModelMetaJson = modelToJsonSchema(NoModelMeta); | ||
| expect(emptyJson).to.eql({}); | ||
| expectValidJsonSchema(emptyJson); | ||
| expect(noModelMetaJson).to.eql({}); | ||
| expectValidJsonSchema(noModelMetaJson); | ||
| }); | ||
|
|
||
| it('infers "title" property from constructor name', () => { | ||
|
|
@@ -68,6 +76,7 @@ describe('build-schema', () => { | |
|
|
||
| const jsonSchema = modelToJsonSchema(TestModel); | ||
| expect(jsonSchema.title).to.eql('TestModel'); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('overrides "title" property if explicitly given', () => { | ||
|
|
@@ -78,6 +87,7 @@ describe('build-schema', () => { | |
|
|
||
| const jsonSchema = modelToJsonSchema(TestModel); | ||
| expect(jsonSchema.title).to.eql('NewName'); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('retains "description" properties from top-level metadata', () => { | ||
|
|
@@ -91,6 +101,7 @@ describe('build-schema', () => { | |
|
|
||
| const jsonSchema = modelToJsonSchema(TestModel); | ||
| expect(jsonSchema.description).to.eql(topMeta.description); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('properly converts string, number, and boolean properties', () => { | ||
|
|
@@ -113,6 +124,7 @@ describe('build-schema', () => { | |
| type: 'boolean', | ||
| }, | ||
| }); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('properly converts object properties', () => { | ||
|
|
@@ -127,6 +139,7 @@ describe('build-schema', () => { | |
| type: 'object', | ||
| }, | ||
| }); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| context('with custom type properties', () => { | ||
|
|
@@ -147,6 +160,7 @@ describe('build-schema', () => { | |
| }, | ||
| }); | ||
| expect(jsonSchema).to.not.have.key('definitions'); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('properly converts decorated custom type properties', () => { | ||
|
|
@@ -176,6 +190,7 @@ describe('build-schema', () => { | |
| }, | ||
| }, | ||
| }); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('creates definitions only at the root level of the schema', () => { | ||
|
|
@@ -223,6 +238,7 @@ describe('build-schema', () => { | |
| }, | ||
| }, | ||
| }); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
| }); | ||
|
|
||
|
|
@@ -241,6 +257,7 @@ describe('build-schema', () => { | |
| }, | ||
| }, | ||
| }); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('properly converts custom type arrays properties', () => { | ||
|
|
@@ -262,6 +279,7 @@ describe('build-schema', () => { | |
| }, | ||
| }, | ||
| }); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('supports explicit primitive type decoration via strings', () => { | ||
|
|
@@ -287,6 +305,7 @@ describe('build-schema', () => { | |
| type: 'number', | ||
| }, | ||
| }); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('maps "required" keyword to the schema appropriately', () => { | ||
|
|
@@ -301,6 +320,7 @@ describe('build-schema', () => { | |
|
|
||
| const jsonSchema = modelToJsonSchema(TestModel); | ||
| expect(jsonSchema.required).to.deepEqual(['propTwo']); | ||
| expectValidJsonSchema(jsonSchema); | ||
| }); | ||
|
|
||
| it('errors out when explicit type decoration is not primitive', () => { | ||
|
|
@@ -335,6 +355,18 @@ describe('build-schema', () => { | |
| }).to.throw(/type is defined as an array/); | ||
| }); | ||
| }); | ||
|
|
||
| function expectValidJsonSchema(schema: JsonSchema) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we consider exporting this as a util function from this package?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤔 This means that we'd have to have
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not that big imo but I'm ok not exporting this as a utility function.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @shimks I think @virkt25 was suggesting to export At one hand, a readily-available helper for verifying JSON Schema may be helpful outside of this module tests too. On the other hand, exporting a test helper from a non-test-helper module is tricky as we may need to move dev-dependencies to regular dependencies. As for In the light of what I wrote above, I think we should not be exporting this utility function. |
||
| const ajv = new Ajv(); | ||
| const validate = ajv.compile( | ||
| require('ajv/lib/refs/json-schema-draft-06.json'), | ||
| ); | ||
| const isValid = validate(schema); | ||
| const result = isValid | ||
| ? 'JSON Schema is valid' | ||
| : ajv.errorsText(validate.errors!); | ||
| expect(result).to.equal('JSON Schema is valid'); | ||
| } | ||
| }); | ||
|
|
||
| describe('getjsonSchema', () => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| // Copyright IBM Corp. 2018. All Rights Reserved. | ||
| // Node module: @loopback/repository-json-schema | ||
| // This file is licensed under the MIT License. | ||
| // License text available at https://opensource.org/licenses/MIT | ||
|
|
||
| import {JsonSchema} from '../../src'; | ||
|
|
||
| describe('JSON Schema type', () => { | ||
| describe('JsonSchema interface', () => { | ||
| /** | ||
| * The classes below are declared as tests for the Interfaces. | ||
| * The TS Compiler will complain if an interface changes in a way | ||
| * inconsistent with the JSON Schema definition. | ||
| * | ||
| * Inspired by https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/json-schema/json-schema-tests.ts | ||
| */ | ||
|
|
||
| // tslint:disable-next-line:no-unused-variable | ||
| const testSchema: JsonSchema = { | ||
| $id: 'test', | ||
| $ref: 'test/sub', | ||
| $schema: 'http://json-schema.org/schema#', | ||
| title: 'test', | ||
| description: 'test description', | ||
| default: 10, | ||
| multipleOf: 5, | ||
| maximum: 4, | ||
| exclusiveMaximum: 20, | ||
| minimum: 5, | ||
| exclusiveMinimum: 5, | ||
| maxLength: 7, | ||
| minLength: 2, | ||
| pattern: 'test pattern', | ||
| additionalItems: true, | ||
| items: [ | ||
| { | ||
| type: 'string', | ||
| }, | ||
| ], | ||
| maxItems: 5, | ||
| minItems: 4, | ||
| uniqueItems: true, | ||
| maxProperties: 5, | ||
| minProperties: 12, | ||
| required: ['foo', 'bar'], | ||
| additionalProperties: true, | ||
| definitions: {foo: {type: 'number'}}, | ||
| properties: {bar: {type: 'string'}}, | ||
| dependencies: {baz: {type: 'boolean'}}, | ||
| enum: ['foo', 23], | ||
| type: 'string', | ||
| allOf: [{type: 'string'}], | ||
| anyOf: [{type: 'number'}], | ||
| oneOf: [{type: 'boolean'}], | ||
| not: {type: 'array'}, | ||
| const: 'test', | ||
| contains: {type: 'string'}, | ||
| examples: [4], | ||
| propertyNames: {enum: ['foo', 'bar']}, | ||
| format: 'email', | ||
| }; | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems redundant. Won't
expectValidJsonSchemacheck if it's{}or not?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it is redundant. On the other hand though, what if someday they decide
{}is not a valid JSON Schema? In that case, we'd want this to test to fail while still maintaining thatemptyJsonis an empty object and that{}is not a valid JSON SchemaThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unlikely, but I'm ok with the redundancy.