Skip to content

Commit

Permalink
feat(helpers): add pui-react-helpers module, with mergeProps func…
Browse files Browse the repository at this point in the history
…tion

[#87784030]
  • Loading branch information
Caroline Taymor, Douglas Blumeyer, Kenny Wang and Matt Royal authored and Caroline Taymor, Kenny Wang and Matt Royal committed Jul 15, 2015
1 parent b61f530 commit ea0d732
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 0 deletions.
138 changes: 138 additions & 0 deletions spec/pivotal-ui-react/helpers/helpers_spec.js
Original file line number Diff line number Diff line change
@@ -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('');
});
});
});
});
49 changes: 49 additions & 0 deletions src/pivotal-ui-react/helpers/helpers.js
Original file line number Diff line number Diff line change
@@ -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 <div {...props}>{children}</div>;
* }
* });
*
* React.render(<Ribbon className="my-ribbon" style={{height: '25px'}} id="unique-ribbon-id" />, myNode);
* // Resultant props: {className: 'ribbon my-ribbon', style: {height: '25px', color: 'blue'}, id: 'unique-ribbon-id'}
* ```
*/

export function mergeProps(reactInstanceProps, defaultProps) {
let {className, id, style, ...remainingProps} = reactInstanceProps;
let {
className: defaultClassName,
id: defaultId,
style: defaultStyle={},
...remainingDefaultProps
} = defaultProps;

className = classnames(defaultClassName, className);
style = {...defaultStyle, ...style};
id = id || defaultId;
remainingProps = {...remainingDefaultProps, ...remainingProps};

return {className, id, style, ...remainingProps};
}
7 changes: 7 additions & 0 deletions src/pivotal-ui-react/helpers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"version": "0.0.2",
"description": "A collection of helpers used by pivotal-ui-react components",
"dependencies": {
"classnames": "^2.1.2"
}
}

0 comments on commit ea0d732

Please sign in to comment.