import { TreeListParentNode, TreeState } from '@stoplight/tree-list'; import { Popover } from '@stoplight/ui-kit'; import { shallow } from 'enzyme'; import 'jest-enzyme'; import { JSONSchema4 } from 'json-schema'; import * as React from 'react'; import { SchemaTree } from '../../tree'; import { metadataStore } from '../../tree/metadata'; import { SchemaKind, SchemaTreeListNode } from '../../types'; import { SchemaErrorRow, SchemaPropertyRow, SchemaRow } from '../SchemaRow'; import { Caret } from '../shared'; import { Validations } from '../shared/Validations'; describe('SchemaRow component', () => { test('should render falsy validations', () => { const node: SchemaTreeListNode = { id: '0.n1f7tvhzoj', name: '', parent: null, }; metadataStore.set(node, { schemaNode: { name: '', id: '232', type: SchemaKind.Object, validations: { enum: [null, 0, false], }, annotations: {}, enum: [null, 0, false], } as any, schema: {} as any, path: [], }); const rowOptions = { isEdited: false, isExpanded: true, }; const wrapper = shallow( shallow() .find(SchemaPropertyRow) .shallow() .find(Validations) .shallow() .find(Popover) .prop('content') as React.ReactElement, ); expect(wrapper).toHaveText('enum:null,0,false'); }); test('should render caret for top-level $ref', () => { const schema: JSONSchema4 = { $ref: '#/definitions/foo', definitions: { foo: { type: 'string', }, }, }; const tree = new SchemaTree(schema, new TreeState(), { expandedDepth: Infinity, mergeAllOf: false, resolveRef: void 0, shouldResolveEagerly: false, onPopulate: void 0, }); tree.populate(); const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Caret)).toExist(); expect(wrapper.find(Caret)).toHaveProp('style', { height: 20, position: 'relative', width: 20, }); }); test('should render caret for top-level array with $ref items', () => { const schema: JSONSchema4 = { type: 'array', items: { $ref: '#/foo', }, }; const tree = new SchemaTree(schema, new TreeState(), { expandedDepth: Infinity, mergeAllOf: false, resolveRef: void 0, shouldResolveEagerly: false, onPopulate: void 0, }); tree.populate(); const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Caret)).toExist(); expect(wrapper.find(Caret)).toHaveProp('style', { height: 20, position: 'relative', width: 20, }); }); describe('expanding errors', () => { describe('$refs', () => { let tree: SchemaTree; beforeEach(() => { const schema: JSONSchema4 = { type: 'object', properties: { user: { $ref: '#/properties/foo', }, }, }; tree = new SchemaTree(schema, new TreeState(), { expandedDepth: Infinity, mergeAllOf: false, resolveRef: void 0, shouldResolveEagerly: false, onPopulate: void 0, }); tree.populate(); }); test('given no custom resolver, should render a generic error message', () => { tree.unwrap(tree.itemAt(1) as TreeListParentNode); const wrapper = shallow() .find(SchemaErrorRow) .shallow(); expect(wrapper).toHaveText(`Could not dereference "#/properties/foo"`); }); test('given a custom resolver, should render a message thrown by it', () => { const message = "I don't know how to resolve it. Sorry"; tree.treeOptions.resolveRef = () => { throw new Error(message); }; tree.unwrap(tree.itemAt(1) as TreeListParentNode); const wrapper = shallow() .find(SchemaErrorRow) .shallow(); expect(wrapper).toHaveText(message); }); }); }); describe('required property', () => { let tree: SchemaTree; beforeEach(() => { const schema: JSONSchema4 = { type: 'object', properties: { user: { $ref: '#/properties/id', }, id: { type: 'object', required: ['foo'], properties: { foo: { type: 'string', }, bar: { type: 'number', }, }, }, }, }; tree = new SchemaTree(schema, new TreeState(), { expandedDepth: Infinity, mergeAllOf: false, resolveRef: void 0, shouldResolveEagerly: false, onPopulate: void 0, }); tree.populate(); tree.unwrap(tree.itemAt(1) as TreeListParentNode); }); test('should preserve the required validation', () => { const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Validations)).toHaveProp('required', true); }); test('should preserve the optional validation', () => { const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Validations)).toHaveProp('required', false); }); describe('given a referenced object', () => { test('should preserve the required validation', () => { const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Validations)).toHaveProp('required', true); }); test('should preserve the optional validation', () => { const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Validations)).toHaveProp('required', false); }); }); describe('given array with items', () => { beforeEach(() => { const schema: JSONSchema4 = { title: 'test', type: 'array', items: { type: 'object', properties: { code: { type: 'number', }, msg: { type: 'string', }, ref: { type: 'string', }, }, required: ['code', 'msg'], }, }; tree = new SchemaTree(schema, new TreeState(), { expandedDepth: Infinity, mergeAllOf: false, resolveRef: void 0, shouldResolveEagerly: false, onPopulate: void 0, }); tree.populate(); }); test.each([1, 2])('should preserve the required validation for %i item', pos => { const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Validations)).toHaveProp('required', true); }); test('should preserve the optional validation', () => { const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Validations)).toHaveProp('required', false); }); }); describe('given array with arrayish items', () => { beforeEach(() => { const schema: JSONSchema4 = { title: 'test', type: 'array', items: [ { type: 'object', properties: { code: { type: 'number', }, msg: { type: 'string', }, ref: { type: 'string', }, }, required: ['code', 'msg'], }, ], }; tree = new SchemaTree(schema, new TreeState(), { expandedDepth: Infinity, mergeAllOf: false, resolveRef: void 0, shouldResolveEagerly: false, onPopulate: void 0, }); tree.populate(); }); test.each([2, 3])('should preserve the required validation for %i item', pos => { const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Validations)).toHaveProp('required', true); }); test('should preserve the optional validation', () => { const wrapper = shallow() .find(SchemaPropertyRow) .shallow(); expect(wrapper.find(Validations)).toHaveProp('required', false); }); }); }); });