lucid-ui
Version:
A UI component library from AppNexus.
269 lines • 15.1 kB
JavaScript
;
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