Skip to content

Commit 485b33f

Browse files
committed
Merge pull request react-bootstrap#1034 from AlexKVal/stylesValidation
Custom styles with no validation
2 parents 2f45d1b + fd3e509 commit 485b33f

File tree

3 files changed

+104
-186
lines changed

3 files changed

+104
-186
lines changed

src/BootstrapMixin.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import React from 'react';
12
import styleMaps from './styleMaps';
23
import CustomPropTypes from './utils/CustomPropTypes';
34

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

37-
let bsStyle = this.props.bsStyle && styleMaps.STYLES[this.props.bsStyle];
3838
if (this.props.bsStyle) {
39-
classes[prefix + bsStyle] = true;
39+
if (styleMaps.STYLES.indexOf(this.props.bsStyle) >= 0) {
40+
classes[prefix + this.props.bsStyle] = true;
41+
} else {
42+
classes[this.props.bsStyle] = true;
43+
}
4044
}
4145
}
4246

src/styleMaps.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@ const styleMaps = {
2121
'row': 'row',
2222
'well': 'well'
2323
},
24-
STYLES: {
25-
'default': 'default',
26-
'primary': 'primary',
27-
'success': 'success',
28-
'info': 'info',
29-
'warning': 'warning',
30-
'danger': 'danger',
31-
'link': 'link',
32-
'inline': 'inline',
33-
'tabs': 'tabs',
34-
'pills': 'pills'
35-
},
24+
STYLES: [
25+
'default',
26+
'primary',
27+
'success',
28+
'info',
29+
'warning',
30+
'danger',
31+
'link',
32+
'inline',
33+
'tabs',
34+
'pills'
35+
],
3636
addStyle(name) {
37-
styleMaps.STYLES[name] = name;
37+
styleMaps.STYLES.push(name);
3838
},
3939
SIZES: {
4040
'large': 'lg',

test/BootstrapMixinSpec.js

Lines changed: 84 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import ReactTestUtils from 'react/lib/ReactTestUtils';
33
import BootstrapMixin from '../src/BootstrapMixin';
44
import styleMaps from '../src/styleMaps';
5+
import { shouldWarn } from './helpers';
56

67
let Component;
78

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

29-
it('should return "col"', function () {
30-
let instance = ReactTestUtils.renderIntoDocument(
31-
<Component bsClass='column'>
32-
content
33-
</Component>
34-
);
35-
assert.deepEqual(instance.getBsClassSet(), {'col': true});
36-
});
37-
38-
it('should return "btn"', function () {
39-
let instance = ReactTestUtils.renderIntoDocument(
40-
<Component bsClass='button'>
41-
content
42-
</Component>
43-
);
44-
assert.deepEqual(instance.getBsClassSet(), {'btn': true});
45-
});
46-
47-
it('should return "btn-group"', function () {
48-
let instance = ReactTestUtils.renderIntoDocument(
49-
<Component bsClass='button-group'>
50-
content
51-
</Component>
52-
);
53-
assert.deepEqual(instance.getBsClassSet(), {'btn-group': true});
54-
});
55-
56-
it('should return "label"', function () {
57-
let instance = ReactTestUtils.renderIntoDocument(
58-
<Component bsClass='label'>
59-
content
60-
</Component>
61-
);
62-
assert.deepEqual(instance.getBsClassSet(), {'label': true});
63-
});
64-
65-
it('should return "alert"', function () {
66-
let instance = ReactTestUtils.renderIntoDocument(
67-
<Component bsClass='alert'>
68-
content
69-
</Component>
70-
);
71-
assert.deepEqual(instance.getBsClassSet(), {'alert': true});
72-
});
73-
74-
it('should return "input-group"', function () {
75-
let instance = ReactTestUtils.renderIntoDocument(
76-
<Component bsClass='input-group'>
77-
content
78-
</Component>
79-
);
80-
assert.deepEqual(instance.getBsClassSet(), {'input-group': true});
81-
});
82-
83-
it('should return "form"', function () {
84-
let instance = ReactTestUtils.renderIntoDocument(
85-
<Component bsClass='form'>
86-
content
87-
</Component>
88-
);
89-
assert.deepEqual(instance.getBsClassSet(), {'form': true});
90-
});
91-
92-
it('should return "panel"', function () {
93-
let instance = ReactTestUtils.renderIntoDocument(
94-
<Component bsClass='panel'>
95-
content
96-
</Component>
97-
);
98-
assert.deepEqual(instance.getBsClassSet(), {'panel': true});
99-
});
100-
101-
it('should return "btn btn-default"', function () {
102-
let instance = ReactTestUtils.renderIntoDocument(
103-
<Component bsClass='button' bsStyle='default'>
104-
content
105-
</Component>
106-
);
107-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-default': true});
108-
});
109-
110-
it('should return "btn btn-primary"', function () {
111-
let instance = ReactTestUtils.renderIntoDocument(
112-
<Component bsClass='button' bsStyle='primary'>
113-
content
114-
</Component>
115-
);
116-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-primary': true});
117-
});
118-
119-
it('should return "btn btn-success"', function () {
120-
let instance = ReactTestUtils.renderIntoDocument(
121-
<Component bsClass='button' bsStyle='success'>
122-
content
123-
</Component>
124-
);
125-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-success': true});
126-
});
127-
128-
it('should return "btn btn-info"', function () {
129-
let instance = ReactTestUtils.renderIntoDocument(
130-
<Component bsClass='button' bsStyle='info'>
131-
content
132-
</Component>
133-
);
134-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-info': true});
135-
});
136-
137-
it('should return "btn btn-link"', function () {
138-
let instance = ReactTestUtils.renderIntoDocument(
139-
<Component bsClass='button' bsStyle='link'>
140-
content
141-
</Component>
142-
);
143-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-link': true});
144-
});
145-
146-
it('should return "btn btn-inline"', function () {
147-
let instance = ReactTestUtils.renderIntoDocument(
148-
<Component bsClass='button' bsStyle='inline'>
149-
content
150-
</Component>
151-
);
152-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-inline': true});
153-
});
154-
155-
it('should return "btn btn-lg"', function () {
156-
let instance = ReactTestUtils.renderIntoDocument(
157-
<Component bsClass='button' bsSize='large'>
158-
content
159-
</Component>
160-
);
161-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-lg': true});
162-
});
163-
164-
it('should return "btn btn-md"', function () {
165-
let instance = ReactTestUtils.renderIntoDocument(
166-
<Component bsClass='button' bsSize='medium'>
167-
content
168-
</Component>
169-
);
170-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-md': true});
171-
});
172-
173-
it('should return "btn btn-sm"', function () {
174-
let instance = ReactTestUtils.renderIntoDocument(
175-
<Component bsClass='button' bsSize='small'>
176-
content
177-
</Component>
178-
);
179-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-sm': true});
180-
});
30+
it('maps and validates OK default classes', function () {
31+
function instanceClassSet(bsClass) {
32+
let instance = ReactTestUtils.renderIntoDocument(
33+
<Component bsClass={bsClass}>
34+
content
35+
</Component>
36+
);
37+
return instance.getBsClassSet();
38+
}
18139

182-
it('should return "btn btn-xs"', function () {
183-
let instance = ReactTestUtils.renderIntoDocument(
184-
<Component bsClass='button' bsSize='xsmall'>
185-
content
186-
</Component>
187-
);
188-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-xs': true});
40+
assert.deepEqual(instanceClassSet('column'), {'col': true});
41+
assert.deepEqual(instanceClassSet('button'), {'btn': true});
42+
assert.deepEqual(instanceClassSet('button-group'), {'btn-group': true});
43+
assert.deepEqual(instanceClassSet('label'), {'label': true});
44+
assert.deepEqual(instanceClassSet('alert'), {'alert': true});
45+
assert.deepEqual(instanceClassSet('input-group'), {'input-group': true});
46+
assert.deepEqual(instanceClassSet('form'), {'form': true});
47+
assert.deepEqual(instanceClassSet('panel'), {'panel': true});
48+
});
49+
50+
describe('Predefined Bootstrap styles', function () {
51+
it('maps and validates OK default styles', function () {
52+
function instanceClassSet(style) {
53+
let instance = ReactTestUtils.renderIntoDocument(
54+
<Component bsClass='button' bsStyle={style}>
55+
content
56+
</Component>
57+
);
58+
return instance.getBsClassSet();
59+
}
60+
61+
assert.deepEqual(instanceClassSet('default'), {'btn': true, 'btn-default': true});
62+
assert.deepEqual(instanceClassSet('primary'), {'btn': true, 'btn-primary': true});
63+
assert.deepEqual(instanceClassSet('success'), {'btn': true, 'btn-success': true});
64+
assert.deepEqual(instanceClassSet('info'), {'btn': true, 'btn-info': true});
65+
assert.deepEqual(instanceClassSet('link'), {'btn': true, 'btn-link': true});
66+
assert.deepEqual(instanceClassSet('inline'), {'btn': true, 'btn-inline': true});
67+
});
68+
});
69+
70+
describe('Sizes', function () {
71+
it('maps english words for sizes to bootstrap sizes constants', function () {
72+
function instanceClassSet(size) {
73+
let instance = ReactTestUtils.renderIntoDocument(
74+
<Component bsClass='button' bsSize={size}>
75+
content
76+
</Component>
77+
);
78+
return instance.getBsClassSet();
79+
}
80+
81+
assert.deepEqual(instanceClassSet('large'), {'btn': true, 'btn-lg': true});
82+
assert.deepEqual(instanceClassSet('small'), {'btn': true, 'btn-sm': true});
83+
assert.deepEqual(instanceClassSet('medium'), {'btn': true, 'btn-md': true});
84+
assert.deepEqual(instanceClassSet('xsmall'), {'btn': true, 'btn-xs': true});
85+
});
86+
});
87+
88+
describe('Custom styles', function () {
89+
it('should validate OK custom styles added via "addStyle()"', function () {
90+
91+
styleMaps.addStyle('wacky');
92+
93+
let instance = ReactTestUtils.renderIntoDocument(
94+
<Component bsClass='button' bsStyle='wacky'>
95+
content
96+
</Component>
97+
);
98+
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-wacky': true});
99+
});
100+
101+
it('should allow custom styles as is but with validation warning', function () {
102+
let instance = ReactTestUtils.renderIntoDocument(
103+
<Component bsClass='button' bsStyle='my-custom-class'>
104+
content
105+
</Component>
106+
);
107+
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'my-custom-class': true});
108+
shouldWarn('Invalid prop `bsStyle` of value `my-custom-class`');
109+
});
189110
});
111+
});
190112

191-
it('should return "btn-title"', function () {
113+
// todo: fix bad naming
114+
describe('#prefixClass', function () {
115+
it('allows custom sub-classes', function () {
192116
let instance = ReactTestUtils.renderIntoDocument(
193117
<Component bsClass='button'>
194118
content
195119
</Component>
196120
);
197121
assert.equal(instance.prefixClass('title'), 'btn-title');
198122
});
199-
200-
it('should return "btn btn-wacky"', function () {
201-
styleMaps.addStyle('wacky');
202-
let instance = ReactTestUtils.renderIntoDocument(
203-
<Component bsClass='button' bsStyle='wacky'>
204-
content
205-
</Component>
206-
);
207-
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-wacky': true});
208-
});
209123
});
210124
});

0 commit comments

Comments
 (0)