var _ = require('src/util')
var Vue = require('src')
describe('Component', function () {
var el
beforeEach(function () {
el = document.createElement('div')
document.body.appendChild(el)
spyWarns()
})
afterEach(function () {
document.body.removeChild(el)
})
it('static', function () {
new Vue({
el: el,
template: '',
components: {
test: {
data: function () {
return { a: 123 }
},
template: '{{a}}'
}
}
})
expect(el.innerHTML).toBe('123')
})
it('replace', function () {
new Vue({
el: el,
template: '',
components: {
test: {
replace: true,
data: function () {
return { a: 123 }
},
template: '
{{a}}
'
}
}
})
expect(el.innerHTML).toBe('123
')
})
it('"is" on table elements', function () {
var vm = new Vue({
el: el,
template: '',
components: {
test: {
data: function () {
return { a: 123 }
},
template: '{{a}} | '
}
}
})
expect(el.innerHTML).toBe(vm.$options.template.replace(//, '| 123 |
'))
expect(getWarnCount()).toBe(0)
})
it('inline-template', function () {
new Vue({
el: el,
template: '{{a}}',
data: {
a: 'parent'
},
components: {
test: {
data: function () {
return { a: 'child' }
},
template: 'child option template'
}
}
})
expect(el.innerHTML).toBe('child')
})
it('block replace', function () {
new Vue({
el: el,
template: '',
components: {
test: {
replace: true,
data: function () {
return { a: 123, b: 234 }
},
template: '{{a}}
{{b}}
'
}
}
})
expect(el.innerHTML).toBe('123
234
')
})
it('dynamic', function (done) {
var vm = new Vue({
el: el,
template: '',
data: {
view: 'view-a'
},
components: {
'view-a': {
template: 'AAA
',
replace: true,
data: function () {
return { view: 'a' }
}
},
'view-b': {
template: 'BBB
',
replace: true,
data: function () {
return { view: 'b' }
}
}
}
})
expect(el.innerHTML).toBe('AAA
')
vm.view = 'view-b'
_.nextTick(function () {
expect(el.innerHTML).toBe('BBB
')
vm.view = ''
_.nextTick(function () {
expect(el.innerHTML).toBe('')
done()
})
})
})
it('keep-alive', function (done) {
var spyA = jasmine.createSpy()
var spyB = jasmine.createSpy()
var vm = new Vue({
el: el,
template: '',
data: {
view: 'view-a'
},
components: {
'view-a': {
created: spyA,
template: 'AAA
',
replace: true
},
'view-b': {
created: spyB,
template: 'BBB
',
replace: true
}
}
})
expect(el.innerHTML).toBe('AAA
')
expect(spyA.calls.count()).toBe(1)
expect(spyB.calls.count()).toBe(0)
vm.view = 'view-b'
_.nextTick(function () {
expect(el.innerHTML).toBe('BBB
')
expect(spyA.calls.count()).toBe(1)
expect(spyB.calls.count()).toBe(1)
vm.view = 'view-a'
_.nextTick(function () {
expect(el.innerHTML).toBe('AAA
')
expect(spyA.calls.count()).toBe(1)
expect(spyB.calls.count()).toBe(1)
vm.view = 'view-b'
_.nextTick(function () {
expect(el.innerHTML).toBe('BBB
')
expect(spyA.calls.count()).toBe(1)
expect(spyB.calls.count()).toBe(1)
done()
})
})
})
})
it('should compile parent template directives & content in parent scope', function (done) {
var vm = new Vue({
el: el,
data: {
ok: false,
message: 'hello'
},
template: '{{message}}',
components: {
test: {
template: ' {{message}}
',
replace: true,
data: function () {
return {
message: 'world'
}
}
}
}
})
expect(el.firstChild.style.display).toBe('none')
expect(el.firstChild.textContent).toBe('hello world')
vm.ok = true
vm.message = 'bye'
_.nextTick(function () {
expect(el.firstChild.style.display).toBe('')
expect(el.firstChild.textContent).toBe('bye world')
done()
})
})
it('parent content + v-if', function (done) {
var vm = new Vue({
el: el,
data: {
ok: false,
message: 'hello'
},
template: '{{message}}',
components: {
test: {
template: ' {{message}}',
data: function () {
return {
message: 'world'
}
}
}
}
})
expect(el.textContent).toBe('')
expect(vm.$children.length).toBe(0)
expect(vm._directives.length).toBe(1) // v-if
vm.ok = true
_.nextTick(function () {
expect(vm.$children.length).toBe(1)
expect(vm._directives.length).toBe(3) // v-if, component, v-text
expect(el.textContent).toBe('hello world')
done()
})
})
it('props', function () {
new Vue({
el: el,
data: {
list: [{a: 1}, {a: 2}]
},
template: '',
components: {
test: {
template: '',
replace: true,
props: ['collection']
}
}
})
expect(el.innerHTML).toBe('')
})
it('activate hook for static component', function (done) {
new Vue({
el: el,
template: '',
components: {
'view-a': {
template: 'AAA',
activate: function (ready) {
setTimeout(function () {
expect(el.textContent).toBe('')
ready()
expect(el.textContent).toBe('AAA')
done()
}, 0)
}
}
}
})
})
it('multiple activate hooks', function (done) {
var mixinSpy = jasmine.createSpy('mixin activate')
new Vue({
el: el,
template: '',
components: {
'view-a': {
template: 'AAA',
mixins: [{
activate: function (done) {
expect(el.textContent).toBe('')
mixinSpy()
done()
}
}],
activate: function (ready) {
setTimeout(function () {
expect(mixinSpy).toHaveBeenCalled()
expect(el.textContent).toBe('')
ready()
expect(el.textContent).toBe('AAA')
done()
}, 0)
}
}
}
})
})
it('activate hook for dynamic components', function (done) {
var next
var vm = new Vue({
el: el,
data: {
view: 'view-a'
},
template: '',
components: {
'view-a': {
template: 'AAA',
activate: function (ready) {
next = ready
}
},
'view-b': {
template: 'BBB',
activate: function (ready) {
next = ready
}
}
}
})
expect(next).toBeTruthy()
expect(el.textContent).toBe('')
next()
expect(el.textContent).toBe('AAA')
vm.view = 'view-b'
_.nextTick(function () {
expect(el.textContent).toBe('AAA')
// old vm is already removed, this is the new vm
expect(vm.$children.length).toBe(1)
next()
expect(el.textContent).toBe('BBB')
// ensure switching before ready event correctly
// cleans up the component being waited on.
// see #1152
vm.view = 'view-a'
// store the ready callback for view-a
var callback = next
_.nextTick(function () {
vm.view = 'view-b'
_.nextTick(function () {
expect(vm.$children.length).toBe(1)
expect(vm.$children[0].$el.textContent).toBe('BBB')
// calling view-a's ready callback here should not throw
// because it should've been cancelled (#1994)
expect(callback).not.toThrow()
done()
})
})
})
})
it('activate hook + keep-alive', function (done) {
var next
var vm = new Vue({
el: el,
data: {
view: 'view-a'
},
template: '',
components: {
'view-a': {
template: 'AAA',
activate: function (ready) {
next = ready
}
},
'view-b': {
template: 'BBB',
activate: function (ready) {
next = ready
}
}
}
})
next()
expect(el.textContent).toBe('AAA')
vm.view = 'view-b'
_.nextTick(function () {
expect(vm.$children.length).toBe(2)
next()
expect(el.textContent).toBe('BBB')
vm.view = 'view-a'
_.nextTick(function () {
// should switch without the need to emit
// because of keep-alive
expect(el.textContent).toBe('AAA')
done()
})
})
})
it('transition-mode: in-out', function (done) {
var spy1 = jasmine.createSpy('enter')
var spy2 = jasmine.createSpy('leave')
var next
var vm = new Vue({
el: el,
data: {
view: 'view-a'
},
template: '',
components: {
'view-a': { template: 'AAA' },
'view-b': { template: 'BBB' }
},
transitions: {
test: {
enter: function (el, done) {
spy1()
next = done
},
leave: function (el, done) {
spy2()
_.nextTick(done)
}
}
}
})
expect(el.textContent).toBe('AAA')
vm.view = 'view-b'
_.nextTick(function () {
expect(spy1).toHaveBeenCalled()
expect(spy2).not.toHaveBeenCalled()
expect(el.textContent).toBe('AAABBB')
next()
_.nextTick(function () {
expect(spy2).toHaveBeenCalled()
_.nextTick(function () {
expect(el.textContent).toBe('BBB')
done()
})
})
})
})
it('transition-mode: out-in', function (done) {
var spy1 = jasmine.createSpy('enter')
var spy2 = jasmine.createSpy('leave')
var next
var vm = new Vue({
el: el,
data: {
view: 'view-a'
},
template: '',
components: {
'view-a': { template: 'AAA' },
'view-b': { template: 'BBB' }
},
transitions: {
test: {
enter: function (el, done) {
spy2()
_.nextTick(done)
},
leave: function (el, done) {
spy1()
next = done
}
}
}
})
expect(el.textContent).toBe('AAA')
vm.view = 'view-b'
_.nextTick(function () {
expect(spy1).toHaveBeenCalled()
expect(spy2).not.toHaveBeenCalled()
expect(el.textContent).toBe('AAA')
next()
expect(spy2).toHaveBeenCalled()
expect(el.textContent).toBe('BBB')
done()
})
})
it('teardown', function (done) {
var vm = new Vue({
el: el,
template: '',
data: {
view: 'test'
},
components: {
test: {},
test2: {}
}
})
vm.view = 'test2'
_.nextTick(function () {
expect(vm.$children.length).toBe(2)
var child = vm.$children[0]
var child2 = vm.$children[1]
vm._directives[0].unbind()
expect(vm._directives[0].cache).toBeNull()
expect(vm.$children.length).toBe(0)
expect(child._isDestroyed).toBe(true)
expect(child2._isDestroyed).toBe(true)
done()
})
})
it('already mounted warn', function () {
el.setAttribute('is', 'test')
new Vue({
el: el
})
expect(hasWarned('cannot mount component "test" on already mounted element')).toBe(true)
})
it('not found component should not throw', function () {
expect(function () {
new Vue({
el: el,
template: ''
})
}).not.toThrow()
})
})