import Vue from 'vue' import { looseEqual } from 'shared/util' // Android 4.4 Chrome 30 has the bug that a multi-select option cannot be // deseleted by setting its "selected" prop via JavaScript. function hasMultiSelectBug () { var s = document.createElement('select') s.setAttribute('multiple', '') var o = document.createElement('option') s.appendChild(o) o.selected = true o.selected = false return o.selected !== false } /** * setting ' + '' + '' + '' + '' }).$mount() document.body.appendChild(vm.$el) expect(vm.test).toBe('b') expect(vm.$el.value).toBe('b') expect(vm.$el.childNodes[1].selected).toBe(true) vm.test = 'c' waitForUpdate(function () { expect(vm.$el.value).toBe('c') expect(vm.$el.childNodes[2].selected).toBe(true) updateSelect(vm.$el, 'a') triggerEvent(vm.$el, 'change') expect(vm.test).toBe('a') }).then(done) }) it('should work with value bindings', done => { const vm = new Vue({ data: { test: 2 }, template: '' }).$mount() document.body.appendChild(vm.$el) expect(vm.$el.value).toBe('2') expect(vm.$el.childNodes[1].selected).toBe(true) vm.test = 3 waitForUpdate(function () { expect(vm.$el.value).toBe('3') expect(vm.$el.childNodes[2].selected).toBe(true) updateSelect(vm.$el, '1') triggerEvent(vm.$el, 'change') expect(vm.test).toBe('1') }).then(done) }) it('should work with value bindings (object loose equal)', done => { const vm = new Vue({ data: { test: { a: 2 } }, template: '' }).$mount() document.body.appendChild(vm.$el) expect(vm.$el.childNodes[1].selected).toBe(true) vm.test = { a: 3 } waitForUpdate(function () { expect(vm.$el.childNodes[2].selected).toBe(true) updateSelect(vm.$el, '1') triggerEvent(vm.$el, 'change') expect(vm.test).toBe('1') updateSelect(vm.$el, { a: 2 }) triggerEvent(vm.$el, 'change') expect(vm.test).toEqual({ a: 2 }) }).then(done) }) it('should work with v-for', done => { const vm = new Vue({ data: { test: 'b', opts: ['a', 'b', 'c'] }, template: '' }).$mount() document.body.appendChild(vm.$el) expect(vm.test).toBe('b') expect(vm.$el.value).toBe('b') expect(vm.$el.childNodes[1].selected).toBe(true) vm.test = 'c' waitForUpdate(function () { expect(vm.$el.value).toBe('c') expect(vm.$el.childNodes[2].selected).toBe(true) updateSelect(vm.$el, 'a') triggerEvent(vm.$el, 'change') expect(vm.test).toBe('a') // update v-for opts vm.opts = ['d', 'a'] }).then(() => { expect(vm.$el.childNodes[0].selected).toBe(false) expect(vm.$el.childNodes[1].selected).toBe(true) }).then(done) }) it('should work with v-for & value bindings', done => { const vm = new Vue({ data: { test: 2, opts: [1, 2, 3] }, template: '' }).$mount() document.body.appendChild(vm.$el) expect(vm.$el.value).toBe('2') expect(vm.$el.childNodes[1].selected).toBe(true) vm.test = 3 waitForUpdate(function () { expect(vm.$el.value).toBe('3') expect(vm.$el.childNodes[2].selected).toBe(true) updateSelect(vm.$el, 1) triggerEvent(vm.$el, 'change') expect(vm.test).toBe(1) // update v-for opts vm.opts = [0, 1] }).then(() => { expect(vm.$el.childNodes[0].selected).toBe(false) expect(vm.$el.childNodes[1].selected).toBe(true) }).then(done) }) it('should work with select which has no default selected options', (done) => { const spy = jasmine.createSpy() const vm = new Vue({ data: { id: 4, list: [1, 2, 3], testChange: 5 }, template: '
' + '' + '{{testChange}}' + '
', methods: { test: spy } }).$mount() document.body.appendChild(vm.$el) vm.testChange = 10 waitForUpdate(() => { expect(spy.calls.count()).toBe(0) }).then(done) }) if (!hasMultiSelectBug()) { it('multiple', done => { const vm = new Vue({ data: { test: ['b'] }, template: '' }).$mount() var opts = vm.$el.options expect(opts[0].selected).toBe(false) expect(opts[1].selected).toBe(true) expect(opts[2].selected).toBe(false) vm.test = ['a', 'c'] waitForUpdate(() => { expect(opts[0].selected).toBe(true) expect(opts[1].selected).toBe(false) expect(opts[2].selected).toBe(true) opts[0].selected = false opts[1].selected = true triggerEvent(vm.$el, 'change') expect(vm.test).toEqual(['b', 'c']) }).then(done) }) it('multiple + v-for', done => { const vm = new Vue({ data: { test: ['b'], opts: ['a', 'b', 'c'] }, template: '' }).$mount() var opts = vm.$el.options expect(opts[0].selected).toBe(false) expect(opts[1].selected).toBe(true) expect(opts[2].selected).toBe(false) vm.test = ['a', 'c'] waitForUpdate(() => { expect(opts[0].selected).toBe(true) expect(opts[1].selected).toBe(false) expect(opts[2].selected).toBe(true) opts[0].selected = false opts[1].selected = true triggerEvent(vm.$el, 'change') expect(vm.test).toEqual(['b', 'c']) // update v-for opts vm.opts = ['c', 'd'] }).then(() => { expect(opts[0].selected).toBe(true) expect(opts[1].selected).toBe(false) expect(vm.test).toEqual(['c']) // should remove 'd' which no longer has a matching option }).then(done) }) } it('should work with multiple binding', (done) => { const spy = jasmine.createSpy() const vm = new Vue({ data: { isMultiple: true, selections: ['1'] }, template: '', watch: { selections: spy } }).$mount() document.body.appendChild(vm.$el) vm.$el.options[1].selected = true triggerEvent(vm.$el, 'change') waitForUpdate(() => { expect(spy).toHaveBeenCalled() expect(vm.selections).toEqual(['1', '2']) }).then(done) }) it('should not have multiple attr with falsy values except \'\'', () => { const vm = new Vue({ template: '
' + '' + '' + '' + '' + '
' }).$mount() expect(vm.$el.querySelector('#undefined').multiple).toEqual(false) expect(vm.$el.querySelector('#null').multiple).toEqual(false) expect(vm.$el.querySelector('#false').multiple).toEqual(false) expect(vm.$el.querySelector('#string').multiple).toEqual(true) }) it('multiple with static template', () => { const vm = new Vue({ template: '' }).$mount() var opts = vm.$el.options expect(opts[0].selected).toBe(true) expect(opts[1].selected).toBe(true) expect(opts[2].selected).toBe(true) }) it('multiple selects', (done) => { const spy = jasmine.createSpy() const vm = new Vue({ data: { selections: ['', ''], selectBoxes: [ [ { value: 'foo', text: 'foo' }, { value: 'bar', text: 'bar' } ], [ { value: 'day', text: 'day' }, { value: 'night', text: 'night' } ] ] }, watch: { selections: spy }, template: '
' + '' + '{{selections}}' + '
' }).$mount() document.body.appendChild(vm.$el) var selects = vm.$el.getElementsByTagName('select') var select0 = selects[0] select0.options[0].selected = true triggerEvent(select0, 'change') waitForUpdate(() => { expect(spy).toHaveBeenCalled() expect(vm.selections).toEqual(['foo', '']) }).then(done) }) it('.number modifier', () => { const vm = new Vue({ data: { test: 2 }, template: '' }).$mount() document.body.appendChild(vm.$el) updateSelect(vm.$el, '1') triggerEvent(vm.$el, 'change') expect(vm.test).toBe(1) }) it('should respect different pritive type value', (done) => { const vm = new Vue({ data: { test: 0 }, template: '' }).$mount() var opts = vm.$el.options expect(opts[0].selected).toBe(false) expect(opts[1].selected).toBe(true) expect(opts[2].selected).toBe(false) expect(opts[3].selected).toBe(false) expect(opts[4].selected).toBe(false) vm.test = 1 waitForUpdate(() => { expect(opts[0].selected).toBe(false) expect(opts[1].selected).toBe(false) expect(opts[2].selected).toBe(true) expect(opts[3].selected).toBe(false) expect(opts[4].selected).toBe(false) vm.test = '' }).then(() => { expect(opts[0].selected).toBe(true) expect(opts[1].selected).toBe(false) expect(opts[2].selected).toBe(false) expect(opts[3].selected).toBe(false) expect(opts[4].selected).toBe(false) vm.test = false }).then(() => { expect(opts[0].selected).toBe(false) expect(opts[1].selected).toBe(false) expect(opts[2].selected).toBe(false) expect(opts[3].selected).toBe(true) expect(opts[4].selected).toBe(false) vm.test = true }).then(() => { expect(opts[0].selected).toBe(false) expect(opts[1].selected).toBe(false) expect(opts[2].selected).toBe(false) expect(opts[3].selected).toBe(false) expect(opts[4].selected).toBe(true) }).then(done) }) it('should warn inline selected', () => { const vm = new Vue({ data: { test: null }, template: '' }).$mount() expect(vm.$el.selectedIndex).toBe(-1) expect('inline selected attributes on