Skip to content

Commit

Permalink
Merge pull request react-bootstrap#1034 from AlexKVal/stylesValidation
Browse files Browse the repository at this point in the history
Custom styles with no validation
  • Loading branch information
AlexKVal committed Jul 25, 2015
2 parents 2f45d1b + fd3e509 commit 485b33f
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 186 deletions.
10 changes: 7 additions & 3 deletions src/BootstrapMixin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react';
import styleMaps from './styleMaps';
import CustomPropTypes from './utils/CustomPropTypes';

Expand All @@ -12,7 +13,7 @@ const BootstrapMixin = {
* Style variants
* @type {("default"|"primary"|"success"|"info"|"warning"|"danger"|"link")}
*/
bsStyle: CustomPropTypes.keyOf(styleMaps.STYLES),
bsStyle: React.PropTypes.oneOf(styleMaps.STYLES),
/**
* Size variants
* @type {("xsmall"|"small"|"medium"|"large")}
Expand All @@ -34,9 +35,12 @@ const BootstrapMixin = {
classes[prefix + bsSize] = true;
}

let bsStyle = this.props.bsStyle && styleMaps.STYLES[this.props.bsStyle];
if (this.props.bsStyle) {
classes[prefix + bsStyle] = true;
if (styleMaps.STYLES.indexOf(this.props.bsStyle) >= 0) {
classes[prefix + this.props.bsStyle] = true;
} else {
classes[this.props.bsStyle] = true;
}
}
}

Expand Down
26 changes: 13 additions & 13 deletions src/styleMaps.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ const styleMaps = {
'row': 'row',
'well': 'well'
},
STYLES: {
'default': 'default',
'primary': 'primary',
'success': 'success',
'info': 'info',
'warning': 'warning',
'danger': 'danger',
'link': 'link',
'inline': 'inline',
'tabs': 'tabs',
'pills': 'pills'
},
STYLES: [
'default',
'primary',
'success',
'info',
'warning',
'danger',
'link',
'inline',
'tabs',
'pills'
],
addStyle(name) {
styleMaps.STYLES[name] = name;
styleMaps.STYLES.push(name);
},
SIZES: {
'large': 'lg',
Expand Down
254 changes: 84 additions & 170 deletions test/BootstrapMixinSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import ReactTestUtils from 'react/lib/ReactTestUtils';
import BootstrapMixin from '../src/BootstrapMixin';
import styleMaps from '../src/styleMaps';
import { shouldWarn } from './helpers';

let Component;

Expand All @@ -26,185 +27,98 @@ describe('BootstrapMixin', function () {
assert.deepEqual(instance.getBsClassSet(), {});
});

it('should return "col"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='column'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'col': true});
});

it('should return "btn"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true});
});

it('should return "btn-group"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button-group'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn-group': true});
});

it('should return "label"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='label'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'label': true});
});

it('should return "alert"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='alert'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'alert': true});
});

it('should return "input-group"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='input-group'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'input-group': true});
});

it('should return "form"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='form'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'form': true});
});

it('should return "panel"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='panel'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'panel': true});
});

it('should return "btn btn-default"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='default'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-default': true});
});

it('should return "btn btn-primary"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='primary'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-primary': true});
});

it('should return "btn btn-success"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='success'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-success': true});
});

it('should return "btn btn-info"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='info'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-info': true});
});

it('should return "btn btn-link"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='link'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-link': true});
});

it('should return "btn btn-inline"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='inline'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-inline': true});
});

it('should return "btn btn-lg"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsSize='large'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-lg': true});
});

it('should return "btn btn-md"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsSize='medium'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-md': true});
});

it('should return "btn btn-sm"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsSize='small'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-sm': true});
});
it('maps and validates OK default classes', function () {
function instanceClassSet(bsClass) {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass={bsClass}>
content
</Component>
);
return instance.getBsClassSet();
}

it('should return "btn btn-xs"', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsSize='xsmall'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-xs': true});
assert.deepEqual(instanceClassSet('column'), {'col': true});
assert.deepEqual(instanceClassSet('button'), {'btn': true});
assert.deepEqual(instanceClassSet('button-group'), {'btn-group': true});
assert.deepEqual(instanceClassSet('label'), {'label': true});
assert.deepEqual(instanceClassSet('alert'), {'alert': true});
assert.deepEqual(instanceClassSet('input-group'), {'input-group': true});
assert.deepEqual(instanceClassSet('form'), {'form': true});
assert.deepEqual(instanceClassSet('panel'), {'panel': true});
});

describe('Predefined Bootstrap styles', function () {
it('maps and validates OK default styles', function () {
function instanceClassSet(style) {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle={style}>
content
</Component>
);
return instance.getBsClassSet();
}

assert.deepEqual(instanceClassSet('default'), {'btn': true, 'btn-default': true});
assert.deepEqual(instanceClassSet('primary'), {'btn': true, 'btn-primary': true});
assert.deepEqual(instanceClassSet('success'), {'btn': true, 'btn-success': true});
assert.deepEqual(instanceClassSet('info'), {'btn': true, 'btn-info': true});
assert.deepEqual(instanceClassSet('link'), {'btn': true, 'btn-link': true});
assert.deepEqual(instanceClassSet('inline'), {'btn': true, 'btn-inline': true});
});
});

describe('Sizes', function () {
it('maps english words for sizes to bootstrap sizes constants', function () {
function instanceClassSet(size) {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsSize={size}>
content
</Component>
);
return instance.getBsClassSet();
}

assert.deepEqual(instanceClassSet('large'), {'btn': true, 'btn-lg': true});
assert.deepEqual(instanceClassSet('small'), {'btn': true, 'btn-sm': true});
assert.deepEqual(instanceClassSet('medium'), {'btn': true, 'btn-md': true});
assert.deepEqual(instanceClassSet('xsmall'), {'btn': true, 'btn-xs': true});
});
});

describe('Custom styles', function () {
it('should validate OK custom styles added via "addStyle()"', function () {

styleMaps.addStyle('wacky');

let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='wacky'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-wacky': true});
});

it('should allow custom styles as is but with validation warning', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='my-custom-class'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'my-custom-class': true});
shouldWarn('Invalid prop `bsStyle` of value `my-custom-class`');
});
});
});

it('should return "btn-title"', function () {
// todo: fix bad naming
describe('#prefixClass', function () {
it('allows custom sub-classes', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button'>
content
</Component>
);
assert.equal(instance.prefixClass('title'), 'btn-title');
});

it('should return "btn btn-wacky"', function () {
styleMaps.addStyle('wacky');
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='wacky'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-wacky': true});
});
});
});

0 comments on commit 485b33f

Please sign in to comment.