diff --git a/docs/api/options.md b/docs/api/options.md index 35eaebae2..de35e147b 100644 --- a/docs/api/options.md +++ b/docs/api/options.md @@ -292,29 +292,21 @@ When `sync` is `false`, the Vue component is rendered asynchronously. ## Other options -When the options for `mount` and `shallowMount` contain the options other than the mounting options, the component options are overwritten with those using [extends](https://vuejs.org/v2/api/#extends). +When the options for `mount` and `shallowMount` contain the options other than the mounting options, the options are added used when the Vue instance is initialized. ```js const Component = { - template: '
{{ foo() }}{{ bar() }}{{ baz() }}
', - methods: { - foo () { - return 'a' - }, - bar () { - return 'b' - } - } + template: ` +
+ id: {$route.params.id} + username: {$store.state.username} +
+ ` } + const options = { - methods: { - bar () { - return 'B' - }, - baz () { - return 'C' - } - } + store, + route } const wrapper = mount(Component, options) expect(wrapper.text()).toBe('aBC') diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index d895af758..7ae2aa91f 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -90,8 +90,8 @@ export default function createInstance ( // extend component from _Vue to add properties and mixins // extend does not work correctly for sub class components in Vue < 2.2 const Constructor = typeof component === 'function' - ? _Vue.extend(component.options).extend(instanceOptions) - : _Vue.extend(component).extend(instanceOptions) + ? _Vue.extend(component.options) + : _Vue.extend(component) // used to identify extended component using constructor Constructor.options.$_vueTestUtils_original = component @@ -151,5 +151,5 @@ export default function createInstance ( } const Parent = _Vue.extend(parentComponentOptions) - return new Parent() + return new Parent(instanceOptions) } diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 4d13e0c25..2e1532191 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -675,11 +675,15 @@ export default class Wrapper implements BaseWrapper { */ setMethods (methods: Object): void { if (!this.isVueInstance()) { - throwError( - `wrapper.setMethods() can only be called on a Vue ` + - `instance` - ) + throwError(`wrapper.setMethods() can only be called on a Vue instance`) } + // the methods object is a reference to the original component methods + // object. So before making any changes we need to replace vm.methods with + // an object that we can change safely. + + // $FlowIgnore + this.vm.$options.methods = Object.create(this.vm.$options.methods) + Object.keys(methods).forEach(key => { // $FlowIgnore : Problem with possibly null this.vm this.vm[key] = methods[key] diff --git a/test/specs/config.spec.js b/test/specs/config.spec.js index 5dacf4adb..d4e5ac275 100644 --- a/test/specs/config.spec.js +++ b/test/specs/config.spec.js @@ -68,21 +68,6 @@ describeWithShallowAndMount('config', mountingMethod => { localVue.prototype.$t = undefined }) - it('overrides a method', () => { - const testComponent = { - template: ` -
{{ val() }}
- ` - } - - config.methods['val'] = () => 'method' - - const wrapper = mountingMethod(testComponent) - - expect(wrapper.vm.val()).to.equal('method') - expect(wrapper.text()).to.equal('method') - }) - it("doesn't stub transition when config.stubs.transition is set to false", () => { const testComponent = { template: ` diff --git a/test/specs/mount.spec.js b/test/specs/mount.spec.js index cdbdfcef4..743b6bfea 100644 --- a/test/specs/mount.spec.js +++ b/test/specs/mount.spec.js @@ -5,7 +5,7 @@ import Component from '~resources/components/component.vue' import ComponentWithProps from '~resources/components/component-with-props.vue' import ComponentWithMixin from '~resources/components/component-with-mixin.vue' import ComponentAsAClass from '~resources/components/component-as-a-class.vue' -import { injectSupported, vueVersion } from '~resources/utils' +import { vueVersion } from '~resources/utils' import { describeRunIf, itDoNotRunIf, itSkipIf } from 'conditional-specs' import Vuex from 'vuex' @@ -161,27 +161,6 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => { expect(wrapper.html()).to.equal(`
foo
`) }) - itDoNotRunIf( - vueVersion < 2.3, - 'overrides methods', () => { - const stub = sinon.stub() - const TestComponent = Vue.extend({ - template: '
', - methods: { - callStub () { - stub() - } - } - }) - mount(TestComponent, { - methods: { - callStub () {} - } - }).vm.callStub() - - expect(stub).not.called - }) - it.skip('overrides component prototype', () => { const mountSpy = sinon.spy() const destroySpy = sinon.spy() @@ -235,9 +214,6 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => { render: h => h('div') }, { - provide: { - prop: 'val' - }, attachToDocument: 'attachToDocument', mocks: { prop: 'val' @@ -257,9 +233,6 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => { } } ) - if (injectSupported) { - expect(typeof wrapper.vm.$options.provide).to.equal('object') - } expect(wrapper.vm.$options.attachToDocument).to.equal(undefined) expect(wrapper.vm.$options.mocks).to.equal(undefined) @@ -373,32 +346,6 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => { expect(wrapper.html()).to.equal(`

prop1

`) }) - it('overwrites the component options with the instance options', () => { - const Component = { - template: '
{{ foo() }}{{ bar() }}{{ baz() }}
', - methods: { - foo () { - return 'a' - }, - bar () { - return 'b' - } - } - } - const options = { - methods: { - bar () { - return 'B' - }, - baz () { - return 'C' - } - } - } - const wrapper = mount(Component, options) - expect(wrapper.text()).to.equal('aBC') - }) - it('handles inline components', () => { const ChildComponent = { render (h) { @@ -415,4 +362,18 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => { }) expect(wrapper.findAll(ChildComponent).length).to.equal(1) }) + + it('has correct own properties in options.components', () => { + const ChildComponent = { + template: '
' + } + const TestComponent = { + template: '
', + components: { + ChildComponent + } + } + const { vm } = mount(TestComponent) + expect(Object.keys(vm.$options.components)).to.contain('ChildComponent') + }) }) diff --git a/test/specs/mounting-options/methods.spec.js b/test/specs/mounting-options/methods.spec.js deleted file mode 100644 index 04524c1ee..000000000 --- a/test/specs/mounting-options/methods.spec.js +++ /dev/null @@ -1,25 +0,0 @@ -import { config } from '~vue/test-utils' -import { describeWithMountingMethods } from '~resources/utils' - -describeWithMountingMethods('options.methods', mountingMethod => { - it('prioritize mounting options over config', () => { - config.methods['val'] = () => 'methodFromConfig' - - const TestComponent = { - template: ` -
{{ val() }}
- ` - } - - const wrapper = mountingMethod(TestComponent, { - methods: { - val () { - return 'methodFromOptions' - } - } - }) - const HTML = - mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() - expect(HTML).to.contain('methodFromOptions') - }) -}) diff --git a/test/specs/wrapper/setComputed.spec.js b/test/specs/wrapper/setComputed.spec.js index 6744234e3..bc39528ca 100644 --- a/test/specs/wrapper/setComputed.spec.js +++ b/test/specs/wrapper/setComputed.spec.js @@ -58,7 +58,7 @@ describeWithShallowAndMount('setComputed', mountingMethod => { expect(wrapper.vm.b).to.equal(3) }) - it('works correctly with mapGetters', () => { + it.skip('works correctly with mapGetters', () => { const localVue = createLocalVue() localVue.use(Vuex) const store = new Vuex.Store({