import Vue from 'vue'
describe('Directive v-once', () => {
it('should not rerender component', done => {
const vm = new Vue({
template: '
{{ a }}
',
data: { a: 'hello' }
}).$mount()
expect(vm.$el.innerHTML).toBe('hello')
vm.a = 'world'
waitForUpdate(() => {
expect(vm.$el.innerHTML).toBe('hello')
}).then(done)
})
it('should not rerender self and child component', done => {
const vm = new Vue({
template: `
{{ a }}
`,
data: { a: 'hello' },
components: {
item: {
template: '{{ b }}
',
props: ['b']
}
}
}).$mount()
expect(vm.$children.length).toBe(1)
expect(vm.$el.innerHTML)
.toBe('hello hello
')
vm.a = 'world'
waitForUpdate(() => {
expect(vm.$el.innerHTML)
.toBe('hello hello
')
}).then(done)
})
it('should rerender parent but not self', done => {
const vm = new Vue({
template: `
{{ a }}
`,
data: { a: 'hello' },
components: {
item: {
template: '{{ b }}
',
props: ['b']
}
}
}).$mount()
expect(vm.$children.length).toBe(1)
expect(vm.$el.innerHTML)
.toBe('hello hello
')
vm.a = 'world'
waitForUpdate(() => {
expect(vm.$el.innerHTML)
.toBe('world hello
')
}).then(done)
})
it('should not rerender static sub nodes', done => {
const vm = new Vue({
template: `
{{ a }}
{{ suffix }}
`,
data: {
a: 'hello',
suffix: '?'
},
components: {
item: {
template: '{{ b }}
',
props: ['b']
}
}
}).$mount()
expect(vm.$el.innerHTML)
.toBe('hello hello
?')
vm.a = 'world'
waitForUpdate(() => {
expect(vm.$el.innerHTML)
.toBe('hello world
?')
vm.suffix = '!'
}).then(() => {
expect(vm.$el.innerHTML)
.toBe('hello world
!')
}).then(done)
})
it('should work with v-if', done => {
const vm = new Vue({
data: {
tester: true,
yes: 'y',
no: 'n'
},
template: `
{{ yes }}
{{ no }}
{{ yes }}
{{ no }}
{{ yes }}
{{ no }}
{{ yes }}
{{ no }}
`
}).$mount()
expectTextContent(vm, 'yyyy')
vm.yes = 'yes'
waitForUpdate(() => {
expectTextContent(vm, 'yesyyesy')
vm.tester = false
}).then(() => {
expectTextContent(vm, 'nnnn')
vm.no = 'no'
}).then(() => {
expectTextContent(vm, 'nononn')
}).then(done)
})
it('should work with v-for', done => {
const vm = new Vue({
data: {
list: [1, 2, 3]
},
template: ``
}).$mount()
expect(vm.$el.textContent).toBe('123')
vm.list.reverse()
waitForUpdate(() => {
expect(vm.$el.textContent).toBe('123')
}).then(done)
})
it('should work inside v-for', done => {
const vm = new Vue({
data: {
list: [
{ id: 0, text: 'a' },
{ id: 1, text: 'b' },
{ id: 2, text: 'c' }
]
},
template: `
`
}).$mount()
expect(vm.$el.textContent).toBe('aabbcc')
vm.list[0].text = 'd'
waitForUpdate(() => {
expect(vm.$el.textContent).toBe('adbbcc')
vm.list[1].text = 'e'
}).then(() => {
expect(vm.$el.textContent).toBe('adbecc')
vm.list.reverse()
}).then(() => {
expect(vm.$el.textContent).toBe('ccbead')
}).then(done)
})
it('should work inside v-for with v-if', done => {
const vm = new Vue({
data: {
list: [
{ id: 0, text: 'a', tester: true, truthy: 'y' }
]
},
template: `
{{ i.truthy }}
{{ i.text }}
{{ i.truthy }}
{{ i.text }}
{{ i.truthy }}
{{ i.text }}
{{ i.truthy }}
{{ i.text }}
`
}).$mount()
expectTextContent(vm, 'yyyy')
vm.list[0].truthy = 'yy'
waitForUpdate(() => {
expectTextContent(vm, 'yyyyyy')
vm.list[0].tester = false
}).then(() => {
expectTextContent(vm, 'aaaa')
vm.list[0].text = 'nn'
}).then(() => {
expectTextContent(vm, 'annann')
}).then(done)
})
it('should work inside v-for with nested v-else', done => {
const vm = new Vue({
data: {
list: [{ id: 0, text: 'a', tester: true, truthy: 'y' }]
},
template: `
{{ i.truthy }}
{{ i.text }}
`
}).$mount()
expectTextContent(vm, 'y')
vm.list[0].truthy = 'yy'
waitForUpdate(() => {
expectTextContent(vm, 'y')
vm.list[0].tester = false
}).then(() => {
expectTextContent(vm, 'a')
vm.list[0].text = 'nn'
}).then(() => {
expectTextContent(vm, 'a')
}).then(done)
})
it('should work inside v-for with nested v-else-if and v-else', done => {
const vm = new Vue({
data: {
tester: false,
list: [{ id: 0, text: 'a', tester: true, truthy: 'y' }]
},
template: `
{{ i.truthy }}
{{ i.text }}elseif
{{ i.text }}
{{ i.truthy }}
{{ i.text }}elseif
{{ i.text }}
`
}).$mount()
expectTextContent(vm, 'y')
vm.list[0].truthy = 'yy'
waitForUpdate(() => {
expectTextContent(vm, 'y')
vm.list[0].tester = false
}).then(() => {
expectTextContent(vm, 'a')
vm.list[0].text = 'nn'
}).then(() => {
expectTextContent(vm, 'a')
vm.tester = true
}).then(() => {
expectTextContent(vm, 'nnelseif')
vm.list[0].text = 'xx'
}).then(() => {
expectTextContent(vm, 'nnelseif')
vm.list[0].tester = true
}).then(() => {
expectTextContent(vm, 'yy')
vm.list[0].truthy = 'nn'
}).then(() => {
expectTextContent(vm, 'yy')
}).then(done)
})
it('should warn inside non-keyed v-for', () => {
const vm = new Vue({
data: {
list: [
{ id: 0, text: 'a' },
{ id: 1, text: 'b' },
{ id: 2, text: 'c' }
]
},
template: `
`
}).$mount()
expect(vm.$el.textContent).toBe('aabbcc')
expect(`v-once can only be used inside v-for that is keyed.`).toHaveBeenWarned()
})
// #4288
it('should inherit child reference for v-once', done => {
const vm = new Vue({
template: `{{a}}
`,
data: {
a: 0,
ok: true
},
components: {
test: {
template: 'foo
'
}
}
}).$mount()
vm.a++ // first update to force a patch
waitForUpdate(() => {
expect(vm.$el.textContent).toBe('1foo')
}).then(() => {
vm.ok = false // teardown component with v-once
}).then(done) // should not throw
})
})
function expectTextContent (vm, text) {
expect(vm.$el.textContent.replace(/\r?\n|\r|\s/g, '')).toBe(text)
}