diff --git a/src/components/__tests__/SchemaRow.spec.tsx b/src/components/__tests__/SchemaRow.spec.tsx index cf42f3de..e2aa289c 100644 --- a/src/components/__tests__/SchemaRow.spec.tsx +++ b/src/components/__tests__/SchemaRow.spec.tsx @@ -1,3 +1,4 @@ +import { Popover } from '@stoplight/ui-kit'; import { shallow } from 'enzyme'; import 'jest-enzyme'; import * as React from 'react'; @@ -30,6 +31,7 @@ describe('SchemaRow component', () => { const wrapper = shallow(shallow() .find(Validations) .shallow() + .find(Popover) .prop('content') as React.ReactElement); expect(wrapper).toHaveText('enum:null,0,false'); diff --git a/src/components/__tests__/Validations.spec.tsx b/src/components/__tests__/Validations.spec.tsx new file mode 100644 index 00000000..ceda5add --- /dev/null +++ b/src/components/__tests__/Validations.spec.tsx @@ -0,0 +1,31 @@ +import { Dictionary } from '@stoplight/types'; +import { Popover } from '@stoplight/ui-kit'; +import { shallow } from 'enzyme'; +import 'jest-enzyme'; +import * as React from 'react'; + +import { getValidations } from '../../utils/getValidations'; +import { Validations } from '../shared/Validations'; + +describe('Validations component', () => { + describe('when property is deprecated', () => { + let validations: Dictionary; + + beforeEach(() => { + validations = getValidations({ 'x-deprecated': true, type: 'string', format: 'email', minLength: 2 }); + }); + + test('should exclude deprecated from general validations', () => { + const wrapper = shallow().find(Popover); + + expect(shallow(wrapper.prop('target') as React.ReactElement)).toHaveText('optional+2'); + expect(shallow(wrapper.prop('content') as React.ReactElement)).toHaveText('format:"email"minLength:2'); + }); + + test('should render deprecated box next to popover', () => { + const wrapper = shallow().childAt(0); + + expect(wrapper).toHaveText('deprecated'); + }); + }); +}); diff --git a/src/components/shared/Validations.tsx b/src/components/shared/Validations.tsx index cd59ffdc..cd940109 100644 --- a/src/components/shared/Validations.tsx +++ b/src/components/shared/Validations.tsx @@ -5,10 +5,13 @@ import * as React from 'react'; export interface IValidations { required: boolean; - validations: Dictionary | {}; + validations: (Dictionary | {}) & { deprecated?: boolean }; } -export const Validations: React.FunctionComponent = ({ required, validations }) => { +export const Validations: React.FunctionComponent = ({ + required, + validations: { deprecated, ...validations }, +}) => { const validationCount = Object.keys(validations).length; const requiredElem = ( @@ -18,49 +21,54 @@ export const Validations: React.FunctionComponent = ({ required, v ); - return validationCount ? ( - - {Object.keys(validations).map((key, index) => { - const validation = validations[key]; + return ( + <> + {deprecated ? deprecated : null} + {validationCount ? ( + + {Object.keys(validations).map((key, index) => { + const validation = validations[key]; - let elem = null; - if (Array.isArray(validation)) { - elem = validation.map((v, i) => ( -
-
{String(v)}
- {i < validation.length - 1 ?
,
: null} -
- )); - } else if (typeof validation === 'object') { - elem = ( -
- {'{...}'} -
- ); - } else { - elem = ( -
- {JSON.stringify(validation)} -
- ); - } + let elem = null; + if (Array.isArray(validation)) { + elem = validation.map((v, i) => ( +
+
{String(v)}
+ {i < validation.length - 1 ?
,
: null} +
+ )); + } else if (typeof validation === 'object') { + elem = ( +
+ {'{...}'} +
+ ); + } else { + elem = ( +
+ {JSON.stringify(validation)} +
+ ); + } - return ( -
-
{key}:
-
{elem}
-
- ); - })} - - } - target={requiredElem} - /> - ) : ( - requiredElem + return ( +
+
{key}:
+
{elem}
+
+ ); + })} + + } + target={requiredElem} + /> + ) : ( + requiredElem + )} + ); }; diff --git a/src/utils/__tests__/getValidations.spec.ts b/src/utils/__tests__/getValidations.spec.ts new file mode 100644 index 00000000..bc357745 --- /dev/null +++ b/src/utils/__tests__/getValidations.spec.ts @@ -0,0 +1,20 @@ +import { getValidations } from '../getValidations'; + +describe('getValidations util', () => { + describe('deprecated property', () => { + test('given present x-deprecated, should include its value', () => { + expect(getValidations({ 'x-deprecated': false })).toStrictEqual({ deprecated: false }); + expect(getValidations({ 'x-deprecated': false, deprecated: true })).toStrictEqual({ deprecated: false }); + expect(getValidations({ 'x-deprecated': true })).toStrictEqual({ deprecated: true }); + }); + + test('given present deprecated, should include its value', () => { + expect(getValidations({ deprecated: false })).toStrictEqual({ deprecated: false }); + expect(getValidations({ deprecated: true })).toStrictEqual({ deprecated: true }); + }); + + test('given missing deprecated, should not include anything', () => { + expect(getValidations({})).toStrictEqual({}); + }); + }); +}); diff --git a/src/utils/getValidations.ts b/src/utils/getValidations.ts index ff82b370..9189c75c 100644 --- a/src/utils/getValidations.ts +++ b/src/utils/getValidations.ts @@ -1,4 +1,4 @@ -import { Dictionary } from '@stoplight/types'; +import { Dictionary, Optional } from '@stoplight/types'; import { JSONSchema4, JSONSchema4TypeName } from 'json-schema'; import { flatMap as _flatMap, pick as _pick } from 'lodash-es'; @@ -7,7 +7,6 @@ export const COMMON_VALIDATION_TYPES = [ 'format', // https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-7 'default', 'example', - 'deprecated', 'nullable', 'discriminator', 'readOnly', @@ -23,6 +22,18 @@ const VALIDATION_TYPES = { array: ['additionalItems', 'minItems', 'maxItems', 'uniqueItems'], }; +function getDeprecatedValue(node: JSONSchema4): Optional { + if ('x-deprecated' in node) { + return !!node['x-deprecated']; + } + + if ('deprecated' in node) { + return !!node.deprecated; + } + + return; +} + function getTypeValidations(type: JSONSchema4TypeName | JSONSchema4TypeName[]): string[] { if (Array.isArray(type)) { return _flatMap(type, getTypeValidations); @@ -33,8 +44,10 @@ function getTypeValidations(type: JSONSchema4TypeName | JSONSchema4TypeName[]): export const getValidations = (node: JSONSchema4): Dictionary => { const extraValidations = node.type && getTypeValidations(node.type); + const deprecated = getDeprecatedValue(node); return { ..._pick(node, COMMON_VALIDATION_TYPES), ...(extraValidations && _pick(node, extraValidations)), + ...(deprecated !== void 0 && { deprecated }), }; };