2
0
mirror of https://github.com/tenrok/vue-meta.git synced 2026-05-17 06:29:38 +03:00
Files
vue-meta/test/unit/plugin-browser.test.js
T
pimlie c040de7be7 fix: use timers instead of requestAnimationFrame
The issue with using requestAnimationFrame is that its meant to be used for visual effects. Therefore when a tab is hidden the browser might decide to not perform animation frame updates until the tab becomes visible, this is confirmed behaviour for Firefox. Due to this title updates would not be triggered while document titles are normally visible in the tabs title. For now we batch updates by setting/clearing timeouts with a 10ms interval

Resolves: #313
2019-04-23 10:58:34 +02:00

164 lines
5.0 KiB
JavaScript

import { triggerUpdate, batchUpdate } from '../../src/client/update'
import { mount, vmTick, VueMetaBrowserPlugin, loadVueMetaPlugin } from '../utils'
import { defaultOptions } from '../../src/shared/constants'
jest.mock('../../src/client/update')
jest.mock('../../package.json', () => ({
version: 'test-version'
}))
describe('plugin', () => {
let Vue
beforeEach(() => jest.clearAllMocks())
beforeAll(() => (Vue = loadVueMetaPlugin(true)))
test('is loaded', () => {
const instance = new Vue()
expect(instance.$meta).toEqual(expect.any(Function))
expect(instance.$meta().inject).toEqual(expect.any(Function))
expect(instance.$meta().refresh).toEqual(expect.any(Function))
expect(instance.$meta().getOptions).toEqual(expect.any(Function))
expect(instance.$meta().inject()).toBeUndefined()
expect(instance.$meta().refresh()).toBeDefined()
const options = instance.$meta().getOptions()
expect(options).toBeDefined()
expect(options.keyName).toBe(defaultOptions.keyName)
})
test('component has _hasMetaInfo set to true', () => {
const Component = Vue.component('test-component', {
template: '<div>Test</div>',
[defaultOptions.keyName]: {
title: 'Hello World'
}
})
const { vm } = mount(Component, { localVue: Vue })
expect(vm._hasMetaInfo).toBe(true)
})
test('plugin sets package version', () => {
expect(VueMetaBrowserPlugin.version).toBe('test-version')
})
test('updates can be paused and resumed', async () => {
const { batchUpdate: _batchUpdate } = jest.requireActual('../../src/client/update')
const batchUpdateSpy = batchUpdate.mockImplementation(_batchUpdate)
// because triggerUpdate & batchUpdate reside in the same file we cant mock them both,
// so just recreate the triggerUpdate fn by copying its implementation
const triggerUpdateSpy = triggerUpdate.mockImplementation((vm, hookName) => {
if (vm.$root._vueMeta.initialized && !vm.$root._vueMeta.paused) {
// batch potential DOM updates to prevent extraneous re-rendering
batchUpdateSpy(() => vm.$meta().refresh())
}
})
const Component = Vue.component('test-component', {
metaInfo() {
return {
title: this.title
}
},
props: {
title: {
type: String,
default: ''
}
},
template: '<div>Test</div>'
})
let title = 'first title'
const wrapper = mount(Component, {
localVue: Vue,
propsData: {
title
}
})
// no batchUpdate on initialization
expect(wrapper.vm.$root._vueMeta.initialized).toBe(false)
expect(wrapper.vm.$root._vueMeta.paused).toBeFalsy()
expect(triggerUpdateSpy).toHaveBeenCalledTimes(1)
expect(batchUpdateSpy).not.toHaveBeenCalled()
jest.clearAllMocks()
await vmTick(wrapper.vm)
title = 'second title'
wrapper.setProps({ title })
// batchUpdate on normal update
expect(wrapper.vm.$root._vueMeta.initialized).toBe(true)
expect(wrapper.vm.$root._vueMeta.paused).toBeFalsy()
expect(triggerUpdateSpy).toHaveBeenCalledTimes(1)
expect(batchUpdateSpy).toHaveBeenCalledTimes(1)
jest.clearAllMocks()
wrapper.vm.$meta().pause()
title = 'third title'
wrapper.setProps({ title })
// no batchUpdate when paused
expect(wrapper.vm.$root._vueMeta.initialized).toBe(true)
expect(wrapper.vm.$root._vueMeta.paused).toBe(true)
expect(triggerUpdateSpy).toHaveBeenCalledTimes(1)
expect(batchUpdateSpy).not.toHaveBeenCalled()
jest.clearAllMocks()
const { metaInfo } = wrapper.vm.$meta().resume()
expect(metaInfo.title).toBe(title)
})
test('updates are batched', async () => {
jest.useFakeTimers()
const { batchUpdate: _batchUpdate } = jest.requireActual('../../src/client/update')
const batchUpdateSpy = batchUpdate.mockImplementation(_batchUpdate)
const refreshSpy = jest.fn()
// because triggerUpdate & batchUpdate reside in the same file we cant mock them both,
// so just recreate the triggerUpdate fn by copying its implementation
triggerUpdate.mockImplementation((vm, hookName) => {
if (vm.$root._vueMeta.initialized && !vm.$root._vueMeta.paused) {
// batch potential DOM updates to prevent extraneous re-rendering
batchUpdateSpy(refreshSpy)
}
})
const Component = Vue.component('test-component', {
metaInfo() {
return {
title: this.title
}
},
props: {
title: {
type: String,
default: ''
}
},
template: '<div>Test</div>'
})
let title = 'first title'
const wrapper = mount(Component, {
localVue: Vue,
propsData: {
title
}
})
await vmTick(wrapper.vm)
jest.clearAllMocks()
title = 'second title'
wrapper.setProps({ title })
jest.advanceTimersByTime(2)
expect(refreshSpy).not.toHaveBeenCalled()
jest.advanceTimersByTime(10)
expect(refreshSpy).toHaveBeenCalled()
})
})