Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use Vue async option for sync mode #1062

Merged
merged 12 commits into from
Feb 2, 2019
1 change: 0 additions & 1 deletion flow/config.flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ declare type Config = {
mocks?: Object,
methods?: { [name: string]: Function },
provide?: Object,
logModifiedComponents?: boolean,
silent?: boolean
};
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@
"sinon-chai": "^2.10.0",
"typescript": "^3.0.1",
"vee-validate": "^2.1.3",
"vue": "2.5.16",
"vue": "2.5.20",
"vue-class-component": "^6.1.2",
"vue-loader": "^13.6.2",
"vue-router": "^3.0.1",
"vue-server-renderer": "2.5.16",
"vue-template-compiler": "2.5.16",
"vue-server-renderer": "2.5.20",
"vue-template-compiler": "2.5.20",
"vuepress": "^0.14.2",
"vuepress-theme-vue": "^1.0.3",
"vuex": "^3.0.1",
Expand Down
1 change: 0 additions & 1 deletion packages/create-instance/extract-instance-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const MOUNTING_OPTIONS = [
'attrs',
'listeners',
'propsData',
'logModifiedComponents',
'sync',
'shouldProxy'
]
Expand Down
1 change: 0 additions & 1 deletion packages/server-test-utils/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ interface VueTestUtilsConfigOptions {
mocks?: object
methods?: Record<string, Function>
provide?: object,
logModifiedComponents?: Boolean
silent?: Boolean
}

