Commit 5da043ee8d44c536e102a4655bfaea893a39665c
Committed by
GitHub

Merge pull request #1696 from SergioCrisostomo/add-select-specs
Add simple unit tests for Select component
Showing
2 changed files
with
206 additions
and
0 deletions
Show diff stats
1 | +import {createVue, destroyVM, waitForIt} from '../util'; | ||
2 | + | ||
3 | +describe('Select.vue', () => { | ||
4 | + let vm; | ||
5 | + afterEach(() => { | ||
6 | + destroyVM(vm); | ||
7 | + }); | ||
8 | + | ||
9 | + describe('Props tests', () => { | ||
10 | + it('should create a Select component with passed placeholder', done => { | ||
11 | + const placeholder = 'Hi! Select something!'; | ||
12 | + vm = createVue({ | ||
13 | + template: ` | ||
14 | + <Select placeholder="${placeholder}"> | ||
15 | + <Option v-for="item in options" :value="item.value" :key="item.value">{{ item.label }}</Option> | ||
16 | + </Select> | ||
17 | + `, | ||
18 | + data() { | ||
19 | + return { | ||
20 | + value: '', | ||
21 | + options: [{value: 1, label: 'Foo'}, {value: 2, label: 'Bar'}] | ||
22 | + }; | ||
23 | + } | ||
24 | + }); | ||
25 | + vm.$nextTick(() => { | ||
26 | + const placeholderSpan = vm.$el.querySelector('.ivu-select-placeholder'); | ||
27 | + expect(placeholderSpan.textContent).to.equal(placeholder); | ||
28 | + expect(placeholderSpan.style.display).to.not.equal('none'); | ||
29 | + | ||
30 | + expect(vm.$children[0].showPlaceholder).to.equal(true); | ||
31 | + done(); | ||
32 | + }); | ||
33 | + }); | ||
34 | + | ||
35 | + it('should create a Select component and take a pre-selected value', done => { | ||
36 | + vm = createVue({ | ||
37 | + template: ` | ||
38 | + <Select :value="2"> | ||
39 | + <Option v-for="item in options" :value="item.value" :key="item.value">{{ item.label }}</Option> | ||
40 | + </Select> | ||
41 | + `, | ||
42 | + data() { | ||
43 | + return { | ||
44 | + value: '', | ||
45 | + options: [{value: 1, label: 'Foo'}, {value: 2, label: 'Bar'}] | ||
46 | + }; | ||
47 | + } | ||
48 | + }); | ||
49 | + vm.$nextTick(() => { | ||
50 | + const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value'); | ||
51 | + expect(selectedValueSpan.textContent).to.equal('Bar'); | ||
52 | + expect(selectedValueSpan.style.display).to.not.equal('none'); | ||
53 | + expect(vm.$children[0].selectedSingle).to.equal('Bar'); | ||
54 | + expect(vm.$children[0].model).to.equal(2); | ||
55 | + done(); | ||
56 | + }); | ||
57 | + }); | ||
58 | + | ||
59 | + xit('should accept normal characters', done => { | ||
60 | + vm = createVue({ | ||
61 | + template: ` | ||
62 | + <Select :value="2"> | ||
63 | + <Option v-for="item in options" :value="item.value" :key="item.value">{{ item.label }}</Option> | ||
64 | + </Select> | ||
65 | + `, | ||
66 | + data() { | ||
67 | + return { | ||
68 | + value: '', | ||
69 | + options: [{value: 1, label: '> 100$'}, {value: 2, label: '< 100$'}] | ||
70 | + }; | ||
71 | + } | ||
72 | + }); | ||
73 | + vm.$nextTick(() => { | ||
74 | + const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value'); | ||
75 | + expect(selectedValueSpan.textContent).to.equal('< 100$'); | ||
76 | + done(); | ||
77 | + }); | ||
78 | + }); | ||
79 | + | ||
80 | + it('should use the value\'s label instead of placeholder when both are set', done => { | ||
81 | + vm = createVue({ | ||
82 | + template: ` | ||
83 | + <Select placeholder="Choose anything!" :value="2"> | ||
84 | + <Option v-for="item in options" :value="item.value" :key="item.value">{{ item.label }}</Option> | ||
85 | + </Select> | ||
86 | + `, | ||
87 | + data() { | ||
88 | + return { | ||
89 | + value: '', | ||
90 | + options: [{value: 1, label: 'Foo'}, {value: 2, label: 'Bar'}] | ||
91 | + }; | ||
92 | + } | ||
93 | + }); | ||
94 | + vm.$nextTick(() => { | ||
95 | + const placeholderSpan = vm.$el.querySelector('.ivu-select-placeholder'); | ||
96 | + const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value'); | ||
97 | + expect(placeholderSpan.style.display).to.equal('none'); | ||
98 | + expect(selectedValueSpan.style.display).to.not.equal('none'); | ||
99 | + done(); | ||
100 | + }); | ||
101 | + }); | ||
102 | + | ||
103 | + it('should set different classes for different sizes', done => { | ||
104 | + vm = createVue(` | ||
105 | + <div> | ||
106 | + <Select placeholder="Choose anything!"><Option v-for="item in []" :value="item" :key="item">{{item}}</Option></Select> | ||
107 | + <Select placeholder="Choose anything!" size="large"><Option v-for="item in []" :value="item" :key="item">{{item}}</Option></Select> | ||
108 | + <Select placeholder="Choose anything!" size="small"><Option v-for="item in []" :value="item" :key="item">{{item}}</Option></Select> | ||
109 | + </div> | ||
110 | + `); | ||
111 | + vm.$nextTick(() => { | ||
112 | + const [defaultSelect, largeSelect, smallSelect] = [...vm.$el.querySelectorAll('.ivu-select')]; | ||
113 | + expect(defaultSelect.className).to.equal('ivu-select ivu-select-single'); | ||
114 | + expect(largeSelect.classList.contains('ivu-select-large')).to.equal(true); | ||
115 | + expect(smallSelect.classList.contains('ivu-select-small')).to.equal(true); | ||
116 | + done(); | ||
117 | + }); | ||
118 | + }); | ||
119 | + | ||
120 | + it('should set new options', done => { | ||
121 | + const laterOptions = [{value: 1, label: 'Foo'}, {value: 2, label: 'Bar'}]; | ||
122 | + | ||
123 | + vm = createVue({ | ||
124 | + template: ` | ||
125 | + <Select> | ||
126 | + <Option v-for="item in options" :value="item.value" :key="item.value">{{ item.label }}</Option> | ||
127 | + </Select> | ||
128 | + `, | ||
129 | + data() { | ||
130 | + return { | ||
131 | + value: '', | ||
132 | + options: [] | ||
133 | + }; | ||
134 | + }, | ||
135 | + mounted() { | ||
136 | + this.$nextTick(() => (this.options = laterOptions)); | ||
137 | + } | ||
138 | + }); | ||
139 | + const condition = function() { | ||
140 | + return vm.$children[0].options.length > 0; | ||
141 | + }; | ||
142 | + const callback = function() { | ||
143 | + if (vm.$children[0].options == 0) return setTimeout(waitForIt.bind(null, done), 50); | ||
144 | + expect(JSON.stringify(vm.$children[0].options)).to.equal(JSON.stringify(laterOptions)); | ||
145 | + | ||
146 | + const renderedOptions = vm.$el.querySelectorAll('.ivu-select-dropdown-list li'); | ||
147 | + expect(renderedOptions.length).to.equal(laterOptions.length); | ||
148 | + | ||
149 | + const labels = [...renderedOptions].map(el => el.textContent).join('<>'); | ||
150 | + const expected = laterOptions.map(o => o.label).join('<>'); | ||
151 | + expect(labels).to.equal(expected); | ||
152 | + done(); | ||
153 | + }; | ||
154 | + waitForIt(condition, callback); | ||
155 | + }); | ||
156 | + }); | ||
157 | + | ||
158 | + describe('Performance tests', () => { | ||
159 | + xit('should handle big numbers of options', done => { | ||
160 | + const manyLaterOptions = Array.apply(null, Array(200)).map((_, i) => { | ||
161 | + return { | ||
162 | + value: i + 1, | ||
163 | + label: Math.random().toString(36).slice(2).toUpperCase() | ||
164 | + }; | ||
165 | + }); | ||
166 | + const start = +new Date(); | ||
167 | + vm = createVue({ | ||
168 | + template: ` | ||
169 | + <Select> | ||
170 | + <Option v-for="item in options" :value="item.value" :key="item.value">{{ item.label }}</Option> | ||
171 | + </Select> | ||
172 | + `, | ||
173 | + data() { | ||
174 | + return { | ||
175 | + value: '', | ||
176 | + options: [] | ||
177 | + }; | ||
178 | + }, | ||
179 | + mounted() { | ||
180 | + this.$nextTick(() => (this.options = manyLaterOptions)); | ||
181 | + } | ||
182 | + }); | ||
183 | + const condition = function() { | ||
184 | + return vm.$children[0].options.length == manyLaterOptions.length; | ||
185 | + }; | ||
186 | + const callback = function() { | ||
187 | + const end = +new Date(); | ||
188 | + const renderedOptions = vm.$el.querySelectorAll('.ivu-select-dropdown-list li'); | ||
189 | + expect(renderedOptions.length).to.equal(manyLaterOptions.length); | ||
190 | + expect(end - start).to.be.not.above(1000); | ||
191 | + done(); | ||
192 | + }; | ||
193 | + waitForIt(condition, callback); | ||
194 | + }); | ||
195 | + }); | ||
196 | +}); |
test/unit/util.js
@@ -83,3 +83,13 @@ exports.triggerEvent = function(elm, name, ...opts) { | @@ -83,3 +83,13 @@ exports.triggerEvent = function(elm, name, ...opts) { | ||
83 | 83 | ||
84 | return elm; | 84 | return elm; |
85 | }; | 85 | }; |
86 | + | ||
87 | +/** | ||
88 | +* Wait for components inner async process, when this.$nextTick is not enough | ||
89 | +* @param {Function} the condition to verify before calling the callback | ||
90 | +* @param {Function} the callback to call when condition is true | ||
91 | +*/ | ||
92 | +exports.waitForIt = function waitForIt(condition, callback) { | ||
93 | + if (condition()) callback(); | ||
94 | + else setTimeout(() => waitForIt(condition, callback), 50); | ||
95 | +}; |