UNPKG

lucid-ui

Version:

A UI component library from AppNexus.

269 lines 15.1 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.mockDate = exports.functionalComponents = exports.controls = exports.icons = exports.common = void 0; var sinon_1 = __importDefault(require("sinon")); var path_1 = require("path"); var react_1 = __importDefault(require("react")); var prop_types_1 = __importDefault(require("prop-types")); var enzyme_1 = require("enzyme"); var assert_1 = __importDefault(require("assert")); var lodash_1 = __importStar(require("lodash")); var glob_1 = __importDefault(require("glob")); var lucid = __importStar(require("../index")); // Common tests for all our components function common(Component, _a) { var _b = _a === void 0 ? {} : _a, _c = _b.getDefaultProps, getDefaultProps = _c === void 0 ? lodash_1.default.constant({}) : _c, _d = _b.exemptFunctionProps, exemptFunctionProps = _d === void 0 ? [] : _d, _e = _b.exemptChildComponents, exemptChildComponents = _e === void 0 ? [] : _e, _f = _b.selectRoot, selectRoot = _f === void 0 ? lodash_1.default.identity : _f, _g = _b.noExport, noExport = _g === void 0 ? false : _g; function generateDefaultProps(props) { if (props === void 0) { props = {}; } return lodash_1.default.assign({}, getDefaultProps(), props); } describe('[common]', function () { if (!Component) { throw new Error('An undefined component was passed to generic tests.'); } if (Component._isLucidHybridComponent) { throw new Error("You're trying to run generic tests on a hybrid component which is bad and won't work and will make you cry. Check your spec files for " + Component.displayName + " and import the raw component instead of the hybrid version."); } it('should have a `displayName` defined', function () { assert_1.default(Component.displayName); }); it('should pass through styles to the root element', function () { var style = { backgroundColor: '#f0f', }; var wrapper = enzyme_1.shallow(react_1.default.createElement(Component, __assign({}, generateDefaultProps(), { style: style })), { disableLifecycleMethods: true }); var rootWrapper = selectRoot(wrapper).first(); var rootStyle = rootWrapper.prop('style'); assert_1.default(lodash_1.default.every(style, function (val, key) { return val === rootStyle[key]; }), 'root style must contain passed styles'); }); it('should pass through `className`', function () { var expectedClass = 'rAnDoM'; var wrapper = enzyme_1.shallow(react_1.default.createElement(Component, __assign({}, generateDefaultProps(), { className: expectedClass })), { disableLifecycleMethods: true }); var rootWrapper = selectRoot(wrapper).first(); var classNames = rootWrapper.prop('className').split(' '); assert_1.default(lodash_1.default.includes(classNames, expectedClass), "'" + classNames + "' should include '" + expectedClass + "'"); }); it('should have an application scoped base class', function () { var expectedClass = 'lucid-' + Component.displayName; var wrapper = enzyme_1.shallow(react_1.default.createElement(Component, __assign({}, generateDefaultProps())), { disableLifecycleMethods: true, }); var rootWrapper = selectRoot(wrapper).first(); var classNames = rootWrapper.prop('className').split(' '); assert_1.default(lodash_1.default.includes(classNames, expectedClass), "'" + classNames + "' should include '" + Component.displayName + "'"); }); it('should have only application scoped classes', function () { var wrapper = enzyme_1.shallow(react_1.default.createElement(Component, __assign({}, generateDefaultProps())), { disableLifecycleMethods: true, }); var rootWrapper = selectRoot(wrapper).first(); var parentClasses = rootWrapper.prop('className').split(' '); var childrenClasses = rootWrapper.children().reduce(function (acc, node) { if (!node.prop('className')) { return acc; } return acc.concat(node.prop('className').split(' ')); }, []); var allClasses = parentClasses.concat(childrenClasses); lodash_1.default.forEach(allClasses, function (className) { assert_1.default(lodash_1.default.includes(className, "lucid-" + Component.displayName), className + " must be scoped"); }); }); describe('function propTypes', function () { var funcProps = lodash_1.default.pickBy(Component.propTypes, function (propType) { return propType === prop_types_1.default.func; }); lodash_1.default.forEach(funcProps, function (propType, propName) { it(propName + " should only use onX convention for function proptypes", function () { assert_1.default(lodash_1.default.startsWith(propName, 'on') || lodash_1.default.includes(exemptFunctionProps, propName), propName + " must follow onX convention"); }); }); }); describe('child components', function () { // Child components are all function types which start with a capital letter var childComponents = lodash_1.default.pickBy(Component, function (value, key) { return /^[A-Z]/.test(key) && lodash_1.default.isFunction(value); }); describe('propNames in propTypes', function () { lodash_1.default.flow(function (x) { return lodash_1.default.map(x, 'propName'); }, function (x) { return lodash_1.default.compact(x); }, function (x) { return lodash_1.default.flatMap(x, lodash_1.default.castArray); }, function (x) { return lodash_1.default.reject(x, function (propName) { return lodash_1.default.includes(exemptChildComponents, propName); }); }, function (x) { return lodash_1.default.forEach(x, function (propName) { it("should include " + propName + " in propTypes", function () { assert_1.default(Component.propTypes[propName], "must include " + propName + " in propTypes"); }); }); })(childComponents); }); }); describe('example testing', function () { var fileNames = glob_1.default.sync("./src/components/**/" + Component.displayName + "/*.stories.@(j|t)sx"); lodash_1.each(fileNames, function (path) { var lib = require('../../' + path.replace('.tsx', '')); lodash_1.each(lodash_1.omit(lib, ['default']), function (Story, name) { it("should match snapshot(s) for " + name, function () { expect(enzyme_1.shallow(react_1.default.createElement(Story, null), { disableLifecycleMethods: true, })).toMatchSnapshot(); }); }); }); // Support for older examples var exampleFileNames = glob_1.default.sync("./src/components/**/" + Component.displayName + "/examples/*.@(j|t)sx"); lodash_1.default.each(exampleFileNames, function (path) { var lib = require('../../' + path.replace('.tsx', '')); var Example = lib.default; var title = path_1.parse(path).name; it("should match snapshot(s) for " + title, function () { var shallowExample = enzyme_1.shallow(react_1.default.createElement(Example, null), { disableLifecycleMethods: true, }); // If the root of the example is an instance of the Component under test, snapshot it. // Otherwise, look under the root for instances of the Component and snapshot those. if (shallowExample.is(Component.displayName)) { expect(enzyme_1.shallow(react_1.default.createElement(Component, __assign({}, shallowExample.props())), { disableLifecycleMethods: true, })).toMatchSnapshot(); } else { shallowExample.find(Component.displayName).forEach(function (example) { expect(enzyme_1.shallow(react_1.default.createElement(Component, __assign({}, example.props())), { disableLifecycleMethods: true, })).toMatchSnapshot(); }); } }); }); }); // Only run this test if it's a public component if (!Component._isPrivate && !noExport) { it('should be available as an exported module from index.ts', function () { assert_1.default(lucid[Component.displayName]); }); } }); } exports.common = common; // Common tests for all our icon components function icons(Component) { describe('[icon]', function () { it('should add the correct class for isClickable', function () { var wrapper = enzyme_1.mount(react_1.default.createElement(Component, { isClickable: true })); var targetClassName = 'lucid-Icon-is-clickable'; assert_1.default(wrapper.find('svg').hasClass(targetClassName), "Missing '" + targetClassName + "' class"); }); }); } exports.icons = icons; // Common tests for all control components function controls(Component, _a) { var callbackName = _a.callbackName, controlSelector = _a.controlSelector, eventType = _a.eventType, _b = _a.additionalProps, additionalProps = _b === void 0 ? {} : _b; // Use DOM tests here since some of our controls use dom events under the hood describe('[control]', function () { it('should callback with `event` and `props`', function () { var _a; var expectedSpecialProp = 32; var props = __assign((_a = { specialProp: expectedSpecialProp }, _a[callbackName] = sinon_1.default.spy(), _a), additionalProps); var wrapper = enzyme_1.mount(react_1.default.createElement(Component, __assign({}, props))); wrapper.find(controlSelector).first().simulate(eventType); // Last argument should be an object with `uniqueId` and `event` var _b = lodash_1.default.last(props[callbackName].args[0]), specialProp = _b.props.specialProp, event = _b.event; assert_1.default(event, 'missing event'); assert_1.default.equal(specialProp, expectedSpecialProp, 'incorrect or missing specialProp'); }); }); } exports.controls = controls; // Common tests for all Functional Components // // These tests are intended to help us make sure our FCs are shaped corrected. // They are necessary because there isn't a perfect way to get the defaultProps // to be factored in correctly yet with React/TypeScript: // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30695#issuecomment-474780159 function functionalComponents(FC) { // Use DOM tests here since some of our controls use dom events under the hood describe('[functionalComponent]', function () { it('should have the correct `peek` properties', function () { expect(FC.propName === undefined || typeof FC.propName === 'string').toBe(true); expect(FC._isPrivate === undefined || typeof FC._isPrivate === 'boolean').toBe(true); expect(typeof FC.peek).toBe('object'); expect(typeof FC.peek.description).toBe('string'); expect(FC.peek.extend === undefined || typeof FC.peek.extend === 'string').toBe(true); expect(FC.peek.extend === undefined || typeof FC.peek.extend === 'string').toBe(true); expect(FC.peek.categories === undefined || Array.isArray(FC.peek.categories)).toBe(true); expect(FC.peek.madeFrom === undefined || Array.isArray(FC.peek.madeFrom)).toBe(true); }); }); } exports.functionalComponents = functionalComponents; var NativeDate = global.Date; var createMockDateClass = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return lodash_1.default.assign(function MockDate() { // @ts-ignore return new (NativeDate.bind.apply(NativeDate, __spreadArrays([void 0], args)))(); }, { UTC: NativeDate.UTC, parse: NativeDate.parse, // @ts-ignore now: function () { return new (NativeDate.bind.apply(NativeDate, __spreadArrays([void 0], args)))().getTime(); }, prototype: NativeDate.prototype, }); }; exports.mockDate = lodash_1.default.assign(function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } // @ts-ignore global.Date = createMockDateClass.apply(void 0, args); }, { restore: function () { global.Date = NativeDate; }, }); //# sourceMappingURL=generic-tests.js.map