From f689640cfc9ea9c335716a3b278e28be73607a54 Mon Sep 17 00:00:00 2001 From: Edd Yerburgh Date: Thu, 3 May 2018 22:26:12 +0200 Subject: [PATCH] refactor: rename shallow to shallowMount (#576) --- packages/test-utils/src/index.js | 9 +- packages/test-utils/src/shallow-mount.js | 36 ++++ test/setup/mocha.setup.js | 3 + test/specs/components/TransitionStub.spec.js | 2 +- test/specs/shallow-mount.spec.js | 206 +++++++++++++++++++ 5 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 packages/test-utils/src/shallow-mount.js create mode 100644 test/specs/shallow-mount.spec.js diff --git a/packages/test-utils/src/index.js b/packages/test-utils/src/index.js index 3eb71602b..b95abbce9 100644 --- a/packages/test-utils/src/index.js +++ b/packages/test-utils/src/index.js @@ -1,16 +1,23 @@ -import shallow from './shallow' +import shallowMount from './shallow-mount' import mount from './mount' import createLocalVue from './create-local-vue' import TransitionStub from './components/TransitionStub' import TransitionGroupStub from './components/TransitionGroupStub' import RouterLinkStub from './components/RouterLinkStub' import config from './config' +import { warn } from 'shared/util' + +function shallow (component, options) { + warn('shallow has been renamed to shallowMount and will be deprecated in 1.0.0') + return shallowMount(component, options) +} export default { createLocalVue, config, mount, shallow, + shallowMount, TransitionStub, TransitionGroupStub, RouterLinkStub diff --git a/packages/test-utils/src/shallow-mount.js b/packages/test-utils/src/shallow-mount.js new file mode 100644 index 000000000..55d878bad --- /dev/null +++ b/packages/test-utils/src/shallow-mount.js @@ -0,0 +1,36 @@ +// @flow + +import './warn-if-no-window' +import Vue from 'vue' +import mount from './mount' +import type VueWrapper from './vue-wrapper' +import { + createComponentStubsForAll, + createStubs +} from 'shared/stub-components' +import { camelize, + capitalize, + hyphenate +} from 'shared/util' + +export default function shallowMount ( + component: Component, + options: Options = {} +): VueWrapper { + const vue = options.localVue || Vue + + // remove any recursive components added to the constructor + // in vm._init from previous tests + if (component.name && component.components) { + delete component.components[capitalize(camelize(component.name))] + delete component.components[hyphenate(component.name)] + } + + return mount(component, { + ...options, + components: { + ...createStubs(vue.options.components), + ...createComponentStubsForAll(component) + } + }) +} diff --git a/test/setup/mocha.setup.js b/test/setup/mocha.setup.js index eecf41117..8a7e69fb7 100644 --- a/test/setup/mocha.setup.js +++ b/test/setup/mocha.setup.js @@ -4,6 +4,9 @@ if (process.env.TEST_ENV !== 'node') { const chai = require('chai') const sinon = require('sinon') +const sinonChai = require('sinon-chai') + +chai.use(sinonChai) global.expect = chai.expect global.sinon = sinon diff --git a/test/specs/components/TransitionStub.spec.js b/test/specs/components/TransitionStub.spec.js index 99d0c41db..602c8207d 100644 --- a/test/specs/components/TransitionStub.spec.js +++ b/test/specs/components/TransitionStub.spec.js @@ -54,7 +54,7 @@ describeWithShallowAndMount('TransitionStub', (mountingMethod) => { 'transition': TransitionStub } }) - expect(error.args[0][0]).to.equal(msg) + expect(error).calledWith(msg) error.restore() }) diff --git a/test/specs/shallow-mount.spec.js b/test/specs/shallow-mount.spec.js new file mode 100644 index 000000000..80f4310d7 --- /dev/null +++ b/test/specs/shallow-mount.spec.js @@ -0,0 +1,206 @@ +import { compileToFunctions } from 'vue-template-compiler' +import Vue from 'vue' +import { mount, shallowMount } from '~vue/test-utils' +import Component from '~resources/components/component.vue' +import ComponentWithChild from '~resources/components/component-with-child.vue' +import ComponentWithNestedChildren from '~resources/components/component-with-nested-children.vue' +import ComponentWithLifecycleHooks from '~resources/components/component-with-lifecycle-hooks.vue' +import ComponentWithoutName from '~resources/components/component-without-name.vue' +import ComponentAsAClassWithChild from '~resources/components/component-as-a-class-with-child.vue' +import RecursiveComponent from '~resources/components/recursive-component.vue' +import { vueVersion, describeIf } from '~resources/utils' + +describeIf(process.env.TEST_ENV !== 'node', + 'shallow', () => { + let info + + beforeEach(() => { + info = sinon.stub(console, 'info') + }) + + afterEach(() => { + info.restore() + }) + + it('returns new VueWrapper of Vue localVue if no options are passed', () => { + const compiled = compileToFunctions('
') + const wrapper = shallowMount(compiled) + expect(wrapper.isVueComponent).to.equal(true) + expect(wrapper.vm).to.be.an('object') + }) + + it('returns new VueWrapper of Vue localVue with all children stubbed', () => { + const wrapper = shallowMount(ComponentWithNestedChildren) + expect(wrapper.isVueComponent).to.equal(true) + expect(wrapper.findAll(Component).length).to.equal(0) + expect(wrapper.findAll(ComponentWithChild).length).to.equal(1) + }) + + it('returns new VueWrapper of Vue localVue with all children stubbed', () => { + const wrapper = shallowMount(ComponentWithNestedChildren) + expect(wrapper.isVueComponent).to.equal(true) + expect(wrapper.findAll(Component).length).to.equal(0) + expect(wrapper.findAll(ComponentWithChild).length).to.equal(1) + }) + + it('does not modify component directly', () => { + const wrapper = shallowMount(ComponentWithNestedChildren) + expect(wrapper.findAll(Component).length).to.equal(0) + const mountedWrapper = mount(ComponentWithNestedChildren) + expect(mountedWrapper.findAll(Component).length).to.equal(1) + }) + + it('stubs globally registered components when options.localVue is provided', () => { + const localVue = Vue.extend() + localVue.component('registered-component', ComponentWithLifecycleHooks) + const Component = { + render: h => h('registered-component') + } + shallowMount(Component, { localVue }) + mount(Component, { localVue }) + + expect(info.callCount).to.equal(4) + }) + + it('stubs globally registered components', () => { + Vue.component('registered-component', ComponentWithLifecycleHooks) + const Component = { + render: h => h('registered-component') + } + shallowMount(Component) + mount(Component) + + expect(info.callCount).to.equal(4) + }) + + it('does not call stubbed children lifecycle hooks', () => { + shallowMount(ComponentWithNestedChildren) + expect(info.called).to.equal(false) + }) + + it('stubs extended components', () => { + const ComponentWithPTag = { + template: `

` + } + const BaseComponent = { + template: ` +
+ +
+ `, + components: { + ComponentWithPTag + } + } + + const TestComponent = { + extends: BaseComponent + } + + const wrapper = shallowMount(TestComponent) + expect(wrapper.find(ComponentWithPTag).exists()).to.equal(true) + expect(wrapper.find('p').exists()).to.equal(false) + }) + + it('stubs nested extended components', () => { + const ComponentWithPTag = { + template: `

` + } + const BaseComponent = { + template: ` +
+ +
+ `, + components: { + ComponentWithPTag + } + } + + const ExtendedBaseComponent = { + extends: BaseComponent + } + + const TestComponent = { + extends: ExtendedBaseComponent + } + + const wrapper = shallowMount(TestComponent) + expect(wrapper.find(ComponentWithPTag).exists()).to.equal(true) + expect(wrapper.find('p').exists()).to.equal(false) + }) + + it('stubs Vue class component children', () => { + if (vueVersion < 2.3) { + return + } + const wrapper = shallowMount(ComponentAsAClassWithChild) + expect(wrapper.find(Component).exists()).to.equal(true) + expect(wrapper.findAll('div').length).to.equal(1) + }) + + it('works correctly with find, contains, findAll, and is on unnamed components', () => { + const TestComponent = { + template: ` +
+ +
+ `, + components: { + ComponentWithoutName + } + } + const wrapper = shallowMount(TestComponent) + expect(wrapper.contains(ComponentWithoutName)).to.equal(true) + expect(wrapper.find(ComponentWithoutName).exists()).to.equal(true) + expect(wrapper.findAll(ComponentWithoutName).length).to.equal(1) + }) + + it('works correctly with find, contains, findAll, and is on named components', () => { + const TestComponent = { + template: ` +
+ +
+ `, + components: { + AComponent: Component + } + } + const wrapper = shallowMount(TestComponent) + expect(wrapper.contains(Component)).to.equal(true) + expect(wrapper.find(Component).exists()).to.equal(true) + expect(wrapper.findAll(Component).length).to.equal(1) + }) + + it('works correctly with find on recursive components', () => { + // this is for a bug that I've been unable to replicate. + // Sometimes components mutate their components, in this line— + RecursiveComponent.components = { + RecursiveComponent: { render: h => h('div') } + } + + expect(shallowMount(RecursiveComponent, { + propsData: { + items: ['', ''] + } + }).findAll(RecursiveComponent).length).to.equal(2) + RecursiveComponent.components = { + 'recursive-component': { render: h => h('div') } + } + expect(shallowMount(RecursiveComponent, { + propsData: { + items: ['', ''] + } + }).findAll(RecursiveComponent).length).to.equal(2) + }) + + it('throws an error when the component fails to mount', () => { + expect(() => shallowMount({ + template: '
', + mounted: function () { + throw (new Error('Error')) + } + })).to.throw() + }) + })