diff --git a/spec/pivotal-ui-react/helpers/helpers_spec.js b/spec/pivotal-ui-react/helpers/helpers_spec.js new file mode 100644 index 000000000..af5829935 --- /dev/null +++ b/spec/pivotal-ui-react/helpers/helpers_spec.js @@ -0,0 +1,138 @@ +require('../spec_helper'); +import {mergeProps} from '../../../src/pivotal-ui-react/helpers/helpers'; + +describe('mergeProps', function() { + let subject; + let defaultProps; + beforeEach(function() { + subject = {props: {}}; + }); + + function mergedProps() { + return mergeProps(subject.props, defaultProps); + } + + describe('when default props are provided', function() { + beforeEach(function() { + // provide default props + defaultProps = { + className: 'class1', + id: 'id1', + style: { + display: 'block', + background: 'blue' + }, + randomKey1: 'preamble' + }; + + }); + + describe('when overriding props are provided', function() { + beforeEach(function() { + subject.props = { + className: 'class2', + id: 'id2', + style: {display: 'inline'}, + randomKey2: 'stuff', + randomKey3: 'things' + }; + }); + + it('overrides the id', function() { + expect(mergedProps().id).toEqual(subject.props.id); + }); + + it('overrides keys under style that are provided', function() { + expect(mergedProps().style.display).toEqual(subject.props.style.display); + }); + + it('does not override keys under style that are not provided', function() { + expect(mergedProps().style.background).toEqual(defaultProps.style.background); + }); + + it('combines classNames', function() { + let classNames = mergedProps().className.split(/\s+/); + expect(classNames).toContain('class1'); + expect(classNames).toContain('class2'); + expect(classNames.length).toEqual(2); + }); + + it('combines the remainingProps', function() { + expect(mergedProps().randomKey1).toEqual(defaultProps.randomKey1); + expect(mergedProps().randomKey2).toEqual(subject.props.randomKey2); + expect(mergedProps().randomKey3).toEqual(subject.props.randomKey3); + }); + }); + + describe('when overriding props are not provided', function() { + it('uses the default id', function() { + expect(mergedProps().id).toEqual(defaultProps.id); + }); + + it('uses the default style', function() { + expect(mergedProps().style).toEqual(defaultProps.style); + }); + + it('uses the default className', function() { + expect(mergedProps().className).toEqual(defaultProps.className); + }); + + it('uses the default remainingProps', function() { + expect(mergedProps().randomKey1).toEqual(defaultProps.randomKey1); + }); + }); + }); + + describe('when default props are not provided', function() { + describe('when overriding props are provided', function() { + beforeEach(function() { + defaultProps = {}; + subject.props = { + className: 'class2', + id: 'id2', + style: {display: 'inline'}, + randomKey2: 'stuff', + randomKey3: 'things' + }; + }); + + it('uses the overridden id', function() { + expect(mergedProps().id).toEqual(subject.props.id); + }); + + it('uses the overridden style', function() { + expect(mergedProps().style).toEqual(subject.props.style); + }); + + + it('uses the overridden classNames', function() { + expect(mergedProps().className).toEqual(subject.props.className); + }); + + it('uses the overridden remainingProps', function() { + expect(mergedProps().randomKey2).toEqual(subject.props.randomKey2); + expect(mergedProps().randomKey3).toEqual(subject.props.randomKey3); + }); + }); + + describe('when overriding props are not provided', function() { + beforeEach(function() { + defaultProps = {}; + subject.props = {}; + }); + + it('uses an undefined id', function() { + expect(mergedProps().id).toEqual(undefined); + }); + + it('uses an empty style', function() { + expect(mergedProps().style).toEqual({}); + }); + + + it('uses an empty string for className', function() { + expect(mergedProps().className).toEqual(''); + }); + }); + }); +}); diff --git a/src/pivotal-ui-react/helpers/helpers.js b/src/pivotal-ui-react/helpers/helpers.js new file mode 100644 index 000000000..5f6133c31 --- /dev/null +++ b/src/pivotal-ui-react/helpers/helpers.js @@ -0,0 +1,49 @@ +import classnames from 'classnames'; + +/** + * @component mergeProps + * @description A helper function that merges default props and provided props + * + * @param reactInstanceProps properties passed into the component. Typically + * `this.props` + * + * @param defaultProps default values for the react component + * + * @return a merged hash of props, giving precedence to the `reactInstanceProps`. + * If `className` is defined by both sets of props, the resultant `className` + * will be a combination of the two. + * If `style` is defined by both, the resultant `style` hash will be a merge of + * the two style hashes, with precedence given to `reactInstanceProps`'s style. + * + * @example ```js + * var {mergeProps} = require('pui-react-helpers'); + * + * var Ribbon = React.createClass({ + * render() { + * var {children, ...others} = this.props; + * var props = mergeProps(others, {className: 'ribbon', style: {height: '50px', color: 'blue'}, id: 'default-ribbon-id'}); + * return