Skip to content

test: use sandbox to avoid memory leaks in test #1128

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

Merged
merged 7 commits into from
Feb 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"test:unit:debug": "npm run build:test && node --inspect-brk node_modules/.bin/mocha-webpack --webpack-config test/setup/webpack.test.config.js test/specs --recursive --require test/setup/mocha.setup.js",
"test:unit:karma": "npm run build:test && TARGET=browser karma start test/setup/karma.conf.js --single-run",
"test:unit:node": "npm run build:test && npm run test:unit:node:only",
"test:unit:node:only": "TEST_ENV=node mocha-webpack --webpack-config test/setup/webpack.test.config.js test/specs --recursive --require test/setup/mocha.setup.js",
"test:unit:node:only": "cross-env TEST_ENV=node mocha-webpack --webpack-config test/setup/webpack.test.config.js test/specs --recursive --require test/setup/mocha.setup.js",
"test:types": "tsc -p packages/test-utils/types && tsc -p packages/server-test-utils/types"
},
"devDependencies": {
Expand Down Expand Up @@ -54,18 +54,18 @@
"karma": "^1.7.0",
"karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.4",
"karma-sinon-chai": "^1.3.1",
"karma-sinon-chai": "^2.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "^0.0.31",
"karma-webpack": "^2.0.3",
"lerna": "2",
"markdown-it-include": "^1.0.0",
"mocha": "^3.5.0",
"mocha": "^5.2.0",
"mocha-webpack": "^1.0.1",
"prettier": "^1.16.0",
"rollup": "^0.58.2",
"sinon": "^2.3.2",
"sinon-chai": "^2.10.0",
"sinon": "^7.2.3",
"sinon-chai": "^3.3.0",
"typescript": "^3.0.1",
"vee-validate": "^2.1.3",
"vue": "^2.5.22",
Expand Down
11 changes: 8 additions & 3 deletions packages/create-instance/create-component-stubs.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ function resolveOptions(component, _Vue) {
return {}
}

return isConstructor(component)
? component.options
: _Vue.extend(component).options
if (isConstructor(component)) {
return component.options
}
const options = _Vue.extend(component).options
component._Ctor = {}

return options
}

