2
0
mirror of https://github.com/tenrok/vue-meta.git synced 2026-06-21 22:30:34 +03:00

test: increase coverage, add missing tests

fix: issues discovered by adding missing tests
This commit is contained in:
pimlie
2019-03-08 22:13:21 +01:00
committed by Alexander Lichter
parent ce7eaf56d3
commit 5f8025e126
18 changed files with 494 additions and 112 deletions
+67 -6
View File
@@ -1,5 +1,6 @@
import _getMetaInfo from '../src/shared/getMetaInfo'
import { mount, defaultOptions, loadVueMetaPlugin } from './utils'
import { mount, loadVueMetaPlugin, vmTick } from './utils'
import { defaultOptions } from './utils/constants'
import GoodbyeWorld from './fixtures/goodbye-world.vue'
import HelloWorld from './fixtures/hello-world.vue'
@@ -8,10 +9,31 @@ import Changed from './fixtures/changed.vue'
const getMetaInfo = component => _getMetaInfo(defaultOptions, component)
jest.mock('../src/shared/window', () => ({
hasGlobalWindow: false
}))
describe('client', () => {
let Vue
let html
beforeAll(() => (Vue = loadVueMetaPlugin()))
beforeAll(() => {
Vue = loadVueMetaPlugin()
// force using timers, jest cant mock rAF
delete window.requestAnimationFrame
delete window.cancelAnimationFrame
html = document.createElement('html')
document._getElementsByTagName = document.getElementsByTagName
jest.spyOn(document, 'getElementsByTagName').mockImplementation((tag) => {
if (tag === 'html') {
return [html]
}
return document._getElementsByTagName(tag)
})
})
test('meta-info refreshed on component\'s data change', () => {
const wrapper = mount(HelloWorld, { localVue: Vue })
@@ -78,20 +100,59 @@ describe('client', () => {
expect(metaInfo.title.text()).toEqual('<title data-vue-meta="true">Hello World</title>')
})
test('changed function is called', () => {
test('doesnt update when ssr attribute is set', () => {
html.setAttribute(defaultOptions.ssrAttribute, 'true')
const wrapper = mount(HelloWorld, { localVue: Vue })
const { tags } = wrapper.vm.$meta().refresh()
expect(tags).toBe(false)
})
test('changed function is called', async () => {
const parentComponent = new Vue({ render: h => h('div') })
const wrapper = mount(Changed, { localVue: Vue, parentComponent })
await vmTick(wrapper.vm)
expect(wrapper.vm.$root._vueMeta.initialized).toBe(true)
let context
const changed = jest.fn(function () {
context = this
})
wrapper.setData({ changed })
wrapper.setData({ childVisible: true })
wrapper.setData({ changed, childVisible: true })
jest.runAllTimers()
wrapper.vm.$parent.$meta().refresh()
expect(changed).toHaveBeenCalledTimes(1)
// TODO: this isnt what the docs say
expect(context._uid).not.toBe(wrapper.vm._uid)
})
test('afterNavigation function is called', () => {
const Vue = loadVueMetaPlugin(false, { refreshOnceOnNavigation: true })
const afterNavigation = jest.fn()
const component = Vue.component('nav-component', {
render: h => h('div'),
metaInfo: { afterNavigation }
})
const guards = {}
Vue.prototype.$router = {
beforeEach(fn) {
guards.before = fn
},
afterEach(fn) {
guards.after = fn
}
}
const wrapper = mount(component, { localVue: Vue })
expect(guards.before).toBeDefined()
expect(guards.after).toBeDefined()
guards.before(null, null, () => {})
expect(wrapper.vm.$root._vueMeta.paused).toBe(true)
guards.after()
expect(afterNavigation).toHaveBeenCalled()
})
})
+6 -2
View File
@@ -1,5 +1,6 @@
import _getMetaInfo from '../src/shared/getMetaInfo'
import { defaultOptions, loadVueMetaPlugin } from './utils'
import { loadVueMetaPlugin } from './utils'
import { defaultOptions } from './utils/constants'
const getMetaInfo = (component, escapeSequences) => _getMetaInfo(defaultOptions, component, escapeSequences)
@@ -11,6 +12,7 @@ describe('escaping', () => {
test('special chars are escaped unless disabled', () => {
const component = new Vue({
metaInfo: {
htmlAttrs: { key: 1 },
title: 'Hello & Goodbye',
script: [{ innerHTML: 'Hello & Goodbye' }],
__dangerouslyDisableSanitizers: ['script']
@@ -21,7 +23,9 @@ describe('escaping', () => {
title: 'Hello &amp; Goodbye',
titleChunk: 'Hello & Goodbye',
titleTemplate: '%s',
htmlAttrs: {},
htmlAttrs: {
key: 1
},
headAttrs: {},
bodyAttrs: {},
meta: [],
+1 -1
View File
@@ -1,5 +1,5 @@
import _generateServerInjector from '../src/server/generateServerInjector'
import { defaultOptions } from './utils'
import { defaultOptions } from './utils/constants'
import metaInfoData from './utils/meta-info-data'
const generateServerInjector = (type, data) => _generateServerInjector(defaultOptions, type, data)
+47 -5
View File
@@ -1,4 +1,5 @@
import getComponentOption from '../src/shared/getComponentOption'
import inMetaInfoBranch from '../src/shared/inMetaInfoBranch'
import { mount, getVue, loadVueMetaPlugin } from './utils'
describe('getComponentOption', () => {
@@ -6,20 +7,20 @@ describe('getComponentOption', () => {
beforeAll(() => (Vue = getVue()))
it('returns an empty object when no matching options are found', () => {
test('returns an empty object when no matching options are found', () => {
const component = new Vue()
const mergedOption = getComponentOption({ component, keyName: 'noop' })
expect(mergedOption).toEqual({})
})
it('fetches the given option from the given component', () => {
test('fetches the given option from the given component', () => {
const component = new Vue({ someOption: { foo: 'bar' } })
const mergedOption = getComponentOption({ component, keyName: 'someOption' })
expect(mergedOption.foo).toBeDefined()
expect(mergedOption.foo).toEqual('bar')
})
it('calls a function option, injecting the component as context', () => {
test('calls a function option, injecting the component as context', () => {
const component = new Vue({
name: 'Foobar',
someFunc() {
@@ -32,7 +33,7 @@ describe('getComponentOption', () => {
expect(mergedOption.opt).toEqual('Foobar')
})
it('fetches deeply nested component options and merges them', () => {
test('fetches deeply nested component options and merges them', () => {
const localVue = loadVueMetaPlugin(true, { keyName: 'foo' })
localVue.component('merge-child', { render: h => h('div'), foo: { bar: 'baz' } })
@@ -47,7 +48,8 @@ describe('getComponentOption', () => {
expect(mergedOption).toEqual({ bar: 'baz', fizz: 'buzz' })
})
it('allows for a custom array merge strategy', () => {
/* this undocumented functionality has been removed
test('allows for a custom array merge strategy', () => {
const localVue = loadVueMetaPlugin(false, { keyName: 'foo' })
localVue.component('array-child', {
render: h => h('div'),
@@ -81,5 +83,45 @@ describe('getComponentOption', () => {
{ name: 'flower', content: 'tulip' },
{ name: 'flower', content: 'rose' }
] })
}) */
test('only traverses branches with metaInfo components', () => {
const localVue = loadVueMetaPlugin(false, { keyName: 'foo' })
localVue.component('meta-child', {
foo: { bar: 'baz' },
render(h) {
return h('div', this.$slots.default)
}
})
localVue.component('nometa-child', {
render(h) {
return h('div', this.$slots.default)
}
})
const component = localVue.component('parent', {
render: h => h('div', null, [
h('meta-child', null, [ h('nometa-child') ]),
h('nometa-child', null, [ h('meta-child') ]),
h('nometa-child')
])
})
const wrapper = mount(component, { localVue })
const mergedOption = getComponentOption({ component: wrapper.vm, keyName: 'foo' })
expect(mergedOption).toEqual({ bar: 'baz' })
expect(wrapper.vm.$children[0]._vueMeta).toBe(true)
expect(wrapper.vm.$children[1]._vueMeta).toBe(false)
expect(wrapper.vm.$children[2]._vueMeta).toBeUndefined()
expect(inMetaInfoBranch(wrapper.vm.$children[0])).toBe(true)
expect(inMetaInfoBranch(wrapper.vm.$children[0].$children[0])).toBe(false)
expect(inMetaInfoBranch(wrapper.vm.$children[1])).toBe(true)
expect(inMetaInfoBranch(wrapper.vm.$children[1].$children[0])).toBe(true)
expect(inMetaInfoBranch(wrapper.vm.$children[2])).toBe(false)
})
})
+66 -3
View File
@@ -1,5 +1,6 @@
import _getMetaInfo from '../src/shared/getMetaInfo'
import { defaultOptions, loadVueMetaPlugin } from './utils'
import { loadVueMetaPlugin } from './utils'
import { defaultOptions } from './utils/constants'
const getMetaInfo = component => _getMetaInfo(defaultOptions, component)
@@ -593,6 +594,60 @@ describe('getMetaInfo', () => {
})
})
test('properly uses meta templates with one-level-deep nested children when parent has no template', () => {
Vue.component('merge-child', {
render: h => h('div'),
metaInfo: {
title: 'Hello',
meta: [
{
vmid: 'og:title',
property: 'og:title',
content: 'An important title!',
template: chunk => `${chunk} - My page`
}
]
}
})
const component = new Vue({
metaInfo: {
meta: [
{
vmid: 'og:title',
property: 'og:title',
content: 'Test title'
}
]
},
el: document.createElement('div'),
render: h => h('div', null, [h('merge-child')])
})
expect(getMetaInfo(component)).toEqual({
title: 'Hello',
titleChunk: 'Hello',
titleTemplate: '%s',
htmlAttrs: {},
headAttrs: {},
bodyAttrs: {},
meta: [
{
vmid: 'og:title',
property: 'og:title',
content: 'An important title! - My page'
}
],
base: [],
link: [],
style: [],
script: [],
noscript: [],
__dangerouslyDisableSanitizers: [],
__dangerouslyDisableSanitizersByTagID: {}
})
})
test('no errors when metaInfo returns nothing', () => {
const component = new Vue({
metaInfo() {},
@@ -623,6 +678,9 @@ describe('getMetaInfo', () => {
render: h => h('div'),
metaInfo: {
title: undefined,
bodyAttrs: {
class: undefined
},
meta: [
{
vmid: 'og:title',
@@ -635,6 +693,9 @@ describe('getMetaInfo', () => {
const component = new Vue({
metaInfo: {
title: 'Hello',
bodyAttrs: {
class: 'class'
},
meta: [
{
vmid: 'og:title',
@@ -652,9 +713,11 @@ describe('getMetaInfo', () => {
title: 'Hello',
titleChunk: 'Hello',
titleTemplate: '%s',
htmlAttrs: {},
bodyAttrs: {
class: 'class'
},
headAttrs: {},
bodyAttrs: {},
htmlAttrs: {},
meta: [
{
vmid: 'og:title',
+2 -1
View File
@@ -1,6 +1,7 @@
import triggerUpdate from '../src/client/triggerUpdate'
import batchUpdate from '../src/client/batchUpdate'
import { mount, defaultOptions, vmTick, VueMetaBrowserPlugin, loadVueMetaPlugin } from './utils'
import { mount, vmTick, VueMetaBrowserPlugin, loadVueMetaPlugin } from './utils'
import { defaultOptions } from './utils/constants'
jest.mock('../src/client/triggerUpdate')
jest.mock('../src/client/batchUpdate')
+13 -1
View File
@@ -1,4 +1,5 @@
import { mount, defaultOptions, VueMetaServerPlugin, loadVueMetaPlugin } from './utils'
import { mount, VueMetaServerPlugin, loadVueMetaPlugin } from './utils'
import { defaultOptions } from './utils/constants'
jest.mock('../package.json', () => ({
version: 'test-version'
@@ -13,6 +14,17 @@ describe('plugin', () => {
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()).toBeDefined()
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', () => {
+1 -1
View File
@@ -1,5 +1,5 @@
import _updateClientMetaInfo from '../src/client/updateClientMetaInfo'
import { defaultOptions } from './utils'
import { defaultOptions } from './utils/constants'
import metaInfoData from './utils/meta-info-data'
const updateClientMetaInfo = (type, data) => _updateClientMetaInfo(defaultOptions, { [type]: data })
+1 -18
View File
@@ -2,15 +2,7 @@ import { mount, createLocalVue } from '@vue/test-utils'
import { renderToString } from '@vue/server-test-utils'
import VueMetaBrowserPlugin from '../../src/browser'
import VueMetaServerPlugin from '../../src'
import {
keyName,
attribute,
ssrAttribute,
tagIDKeyName,
metaTemplateKeyName,
contentKeyName
} from '../../src/shared/constants'
import { defaultOptions } from './constants'
export {
mount,
@@ -19,15 +11,6 @@ export {
VueMetaServerPlugin
}
export const defaultOptions = {
keyName,
attribute,
ssrAttribute,
tagIDKeyName,
metaTemplateKeyName,
contentKeyName
}
export function getVue() {
return createLocalVue()
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { defaultOptions } from './'
import { defaultOptions } from './constants'
const metaInfoData = {
title: {
-4
View File
@@ -1,5 +1 @@
import jsdom from 'jsdom-global'
jsdom()
jest.useFakeTimers()