Expand Down
1 change: 0 additions & 1 deletion packages/server-test-utils/types/test/renderToString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,4 @@ config.methods = {
config.provide = {
foo: {}
}
config.logModifiedComponents = true
config.silent = true
3 changes: 3 additions & 0 deletions packages/shared/consts.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export const COMPONENT_SELECTOR = 'COMPONENT_SELECTOR'
export const REF_SELECTOR = 'REF_SELECTOR'
export const DOM_SELECTOR = 'DOM_SELECTOR'
export const INVALID_SELECTOR = 'INVALID_SELECTOR'

export const COMPAT_SYNC_MODE = 'COMPAT_SYNC_MODE'

export const VUE_VERSION = Number(
`${Vue.version.split('.')[0]}.${Vue.version.split('.')[1]}`
)
Expand Down
1 change: 0 additions & 1 deletion packages/shared/merge-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export function mergeOptions (options: Options, config: Config): Options {
const provide = ((getOption(options.provide, config.provide)): Object)
return {
...options,
logModifiedComponents: config.logModifiedComponents,
stubs: getOption(normalizeStubs(options.stubs), config.stubs),
mocks,
methods,
Expand Down
37 changes: 34 additions & 3 deletions packages/test-utils/src/mount.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,53 @@ import config from './config'
import warnIfNoWindow from './warn-if-no-window'
import createWrapper from './create-wrapper'
import createLocalVue from './create-local-vue'
import { semVerGreaterThan, warn } from 'shared/util'
import { COMPAT_SYNC_MODE } from 'shared/consts'

Vue.config.productionTip = false
Vue.config.devtools = false

function getSyncOption (syncOption) {
if (syncOption === false) {
Vue.config.async = true
return false
}
if (!semVerGreaterThan(Vue.version, '2.5.17')) {
warn(
`Vue Test Utils runs in sync mode by default. Due to bugs, sync mode ` +
`requires Vue > 2.5.18. In Vue Test Utils 1.0 sync mode will only be ` +
`supported with Vue 2.5.18 running in development mode. If you are ` +
`unable to upgrade, you should rewrite your tests to run synchronously` +
eddyerburgh marked this conversation as resolved.
Show resolved Hide resolved
`you can do this by setting the sync mounting option to false.`
)
return COMPAT_SYNC_MODE
}

if (typeof Vue.config.async === 'undefined') {
warn(
`Sync mode only works when Vue runs in dev mode. ` +
`Please set Vue to run in dev mode, or set sync to false`
)
}

Vue.config.async = false
return true
}

export default function mount (
component: Component,
options: Options = {}
): VueWrapper | Wrapper {
const mergedOptions = mergeOptions(options, config)
const sync = getSyncOption(mergedOptions.sync)
const existingErrorHandler = Vue.config.errorHandler

Vue.config.errorHandler = errorHandler

warnIfNoWindow()

const elm = options.attachToDocument ? createElement() : undefined

const mergedOptions = mergeOptions(options, config)

const parentVm = createInstance(
component,
mergedOptions,
Expand All @@ -49,7 +80,7 @@ export default function mount (

const wrapperOptions = {
attachedToDocument: !!mergedOptions.attachToDocument,
sync: mergedOptions.sync
sync
}
const root = vm.$options._isFunctionalContainer
? vm._vnode
Expand Down
3 changes: 2 additions & 1 deletion packages/test-utils/src/vue-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Wrapper from './wrapper'
import { throwError } from 'shared/util'
import { setWatchersToSync } from './set-watchers-to-sync'
import { orderWatchers } from './order-watchers'
import { COMPAT_SYNC_MODE } from 'shared/consts'

export default class VueWrapper extends Wrapper implements BaseWrapper {
constructor (vm: Component, options: WrapperOptions) {
Expand All @@ -28,7 +29,7 @@ export default class VueWrapper extends Wrapper implements BaseWrapper {
get: () => vm,
set: () => throwError('wrapper.vm is read-only')
})
if (options.sync) {
if (options.sync === COMPAT_SYNC_MODE) {
setWatchersToSync(vm)
orderWatchers(vm)
}
Expand Down
11 changes: 7 additions & 4 deletions packages/test-utils/src/wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import Vue from 'vue'
import getSelector from './get-selector'
import {
REF_SELECTOR,
FUNCTIONAL_OPTIONS
FUNCTIONAL_OPTIONS,
COMPAT_SYNC_MODE
} from 'shared/consts'
import config from './config'
import WrapperArray from './wrapper-array'
Expand Down Expand Up @@ -758,8 +759,10 @@ export default class Wrapper implements BaseWrapper {
})
// $FlowIgnore : Problem with possibly null this.vm
this.vm.$forceUpdate()
// $FlowIgnore : Problem with possibly null this.vm
orderWatchers(this.vm || this.vnode.context.$root)
if (this.options.sync === COMPAT_SYNC_MODE) {
// $FlowIgnore : Problem with possibly null this.vm
orderWatchers(this.vm || this.vnode.context.$root)
}
Vue.config.silent = originalConfig
}

Expand Down Expand Up @@ -832,7 +835,7 @@ export default class Wrapper implements BaseWrapper {
const event = createDOMEvent(type, options)
this.element.dispatchEvent(event)

if (this.vnode) {
if (this.vnode && this.options.sync === COMPAT_SYNC_MODE) {
orderWatchers(this.vm || this.vnode.context.$root)
}
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-compat-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ scripts/test-compat.sh "2.1.10"
scripts/test-compat.sh "2.2.6"
scripts/test-compat.sh "2.3.4"
scripts/test-compat.sh "2.4.2"
scripts/test-compat.sh "2.5.16"
scripts/test-compat.sh "2.5.20"
34 changes: 7 additions & 27 deletions test/specs/config.spec.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import { describeWithShallowAndMount, vueVersion } from '~resources/utils'
import { describeWithShallowAndMount } from '~resources/utils'
import ComponentWithProps from '~resources/components/component-with-props.vue'
import { itDoNotRunIf, itSkipIf } from 'conditional-specs'
import { itDoNotRunIf } from 'conditional-specs'
import {
config,
TransitionStub,
TransitionGroupStub,
createLocalVue
} from '~vue/test-utils'
import Vue from 'vue'

describeWithShallowAndMount('config', mountingMethod => {
let configStubsSave, consoleError, configLogSave, configSilentSave
let configStubsSave, configLogSave, configSilentSave

beforeEach(() => {
configStubsSave = config.stubs
configLogSave = config.logModifiedComponents
configSilentSave = config.silent
consoleError = sinon.stub(console, 'error')
sinon.stub(console, 'error').callThrough()
})

afterEach(() => {
config.stubs = configStubsSave
config.logModifiedComponents = configLogSave
config.silent = configSilentSave
consoleError.restore()
console.error.restore()
})

itDoNotRunIf(
Expand Down Expand Up @@ -150,7 +149,7 @@ describeWithShallowAndMount('config', mountingMethod => {
wrapper.setProps({
prop1: 'new value'
})
expect(consoleError.called).to.equal(false)
expect(console.error).not.calledWith(sinon.match('[Vue warn]'))
})

it('does throw Vue warning when silent is set to false', () => {
Expand All @@ -166,25 +165,6 @@ describeWithShallowAndMount('config', mountingMethod => {
wrapper.setProps({
prop1: 'new value'
})
expect(consoleError.called).to.equal(true)
expect(console.error).calledWith(sinon.match('[Vue warn]'))
})

itSkipIf(
vueVersion < 2.3,
'does not log when component is extended if logModifiedComponents is false',
() => {
const ChildComponent = Vue.extend({
template: '<span />'
})
const TestComponent = {
template: '<child-component />',
components: {
ChildComponent
}
}
config.logModifiedComponents = false
mountingMethod(TestComponent)
expect(consoleError.called).to.equal(false)
}
)
})
25 changes: 25 additions & 0 deletions test/specs/mounting-options/scopedSlots.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,29 @@ describeWithShallowAndMount('scopedSlots', mountingMethod => {
.with.property('message', message)
}
)

itDoNotRunIf(
vueVersion < 2.5,
'renders scoped slots in sync mode by default', () => {
const TestComponent = {
data () {
return {
val: null
}
},
mounted () {
this.val = 123
},
render () {
return this.$scopedSlots.default(this.val)
}
}
const stub = sinon.stub()
mountingMethod(TestComponent, {
scopedSlots: {
default: stub
}
})
expect(stub).calledWith(123)
})
})
31 changes: 28 additions & 3 deletions test/specs/mounting-options/sync.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import sinon from 'sinon'
import { describeWithShallowAndMount } from '~resources/utils'
import { describeWithShallowAndMount, vueVersion } from '~resources/utils'
import { itDoNotRunIf } from 'conditional-specs'

describeWithShallowAndMount('options.sync', mountingMethod => {
beforeEach(() => {
sinon.stub(console, 'error').callThrough()
})

afterEach(() => {
console.error.restore()
})

it('sets watchers to sync if set to true', () => {
const TestComponent = {
template: '<div>{{someData}}</div>',
Expand All @@ -12,11 +21,12 @@ describeWithShallowAndMount('options.sync', mountingMethod => {
const wrapper = mountingMethod(TestComponent, {
sync: true
})
const syncValue = vueVersion < 2.5 ? 'COMPAT_SYNC_MODE' : true

expect(wrapper.text()).to.equal('hello')
wrapper.vm.someData = 'world'
expect(wrapper.text()).to.equal('world')
expect(wrapper.options.sync).to.equal(true)
expect(wrapper.options.sync).to.equal(syncValue)
})

it('sets watchers to sync if undefined', () => {
Expand All @@ -27,11 +37,12 @@ describeWithShallowAndMount('options.sync', mountingMethod => {
})
}
const wrapper = mountingMethod(TestComponent)
const syncValue = vueVersion < 2.5 ? 'COMPAT_SYNC_MODE' : true

expect(wrapper.text()).to.equal('hello')
wrapper.vm.someData = 'world'
expect(wrapper.text()).to.equal('world')
expect(wrapper.options.sync).to.equal(true)
expect(wrapper.options.sync).to.equal(syncValue)
})

it('handles methods that update watchers', () => {
Expand Down Expand Up @@ -145,4 +156,18 @@ describeWithShallowAndMount('options.sync', mountingMethod => {
expect(childComponentSpy.calledOnce).to.equal(true)
expect(wrapper.html()).to.equal('<div>bar<div>bar</div></div>')
})

itDoNotRunIf(
vueVersion > 2.4,
'warns if Vue version is less than 2.5.18',
() => {
const TestComponent = {
template: '<div />'
}
mountingMethod(TestComponent)
expect(console.error)
.calledWith(
sinon.match('Vue Test Utils runs in sync mode by default')
)
})
})
4 changes: 2 additions & 2 deletions test/specs/shallow-mount.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => {
}
}
shallowMount(TestComponent)
expect(console.error).not.called
expect(console.error).not.calledWith(sinon.match('[Vue warn]'))
}
)

Expand Down Expand Up @@ -248,7 +248,7 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => {
}
const wrapper = shallowMount(TestComponent)
expect(wrapper.html()).to.contain('<test-component-stub>')
expect(console.error).not.called
expect(console.error).not.calledWith('[Vue warn]')
})

it('does not call stubbed children lifecycle hooks', () => {
Expand Down
Loading