UNPKG

lucid-ui

Version:

A UI component library from AppNexus.

340 lines (336 loc) 15.1 kB
import _isNull from "lodash/isNull"; import _forEach from "lodash/forEach"; import _isEqual from "lodash/isEqual"; import _get from "lodash/get"; import _has from "lodash/has"; import _isFunction from "lodash/isFunction"; import assert from 'assert'; import React from 'react'; import PropTypes from 'prop-types'; import { shallow } from 'enzyme'; import { createClass, filterTypes, rejectTypes, createElements, findTypes, omitProps } from './component-types'; function isReactComponentClass(componentClass) { return _isFunction(componentClass) && _has(componentClass, 'prototype') && !!componentClass.prototype.isReactComponent; } describe('component-types', function () { describe('createClass', function () { it('should return a React component type.', function () { assert(isReactComponentClass(createClass({})), 'must be a React component'); }); it('should make child `components` static properties.', function () { var Panel = createClass({ components: { Header: createClass({}), Footer: createClass({}) } }); assert(_has(Panel, 'Header'), 'must have `Header` as a static property'); assert(_has(Panel, 'Footer'), 'must have `Footer` as a static property'); }); it('should make `reducers` a static property.', function () { var panelReducers = { // eslint-disable-next-line @typescript-eslint/no-empty-function onExpand: function onExpand() {} }; var Panel = createClass({ reducers: panelReducers }); assert(_has(Panel, 'reducers'), 'must have `reducers` as a static property'); assert.equal(_get(Panel, 'reducers'), panelReducers, 'static `reducers` must equal defined reducers'); }); it('should make `selectors` a static property.', function () { var panelSelectors = { isValid: function isValid() {} }; var Panel = createClass({ selectors: panelSelectors }); assert(_has(Panel, 'selectors'), 'must have `selectors` as a static property'); assert.equal(_get(Panel, 'selectors'), panelSelectors, 'static `selectors` must equal defined selectors'); }); it('should make `initialState` a static property.', function () { var initialState = { foo: 'bar' }; var Panel = createClass({ initialState: initialState }); assert(_has(Panel, 'initialState'), 'must have `initialState` as a static property'); assert.equal(_get(Panel, 'initialState'), initialState, 'static `initialState` must equal defined initialState'); }); it('should use `getDefaultProps` for default initialState', function () { var defaultProps = { baz: 'qux' }; var Panel = createClass({ getDefaultProps: function getDefaultProps() { return defaultProps; } }); assert(_has(Panel, 'initialState'), 'must have `initialState` as a static property'); assert.deepEqual(_get(Panel, 'initialState'), defaultProps, 'static `initialState` must equal return value of `getDefaultProps`'); }); it('should move `getDefaultProps` to `defaultProps` on the returned item', function () { var defaultProps = { name: 'jon' }; var NameBadge = createClass({ getDefaultProps: function getDefaultProps() { return defaultProps; } }); assert(!_has(NameBadge, 'getDefaultProps'), 'must not have `getDefaultProps` as a static property'); assert.deepEqual(NameBadge.defaultProps, defaultProps, 'static `defaultProps` must equal expected value passed as `getDefaultProps`'); }); it('should make `propName` a static property.', function () { var Panel = createClass({ propName: ['Panel', 'panel', 'panels'] }); assert(_has(Panel, 'propName'), 'must have `propName` as a static property'); assert(_isEqual(_get(Panel, 'propName'), ['Panel', 'panel', 'panels']), 'static `propName` must equal defined prop names'); }); }); describe('filterTypes', function () { it('should filter elements by a single component type', function () { var Option = createClass({}); var elements = [/*#__PURE__*/React.createElement("span", { key: "1" }, "Many"), /*#__PURE__*/React.createElement(Option, { key: "2" }, "Hands"), /*#__PURE__*/React.createElement("span", { key: "3" }, "Make"), /*#__PURE__*/React.createElement(Option, { key: "4" }, "Light"), /*#__PURE__*/React.createElement("span", { key: "5" }, "Work")]; var spanElements = filterTypes(elements, 'span'); assert.equal(3, spanElements.length, 'length must be 3'); assert( /*#__PURE__*/React.isValidElement(spanElements[0]), 'must be a valid React element'); assert.equal('Many', shallow(spanElements[0]).text(), 'text must be `Many`'); assert( /*#__PURE__*/React.isValidElement(spanElements[1]), 'must be a valid React element'); assert.equal('Make', shallow(spanElements[1]).text(), 'text must be `Make`'); assert( /*#__PURE__*/React.isValidElement(spanElements[2]), 'must be a valid React element'); assert.equal('Work', shallow(spanElements[2]).text(), 'text must be `Work`'); }); it('should filter elements by many component types', function () { var Option = createClass({}); var elements = [/*#__PURE__*/React.createElement("span", { key: "1" }, "Many"), /*#__PURE__*/React.createElement(Option, { key: "2" }, "Hands"), /*#__PURE__*/React.createElement("section", { key: "3" }, "Make"), /*#__PURE__*/React.createElement(Option, { key: "4" }, "Light"), /*#__PURE__*/React.createElement("section", { key: "5" }, "Work")]; var spanElements = filterTypes(elements, ['section', Option]); assert.equal(4, spanElements.length, 'length must be 4'); assert( /*#__PURE__*/React.isValidElement(spanElements[0]), 'must be a valid React element'); assert.equal(Option, spanElements[0].type, 'type must be `Option`'); assert( /*#__PURE__*/React.isValidElement(spanElements[1]), 'must be a valid React element'); assert.equal('Make', shallow(spanElements[1]).text(), 'text must be `Make`'); assert( /*#__PURE__*/React.isValidElement(spanElements[2]), 'must be a valid React element'); assert.equal(Option, spanElements[0].type, 'type must be `Option`'); assert( /*#__PURE__*/React.isValidElement(spanElements[3]), 'must be a valid React element'); assert.equal('Work', shallow(spanElements[3]).text(), 'text must be `Work`'); }); }); describe('rejectTypes', function () { it('should reject elements of a single component type', function () { var Option = createClass({}); var elements = [/*#__PURE__*/React.createElement("span", { key: "1" }, "Many"), /*#__PURE__*/React.createElement(Option, { key: "2" }, "Hands"), /*#__PURE__*/React.createElement("span", { key: "3" }, "Make"), /*#__PURE__*/React.createElement(Option, { key: "4" }, "Light"), /*#__PURE__*/React.createElement("span", { key: "5" }, "Work")]; var nonSpanElements = rejectTypes(elements, 'span'); assert.equal(2, nonSpanElements.length, 'length must be 2'); assert( /*#__PURE__*/React.isValidElement(nonSpanElements[0]), 'must be a valid React element'); assert.equal(Option, nonSpanElements[0].type, 'type must be `Option`'); assert.equal('Hands', nonSpanElements[0].props.children, 'first element must have the string `Hands`'); assert( /*#__PURE__*/React.isValidElement(nonSpanElements[1]), 'must be a valid React element'); assert.equal(Option, nonSpanElements[1].type, 'type must be `Option`'); assert.equal('Light', nonSpanElements[1].props.children, 'second element must have the string `Light`'); }); it('should reject elements of many component types', function () { var Option = createClass({}); var elements = [/*#__PURE__*/React.createElement("span", { key: "1" }, "Many"), /*#__PURE__*/React.createElement(Option, { key: "2" }, "Hands"), /*#__PURE__*/React.createElement("section", { key: "3" }, "Make"), /*#__PURE__*/React.createElement(Option, { key: "4" }, "Light"), /*#__PURE__*/React.createElement("span", { key: "5" }, "Work")]; var remainingElements = rejectTypes(elements, [Option, 'span']); assert.equal(1, remainingElements.length, 'length must be 1'); assert( /*#__PURE__*/React.isValidElement(remainingElements[0]), 'must be a valid React element'); assert.equal('section', shallow(remainingElements[0]).type(), 'type must be `section`'); assert.equal('Make', shallow(remainingElements[0]).text(), 'element must have the string `Make`'); }); }); describe('createElements', function () { it('should create elements of the given type from the array', function () { var Option = createClass({}); var elements = createElements(Option, [/*#__PURE__*/React.createElement(Option, { key: "1" }), /*#__PURE__*/React.createElement("button", { key: "2" }), 'red', null, { isDisabled: true }]); assert.equal(5, elements.length, 'length must be 5'); _forEach(elements, function (element) { assert.equal(Option, element.type, 'type must be Option'); }); assert.equal('button', elements[1].props.children.type, 'element must be a button'); assert.equal('red', elements[2].props.children, 'element children must be `red`'); assert(_isNull(elements[3].props.children), 'must pass null values through'); assert(_isEqual({ isDisabled: true }, elements[4].props), 'element props must match'); }); }); describe('findTypes', function () { it('should find all elements of the same type from children', function (done) { var Option = createClass({ propName: 'option' }); var Selector = createClass({ render: function render() { var optionElements = findTypes(this.props, Option); assert.equal(2, optionElements.length, 'length must be 2'); assert.equal(true, _get(optionElements[0].props, 'isDisabled'), 'element must have prop `isDisabled`'); assert.equal('Select red', _get(optionElements[1].props, 'title'), 'element must have prop `title`'); done(); } }); shallow( /*#__PURE__*/React.createElement(Selector, null, /*#__PURE__*/React.createElement("button", null), /*#__PURE__*/React.createElement(Option, { isDisabled: true }), /*#__PURE__*/React.createElement("button", null), /*#__PURE__*/React.createElement(Option, { title: "Select red" }, "Red"), /*#__PURE__*/React.createElement("button", null))); }); it('should find all elements of the same type from props if type has `propName` defined', function (done) { var Option = createClass({ propName: ['option', 'options'] }); var Selector = createClass({ render: function render() { var optionElements = findTypes(this.props, Option); assert.equal(3, optionElements.length, 'length must be 3'); assert.equal('red', _get(optionElements[0].props, 'children'), 'element children must match prop value'); assert(_isEqual({ children: 'green', isDisabled: true }, optionElements[1].props), 'element props must match props'); assert.equal('blue', _get(optionElements[2].props, 'children'), 'element children must match prop value'); done(); } }); shallow( /*#__PURE__*/React.createElement(Selector, { option: "red", options: [{ children: 'green', isDisabled: true }, 'blue'] })); }); it('should find all elements of the same type from props and children', function (done) { var Option = createClass({ propName: ['option', 'options'] }); var Selector = createClass({ render: function render() { var optionElements = findTypes(this.props, Option); assert.equal(5, optionElements.length, 'length must be 3'); assert.equal('red', _get(optionElements[0].props, 'children'), 'element children must match prop value'); assert(_isEqual({ children: 'green', isDisabled: true }, optionElements[1].props), 'element props must match props'); assert.equal('blue', _get(optionElements[2].props, 'children'), 'element children must match prop value'); assert.equal(true, _get(optionElements[3].props, 'isDisabled'), 'element must have prop `isDisabled`'); assert.equal('Select red', _get(optionElements[4].props, 'title'), 'element must have prop `title`'); done(); } }); shallow( /*#__PURE__*/React.createElement(Selector, { option: "red", options: [{ children: 'green', isDisabled: true }, 'blue'] }, /*#__PURE__*/React.createElement("button", null), /*#__PURE__*/React.createElement(Option, { isDisabled: true }), /*#__PURE__*/React.createElement("button", null), /*#__PURE__*/React.createElement(Option, { title: "Select red" }, "Red"), /*#__PURE__*/React.createElement("button", null))); }); }); describe('omitProps', function () { var Button = createClass({ propTypes: { className: PropTypes.any, isActive: PropTypes.any, isDisabled: PropTypes.any, kind: PropTypes.any, size: PropTypes.any } }); it('should omit props which are defined in propTypes', function () { var props = omitProps({ className: 'test-button', text: 'Click Me', isActive: true, isPrimary: true, size: 'normal' }, Button); assert.deepEqual(props, { text: 'Click Me', isPrimary: true }, 'must omit props defined in propTypes'); }); it('should omit `callbackId` from props by default', function () { var props = omitProps({ className: 'test-button', text: 'Click Me', isActive: true, isPrimary: true, size: 'normal', callbackId: 'cant find me' }, Button); assert.deepEqual(props, { text: 'Click Me', isPrimary: true }, 'must omit props defined in propTypes'); }); it('should not omit `callbackId` from props when specified', function () { var props = omitProps({ className: 'test-button', text: 'Click Me', isActive: true, isPrimary: true, size: 'normal', callbackId: 'can find me' }, Button, [], false); assert.deepEqual(props, { text: 'Click Me', isPrimary: true, callbackId: 'can find me' }, 'must omit props defined in propTypes'); }); }); });