diff --git a/src/BootstrapMixin.js b/src/BootstrapMixin.js
index df8795de4d..17c8e81d2b 100644
--- a/src/BootstrapMixin.js
+++ b/src/BootstrapMixin.js
@@ -1,3 +1,4 @@
+import React from 'react';
import styleMaps from './styleMaps';
import CustomPropTypes from './utils/CustomPropTypes';
@@ -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")}
@@ -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;
+ }
}
}
diff --git a/src/styleMaps.js b/src/styleMaps.js
index a200286d33..49ad80f3f0 100644
--- a/src/styleMaps.js
+++ b/src/styleMaps.js
@@ -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',
diff --git a/test/BootstrapMixinSpec.js b/test/BootstrapMixinSpec.js
index 333870506b..9c7b519120 100644
--- a/test/BootstrapMixinSpec.js
+++ b/test/BootstrapMixinSpec.js
@@ -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;
@@ -26,169 +27,92 @@ describe('BootstrapMixin', function () {
assert.deepEqual(instance.getBsClassSet(), {});
});
- it('should return "col"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'col': true});
- });
-
- it('should return "btn"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true});
- });
-
- it('should return "btn-group"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn-group': true});
- });
-
- it('should return "label"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'label': true});
- });
-
- it('should return "alert"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'alert': true});
- });
-
- it('should return "input-group"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'input-group': true});
- });
-
- it('should return "form"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'form': true});
- });
-
- it('should return "panel"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'panel': true});
- });
-
- it('should return "btn btn-default"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-default': true});
- });
-
- it('should return "btn btn-primary"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-primary': true});
- });
-
- it('should return "btn btn-success"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-success': true});
- });
-
- it('should return "btn btn-info"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-info': true});
- });
-
- it('should return "btn btn-link"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-link': true});
- });
-
- it('should return "btn btn-inline"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-inline': true});
- });
-
- it('should return "btn btn-lg"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-lg': true});
- });
-
- it('should return "btn btn-md"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-md': true});
- });
-
- it('should return "btn btn-sm"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-sm': true});
- });
+ it('maps and validates OK default classes', function () {
+ function instanceClassSet(bsClass) {
+ let instance = ReactTestUtils.renderIntoDocument(
+
+ content
+
+ );
+ return instance.getBsClassSet();
+ }
- it('should return "btn btn-xs"', function () {
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- 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(
+
+ content
+
+ );
+ 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(
+
+ content
+
+ );
+ 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(
+
+ content
+
+ );
+ 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(
+
+ content
+
+ );
+ 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(
content
@@ -196,15 +120,5 @@ describe('BootstrapMixin', function () {
);
assert.equal(instance.prefixClass('title'), 'btn-title');
});
-
- it('should return "btn btn-wacky"', function () {
- styleMaps.addStyle('wacky');
- let instance = ReactTestUtils.renderIntoDocument(
-
- content
-
- );
- assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-wacky': true});
- });
});
});