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 | 83 | |
84 | 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 | +}; | ... | ... |