Skip to content

Commit d5fb544

Browse files
author
jfusco
committed
Adding finishing touches on unit tests for V1 - adding maxTags options - changing name of allowDupes to uniqueTags - changing name of events to be prefixed with 'on' - adding test task to the build process - refacotring SCSS into multip[le files based on core and components - now destructuring properties in methods in tags component - changing name of delimiters to addKeys.
1 parent 27b9a95 commit d5fb544

File tree

21 files changed

+488
-336
lines changed

21 files changed

+488
-336
lines changed

.eslintrc

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"brace-style": [2, "1tbs", {
5151
"allowSingleLine": true
5252
}],
53-
"object-curly-spacing": [2, "never", {
53+
"object-curly-spacing": [2, "always", {
5454
"objectsInObjects": true,
5555
"arraysInObjects": true
5656
}],
@@ -78,10 +78,6 @@
7878
}]
7979
},
8080
"globals": {
81-
"console": true,
82-
"alert": true,
83-
"document": true,
84-
"window": true,
85-
"WeakMap": true
81+
"console": true
8682
}
8783
}

README.md

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class Application extends Component{
4444
<Tags
4545
initialTags={this.state.tags}
4646
placeholder="Add a tag"
47-
change={this.onTagsChange} />
47+
onChange={this.onTagsChange} />
4848
</div>
4949
);
5050
}
@@ -57,14 +57,14 @@ render(<Application />, document.getElementById('application'));
5757
#### Options
5858
* **[`initialTags`](#initialTags)**
5959
* **[`placeholder`](#placeholder)**
60-
* **[`delimiters`](#delimiters)**
61-
* **[`change`](#change)**
62-
* **[`added`](#added)**
63-
* **[`removed`](#removed)**
60+
* **[`addKeys`](#addKeys)**
61+
* **[`onChange`](#onChange)**
62+
* **[`onAdded`](#onAdded)**
63+
* **[`onRemoved`](#onRemoved)**
64+
* **[`maxTags`](#maxTags)**
6465
* **[`readOnly`](#readOnly)**
65-
* **[`removeTagWithDeleteKey`](#removeTagWithDeleteKey)**
6666
* **[`removeTagIcon`](#removeTagIcon)**
67-
* **[`allowDupes`](#allowDupes)**
67+
* **[`uniqueTags`](#allowDupes)**
6868
* **[`id`](#id)**
6969

7070
<a name="initialTags"></a>
@@ -83,46 +83,53 @@ A `string` used as placeholder text in the tags input field
8383
<Tags placeholder="Add a tag" />
8484
```
8585

86-
<a name="delimiters"></a>
87-
##### delimiters ~ optional ~ default `[13, 9, 32]`
86+
<a name="addKeys"></a>
87+
##### addKeys ~ optional ~ default `[13, 9, 32]`
8888
An `array` of keyCodes used to tell the tags component which delimiter to use to add a tag
8989

9090
[Here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode) is more info and a list of keyCodes
9191
```js
92-
<Tags delimiters={[13, 9, 32, 188]} />
92+
<Tags addKeys={[13, 9, 32, 188]} />
9393
```
9494

95-
<a name="change"></a>
96-
##### change ~ optional
95+
<a name="onChange"></a>
96+
##### onChange ~ optional
9797
A `function` fired anytime there is a change - returns the new `array` of tags
9898
```js
9999
onTagsChange(tags){
100100
console.log(`new tags: ${tags}`);
101101
}
102102

103-
<Tags change={this.onTagsChange} />
103+
<Tags onChange={this.onTagsChange} />
104104
```
105105

106-
<a name="added"></a>
107-
##### added ~ optional
106+
<a name="onAdded"></a>
107+
##### onAdded ~ optional
108108
A `function` fired when a new tag is added - returns a `string` of the new tag
109109
```js
110110
onTagAdded(tag){
111111
console.log(`new tag: ${tags}`);
112112
}
113113

114-
<Tags added={this.onTagAdded} />
114+
<Tags onAdded={this.onTagAdded} />
115115
```
116116

117-
<a name="removed"></a>
118-
##### removed ~ optional
117+
<a name="onRemoved"></a>
118+
##### onRemoved ~ optional
119119
A `function` fired when a new tag is deleted - returns a `string` of the tag that was deleted
120120
```js
121121
onTagRemoved(tag){
122122
console.log(`deleted tag: ${tag}`);
123123
}
124124

125-
<Tags removed={this.onTagRemoved} />
125+
<Tags onRemoved={this.onTagRemoved} />
126+
```
127+
128+
<a name="maxTags"></a>
129+
##### maxTags ~ optional ~ default `-1` (infinite)
130+
An `integer` representing the maximum number of tags that are allowed to be added
131+
```js
132+
<Tags maxTags={10} />
126133
```
127134

128135
<a name="readOnly"></a>
@@ -132,13 +139,6 @@ A `boolean` that sets the tag component to read only mode. No adding or removing
132139
<Tags readOnly={true} />
133140
```
134141

135-
<a name="removeTagWithDeleteKey"></a>
136-
##### removeTagWithDeleteKey ~ optional ~ default `true`
137-
A `boolean` that allows tags to be removed with the delete key when the input field is empty
138-
```js
139-
<Tags removeTagWithDeleteKey={true} />
140-
```
141-
142142
<a name="removeTagIcon"></a>
143143
##### removeTagIcon ~ optional ~ default `"x"`
144144
The `element` to be used for the delete icon
@@ -152,11 +152,12 @@ const removeIcon = () => {
152152
<Tags removeTagsIcon={removeIcon()} />
153153
```
154154

155-
<a name="allowDupes"></a>
156-
##### allowDupes ~ optional ~ default `false`
157-
A `boolean` that allows tags to be added more than once
155+
<a name="uniqueTags"></a>
156+
##### uniqueTags ~ optional ~ default `false`
157+
A `boolean` that allows the same tag to be added more than once
158158
```js
159-
<Tags allowDupes={false} />
159+
//-- Only allow unique tags to be added
160+
<Tags uniqueTags={true} />
160161
```
161162

162163
<a name="id"></a>

__tests__/Tag-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,15 @@ describe('Tag - "removeTagIcon"', () => {
137137
});
138138
});
139139

140-
describe('Tag - "removeTag"', () => {
140+
describe('Tag - "onRemoveTag"', () => {
141141
it('should be called when clicking the remove icon', () => {
142142
const onRemoveClick = jest.genMockFunction();
143143

144144
const tag = renderIntoDocument(
145145
<div>
146146
<Tag
147147
name={TAG_NAME}
148-
removeTag={onRemoveClick} />
148+
onRemoveTag={onRemoveClick} />
149149
</div>
150150
);
151151

__tests__/Tags-test.js

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,18 @@ describe('Tags', () => {
4040
});
4141

4242
it('should render custom placeholder if provided', () => {
43-
expect(tags.props.children[1].type).toBe('input');
44-
expect(tags.props.children[1].props.placeholder).toBe('Custom placeholder text');
43+
const input = tags.props.children[1];
44+
45+
expect(input.type).toBe('input');
46+
expect(input.props.placeholder).toBe('Custom placeholder text');
4547
});
46-
});
4748

49+
it('should set aria-label', () => {
50+
const input = tags.props.children[1];
51+
52+
expect(input.props['aria-label']).toBe('Custom placeholder text');
53+
});
54+
});
4855

4956
describe('Tags - "initialTags"', () => {
5057
it('should render tags (shallow render)', () => {
@@ -109,7 +116,7 @@ describe('Tags - "readOnly"', () => {
109116
});
110117

111118

112-
describe('Tags - "delimiters"', () => {
119+
describe('Tags - "addKeys"', () => {
113120
let tags,
114121
input,
115122
tagContainer;
@@ -118,7 +125,7 @@ describe('Tags - "delimiters"', () => {
118125
tags = renderIntoDocument(
119126
<Tags
120127
initialTags={TEST_TAGS}
121-
delimiters={[13, 9, 32, 188]} />
128+
addKeys={[13, 9, 32, 188]} />
122129
);
123130

124131
const renderedDOM = findDOMNode(tags);
@@ -177,14 +184,16 @@ describe('Tags - events', () => {
177184
const onTagAdded = jest.genMockFunction();
178185
const onTagRemoved = jest.genMockFunction();
179186
const onTagsChanged = jest.genMockFunction();
187+
const onTagsInputChange = jest.genMockFunction();
180188

181189
beforeEach(() => {
182190
tags = renderIntoDocument(
183191
<Tags
184192
initialTags={TEST_TAGS}
185-
added={onTagAdded}
186-
removed={onTagRemoved}
187-
change={onTagsChanged} />
193+
onAdded={onTagAdded}
194+
onRemoved={onTagRemoved}
195+
onChange={onTagsChanged}
196+
onInputChange={onTagsInputChange} />
188197
);
189198

190199
const renderedDOM = findDOMNode(tags);
@@ -206,11 +215,11 @@ describe('Tags - events', () => {
206215
Simulate.keyDown(input, {key: 'Enter', keyCode: 13, which: 13});
207216
});
208217

209-
it('should call the "added" event and return the new tag', () => {
218+
it('should call the "onAdded" event and return the new tag', () => {
210219
expect(onTagAdded).toBeCalledWith(TEST_TAGS[0]);
211220
});
212221

213-
it('should call the "changed" event and return the new tags list as an array', () => {
222+
it('should call the "onChange" event and return the new tags list as an array', () => {
214223
const newArray = TEST_TAGS.concat('foo');
215224

216225
expect(onTagsChanged).toBeCalledWith(newArray);
@@ -225,14 +234,26 @@ describe('Tags - events', () => {
225234
Simulate.keyDown(input, {key: 'Delete', keyCode: 8, which: 8});
226235
});
227236

228-
it('should call the "removed" event and return the tag that was removed', () => {
237+
it('should call the "onRemoved" event and return the tag that was removed', () => {
229238
expect(onTagRemoved).toBeCalledWith(TEST_TAGS[1]);
230239
});
231240

232-
it('should call the "changed" event and return the new tags list as an array', () => {
241+
it('should call the "onChange" event and return the new tags list as an array', () => {
233242
expect(onTagsChanged).toBeCalledWith([TEST_TAGS[0]]);
234243
});
235244
});
245+
246+
describe('when typing in the input field', () => {
247+
it('should call the "inputChange" and return the word as you\'re typing', () => {
248+
Simulate.change(input, {
249+
target: {
250+
value: 'a'
251+
}
252+
});
253+
254+
expect(onTagsInputChange).toBeCalledWith('a');
255+
});
256+
});
236257
});
237258

238259
describe('Tags - removing', () => {
@@ -293,11 +314,12 @@ describe('Tags - removing', () => {
293314
});
294315
});
295316

296-
describe('Tags - "allowDupes"', () => {
317+
describe('Tags - "uniqueTags"', () => {
297318
it('should allow duplicate tags to be created', () => {
298319
const tags = renderIntoDocument(
299320
<Tags
300-
initialTags={TEST_TAGS} />
321+
initialTags={TEST_TAGS}
322+
uniqueTags={false} />
301323
);
302324

303325
const renderedDOM = findDOMNode(tags);
@@ -318,7 +340,7 @@ describe('Tags - "allowDupes"', () => {
318340
const tags = renderIntoDocument(
319341
<Tags
320342
initialTags={TEST_TAGS}
321-
allowDupes={false} />
343+
uniqueTags={true} />
322344
);
323345

324346
const renderedDOM = findDOMNode(tags);
@@ -333,3 +355,30 @@ describe('Tags - "allowDupes"', () => {
333355
expect(tagContainer.children.length).toBe(2);
334356
});
335357
});
358+
359+
describe('Tags - "maxTags"', () => {
360+
describe('when maxTags is set to 3', () => {
361+
it('should allow no more than 3 tags to be added', () => {
362+
const tags = renderIntoDocument(
363+
<Tags
364+
initialTags={TEST_TAGS}
365+
maxTags={3} />
366+
);
367+
368+
const renderedDOM = findDOMNode(tags);
369+
const input = renderedDOM.getElementsByTagName('input')[0];
370+
const tagContainer = renderedDOM.querySelector('.tags-container');
371+
372+
input.value = TEST_TAGS[0];
373+
374+
Simulate.change(input);
375+
Simulate.keyDown(input, {key: 'Enter', keyCode: 13, which: 13});
376+
377+
input.value = TEST_TAGS[0];
378+
379+
Simulate.keyDown(input, {key: 'Enter', keyCode: 13, which: 13});
380+
381+
expect(tagContainer.children.length).toBe(3);
382+
});
383+
});
384+
});

dist-components/Tag.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var Tag = function Tag(props) {
1414
var onRemoveClick = function onRemoveClick(e) {
1515
e.preventDefault();
1616

17-
props.removeTag();
17+
props.onRemoveTag(e);
1818
};
1919

2020
var removeIcon = !props.readOnly ? _react2.default.createElement(
@@ -36,7 +36,7 @@ exports.default = Tag;
3636

3737
Tag.propTypes = {
3838
name: _react2.default.PropTypes.string.isRequired,
39-
removeTag: _react2.default.PropTypes.func,
39+
onRemoveTag: _react2.default.PropTypes.func,
4040
selectedTag: _react2.default.PropTypes.bool,
4141
readOnly: _react2.default.PropTypes.bool,
4242
removeTagIcon: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.element])

0 commit comments

Comments
 (0)