export function createStubFromComponent(
Expand Down Expand Up @@ -165,6 +169,7 @@ export function createStubsFromStubsObject(
}

acc[stubName] = stub
stub._Ctor = {}

return acc
}, {})
Expand Down
2 changes: 1 addition & 1 deletion packages/create-instance/create-instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default function createInstance(
// make sure all extends are based on this instance

const Constructor = _Vue.extend(componentOptions).extend(instanceOptions)

componentOptions._Ctor = {}
Constructor.options._base = _Vue

const scopedSlots = createScopedSlots(options.scopedSlots, _Vue)
Expand Down
1 change: 1 addition & 0 deletions packages/create-instance/patch-create-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function shouldExtend(component, _Vue) {
function extend(component, _Vue) {
const componentOptions = component.options ? component.options : component
const stub = _Vue.extend(componentOptions)
componentOptions._Ctor = {}
stub.options.$_vueTestUtils_original = component
stub.options._base = _Vue
return stub
Expand Down
1 change: 0 additions & 1 deletion test/resources/components/component-with-events.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export default {
mousedownHandler(event) {
if (event.button === 0) {
this.clickHandler()
console.info(event.defaultPrevented)
}
},
toggleActive() {
Expand Down
4 changes: 2 additions & 2 deletions test/resources/components/recursive-component.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template>
<div>
<recursive-component
v-for="item in items"
:key="item"
v-for="(item, i) in items"
:key="i"
:items="items ? items[0] : []"
>{{ something }}</recursive-component
>
Expand Down
9 changes: 5 additions & 4 deletions test/specs/components/TransitionStub.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { TransitionStub } from '~vue/test-utils'
import { itDoNotRunIf } from 'conditional-specs'

describeWithShallowAndMount('TransitionStub', mountingMethod => {
let consoleError
const sandbox = sinon.createSandbox()

beforeEach(() => {
consoleError = sinon.stub(console, 'error')
sandbox.stub(console, 'error').callThrough()
})

afterEach(() => {
consoleError.restore()
sandbox.reset()
sandbox.restore()
})

it('update synchronously when used as stubs for Transition', () => {
Expand Down Expand Up @@ -76,7 +77,7 @@ describeWithShallowAndMount('TransitionStub', mountingMethod => {
transition: TransitionStub
}
})
expect(consoleError).calledWith(msg)
expect(console.error).calledWith(msg)
})

it('handles keyed transitions', () => {
Expand Down
16 changes: 10 additions & 6 deletions test/specs/config.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ import {
} from '~vue/test-utils'

describeWithShallowAndMount('config', mountingMethod => {
let configStubsSave, configLogSave, configSilentSave
const sandbox = sinon.createSandbox()
let configStubsSave
let configLogSave
let configSilentSave

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

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

itDoNotRunIf(
Expand Down Expand Up @@ -113,7 +117,7 @@ describeWithShallowAndMount('config', mountingMethod => {
const testComponent = {
template: `
<div>
<transition-group><p /><p /></transition-group>
<transition-group><p key="1"/><p key="2" /></transition-group>
</div>
`
}
Expand All @@ -135,7 +139,7 @@ describeWithShallowAndMount('config', mountingMethod => {
wrapper.setProps({
prop1: 'new value'
})
expect(console.error).not.calledWith(sinon.match('[Vue warn]'))
expect(console.error).not.calledWith(sandbox.match('[Vue warn]'))
})

it('does throw Vue warning when silent is set to false', () => {
Expand All @@ -151,6 +155,6 @@ describeWithShallowAndMount('config', mountingMethod => {
wrapper.setProps({
prop1: 'new value'
})
expect(console.error).calledWith(sinon.match('[Vue warn]'))
expect(console.error).calledWith(sandbox.match('[Vue warn]'))
})
})
7 changes: 4 additions & 3 deletions test/specs/error-wrapper.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { compileToFunctions } from 'vue-template-compiler'
import { describeWithShallowAndMount } from '~resources/utils'

describeWithShallowAndMount('ErrorWrapper', mountingMethod => {
Expand Down Expand Up @@ -36,10 +35,12 @@ describeWithShallowAndMount('ErrorWrapper', mountingMethod => {
]
methods.forEach(method => {
it(`${method} throws error when called`, () => {
const compiled = compileToFunctions('<p />')
const TestComponent = {
template: '<p />'
}
const selector = 'div'
const message = `[vue-test-utils]: find did not return ${selector}, cannot call ${method}() on empty Wrapper`
const wrapper = mountingMethod(compiled)
const wrapper = mountingMethod(TestComponent)
const error = wrapper.find(selector)
expect(error.constructor.name).to.equal('ErrorWrapper')
expect(() => error[method]())
Expand Down
24 changes: 13 additions & 11 deletions test/specs/mount.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import { describeRunIf, itDoNotRunIf, itSkipIf } from 'conditional-specs'
import Vuex from 'vuex'

describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => {
const sandbox = sinon.createSandbox()
const windowSave = window

beforeEach(() => {
sinon.stub(console, 'error').callThrough()
sandbox.stub(console, 'error').callThrough()
})

afterEach(() => {
window = windowSave // eslint-disable-line no-native-reassign
console.error.restore()
sandbox.reset()
sandbox.restore()
})

it('returns new VueWrapper with mounted Vue instance if no options are passed', () => {
Expand Down Expand Up @@ -101,7 +103,7 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => {
'handles extended components added to Vue constructor',
() => {
const ChildComponent = Vue.extend({
template: '<div />',
render: h => h('div'),
mounted() {
this.$route.params
}
Expand All @@ -126,10 +128,11 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => {
)

it('does not use cached component', () => {
ComponentWithMixin.methods.someMethod = sinon.stub()
sandbox.stub(ComponentWithMixin.methods, 'someMethod')
mount(ComponentWithMixin)
expect(ComponentWithMixin.methods.someMethod.callCount).to.equal(1)
ComponentWithMixin.methods.someMethod = sinon.stub()
ComponentWithMixin.methods.someMethod.restore()
sandbox.stub(ComponentWithMixin.methods, 'someMethod')
mount(ComponentWithMixin)
expect(ComponentWithMixin.methods.someMethod.callCount).to.equal(1)
})
Expand All @@ -138,7 +141,6 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => {
if (
!(navigator.userAgent.includes && navigator.userAgent.includes('node.js'))
) {
console.log('window read only. skipping test ...')
return
}

Expand All @@ -160,7 +162,7 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => {
})

itDoNotRunIf(vueVersion < 2.3, 'overrides methods', () => {
const stub = sinon.stub()
const stub = sandbox.stub()
const TestComponent = Vue.extend({
template: '<div />',
methods: {
Expand All @@ -179,8 +181,8 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => {
})

it.skip('overrides component prototype', () => {
const mountSpy = sinon.spy()
const destroySpy = sinon.spy()
const mountSpy = sandbox.spy()
const destroySpy = sandbox.spy()
const Component = Vue.extend({})
const {
$mount: originalMount,
Expand Down Expand Up @@ -233,7 +235,7 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => {
it('deletes mounting options before passing options to component', () => {
const wrapper = mount(
{
render: h => h('div')
template: '<div />'
},
{
provide: {
Expand All @@ -248,7 +250,7 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => {
},
localVue: createLocalVue(),
stubs: {
prop: 'val'
prop: { template: '<div />' }
},
attrs: {
prop: 'val'
Expand Down
8 changes: 5 additions & 3 deletions test/specs/mounting-options/attrs.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { compileToFunctions } from 'vue-template-compiler'
import { attrsSupported } from '~resources/utils'
import {
describeWithMountingMethods,
Expand All @@ -15,7 +14,10 @@ describeWithMountingMethods('options.attrs', mountingMethod => {
'handles inherit attrs',
() => {
if (!attrsSupported) return
const wrapper = mountingMethod(compileToFunctions('<p :id="anAttr" />'), {
const TestComponent = {
template: '<p :id="$attrs.anAttr" />'
}
const wrapper = mountingMethod(TestComponent, {
attrs: {
anAttr: 'an attribute'
}
Expand All @@ -29,7 +31,7 @@ describeWithMountingMethods('options.attrs', mountingMethod => {
mountingMethod.name === 'renderToString' || vueVersion < 2.5,
'defines attrs as empty object even when not passed',
() => {
const wrapper = mountingMethod(compileToFunctions('<p />'))
const wrapper = mountingMethod({ template: '<p />' })
expect(wrapper.vm.$attrs).to.deep.equal({})
}
)
Expand Down
7 changes: 4 additions & 3 deletions test/specs/mounting-options/listeners.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { compileToFunctions } from 'vue-template-compiler'
import { listenersSupported } from '~resources/utils'
import {
describeWithShallowAndMount,
Expand All @@ -14,7 +13,9 @@ describeWithShallowAndMount('options.listeners', mountingMethod => {
() => {
const aListener = () => {}
const wrapper = mountingMethod(
compileToFunctions('<p :id="aListener" />'),
{
template: '<p :id="$listeners.aListener" />'
},
{
listeners: {
aListener
Expand Down Expand Up @@ -56,7 +57,7 @@ describeWithShallowAndMount('options.listeners', mountingMethod => {
vueVersion < 2.5,
'defines listeners as empty object even when not passed',
() => {
const wrapper = mountingMethod(compileToFunctions('<p />'))
const wrapper = mountingMethod({ template: '<p />' })
expect(wrapper.vm.$listeners).to.deep.equal({})
}
)
Expand Down
2 changes: 1 addition & 1 deletion test/specs/mounting-options/localVue.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describeWithMountingMethods('options.localVue', mountingMethod => {
const Extends = {
template: '<div />',
created() {
console.log(this.$route.params)
this.$route.params
}
}
const TestComponent = {
Expand Down
8 changes: 5 additions & 3 deletions test/specs/mounting-options/mocks.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ import { describeWithMountingMethods, vueVersion } from '~resources/utils'
import { itDoNotRunIf, itSkipIf, itRunIf } from 'conditional-specs'

describeWithMountingMethods('options.mocks', mountingMethod => {
const sandbox = sinon.createSandbox()
let configMocksSave

beforeEach(() => {
configMocksSave = config.mocks
config.mocks = {}
sinon.stub(console, 'error')
sandbox.stub(console, 'error').callThrough()
})

afterEach(() => {
config.mocks = configMocksSave
console.error.restore()
sandbox.reset()
sandbox.restore()
})

it('adds variables to vm when passed', () => {
Expand Down Expand Up @@ -69,7 +71,7 @@ describeWithMountingMethods('options.mocks', mountingMethod => {
mountingMethod.name === 'renderToString',
'adds variables as reactive properties to vm when passed',
() => {
const stub = sinon.stub()
const stub = sandbox.stub()
const $reactiveMock = { value: 'value' }
const wrapper = mountingMethod(
{
Expand Down
Loading