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 | +}; |