From 6d006c631c501b5e0a999614654c754e0dc238a8 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Tue, 14 Jul 2020 18:04:48 +1000 Subject: [PATCH 1/4] docs: shallow and stubs --- src/guide/stubs-shallow-mount.md | 199 ++++++++++++++++++++++++++++++- 1 file changed, 198 insertions(+), 1 deletion(-) diff --git a/src/guide/stubs-shallow-mount.md b/src/guide/stubs-shallow-mount.md index d537033..042b098 100644 --- a/src/guide/stubs-shallow-mount.md +++ b/src/guide/stubs-shallow-mount.md @@ -1,3 +1,200 @@ # Stubs and Shallow Mount -Mostly `mount({ shallow: true })` and `global.stubs`. \ No newline at end of file +Vue Test Utils provides some features for *stubbing* components. A *stub* is where you replace an existing implementation of a custom component with a dummy component that doesn't do anything at all, which can simplify an otherwise complex test. Let's see an example. + +## Mocking with `global.stubs` + +A common example is when you would like to test something in a component that appers very high in the component hierarchy. + +In this example, we have an `` that renders a message, as well as a `FetchDataFromApi` component that makes an API call. + +```js +const FetchDataFromApi = { + name: 'FetchDataFromApi', + template: ` +
{{ result }}
+ `, + async mounted() { + const res = await axios.get('/api/info') + this.result = res.data + }, + data() { + return { + result: '' + } + } +} + +const App = { + components: { + FetchDataFromApi + }, + template: ` +
+

Welcome to Vue.js 3

+ +
+ ` +} +``` + + We do not want to make the API call in this particular test, we just want to assert the message is rendered. In this case, we could use the `stubs`, which appears in the `global` mounting option. + +```js {12} +test('stubs', () => { + const wrapper = mount(App, { + global: { + stubs: { + FetchDataFromApi: { + template: '' + } + } + } + }) + + console.log(wrapper.html()) //

Welcome to Vue.js 3

+ expect(wrapper.html()).toContain('Welcome to Vue.js 3') +}) +``` + +Notice that the template is showing `` where `` was? We replaced it with a stub - in this case, we provided our own implementation by passing in a `template`. + +You can also get a default stub, instead of providing your own: + +```js {9} +test('stubs', () => { + const wrapper = mount(App, { + global: { + stubs: { + FetchDataFromApi: true + } + } + }) + console.log(wrapper.html()) //

Welcome to Vue.js 3

+ expect(wrapper.html()).toContain('Welcome to Vue.js 3') +}) +``` + +This will stub out *all* the `` components in the entire render tree, regardless of what level they appear at. That's why it is in the `global` mounting option. + +## `shallow: true` or `shallowMount` + +Sometimes you might want to stub out *all* the custom components. For example you might have a component like this: + +```js +const ComplexComponent = { + components: { ComplexA, ComplexB, ComplexC }, + template: ` +
+

Welcome to Vue.js 3

+ + + +
+ ` +} +``` + +Imagine each of the `` does something complicated, and you are only interested in testing that the `

` is rendering the correct greeting. You could do something like: + +```js +const wrapper = mount(ComplexComponent, { + global: { + stubs: { + ComplexA: true, + ComplexB: true, + ComplexC: true, + } + } +}) +``` + +But that's a lot of boilerplate. VTU has a `shallow` mounting option that will automatically stub out all the child components: + +```js {5} +test('shallow', () => { + const wrapper = shallow(ComplexComponent, { + shallow: true + }) + console.log(wrapper.html()) //

Welcome to Vue.js 3

+}) +``` + +> TIP: If you used VTU V1, you may remember this as `shallowMount`. That method is still available, too - it's the same as writing `shallow: true`. + +## Default Slots and `shallow` + +Since `shallow` stubs out all the render function of any custom components, any `` components are not rendered when using `shallow`. While this is not a problem in most cases, there are some scenarios where this isn't ideal. Maybe you have a custom button component in your app: + +```js +const CustomButton = { + template: ` + + ` +} +``` + +And you might use it like this: + +```js +const App = { + props: ['authenticated'], + components: { CustomButton }, + template: ` +
+

Welcome!

+ +
+ Log out +
+
+ Log in +
+
+
+ ` +} +``` + +If you are using `shallow`, the `` will not be rendered, since the render function in `` is stubbed out. That means you won't be able to verify the correct text is rendered! For this use case, you can use `config.renderDefaultStub`, which will render the default ``, even when using `shallow`: + +```js {1,4,8} +import { config, mount } from '@vue/test-utils' + +beforeAll(() => { + config.renderStubDefaultSlot = true +}) + +afterAll(() => { + config.renderStubDefaultSlot = false +}) + +test('shallow with stubs', () => { + const wrapper = mount(AnotherApp, { + props: { + authenticated: true + }, + shallow: true + }) + + expect(wrapper.html()).toContain('Log out') +}) +``` + +Since this behavior is global, not on a `mount` by `mount` basis, you need to remember to enable/disable it before and after each test. + +If you prefer this behavior, you can enable this globally by importing `config` in your test setup file, and setting `renderStubDefaultSlot` to `true`. Unfortunately, due to technical limitations, this behavior is not extended to slots other than the default slot. + +## `mount`, `shallow` and `stubs`: which one and when? + +Tests that use `mount` will render the entire component hierarchy, which is closer to what the user will experiene in a real browser. Tests using `shallow` are focused on a specific component. As a rule of thumb, the more your tests resemble the way your software is used, the more confidence they can give you. `shallow` can be useful for testing a specific component in complete isolation. If you just have one or two components that are not relevant to your tests, consider using `mount` in combination with `stubs` instead of `shallow`. The more you stub, the less production-like your test becomes. + +Keep in mind that whether you are doing a full mount or a shallow render, good tests focus on inputs (`props` and user interaction, such as with `trigger`) and outputs (in the case of a component, the DOM elements that are rendered), not implementation details. So regardless of which mounting method you choose, keep these guidelines in mind. + +## Conclusion + +- use `global.stubs` to replace a component with a dummy one that does nothing to simplify your tests +- use `shallow: true` (or `shallowMount`) to stub out all custom components +- use `config.stubRenderDefaultSlot` to render the default `` for a stubbed component From b3ac78141706768ddf8fbb9a31859f8b16a85381 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Fri, 17 Jul 2020 20:38:46 +1000 Subject: [PATCH 2/4] docs: make guide on stubs more terse --- src/guide/stubs-shallow-mount.md | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/guide/stubs-shallow-mount.md b/src/guide/stubs-shallow-mount.md index 042b098..a1b5bf7 100644 --- a/src/guide/stubs-shallow-mount.md +++ b/src/guide/stubs-shallow-mount.md @@ -1,8 +1,8 @@ # Stubs and Shallow Mount -Vue Test Utils provides some features for *stubbing* components. A *stub* is where you replace an existing implementation of a custom component with a dummy component that doesn't do anything at all, which can simplify an otherwise complex test. Let's see an example. +Vue Test Utils provides some advanced features for *stubbing* components. A *stub* is where you replace an existing implementation of a custom component with a dummy component that doesn't do anything at all, which can simplify an otherwise complex test. Let's see an example. -## Mocking with `global.stubs` +## Stubbing a single child component A common example is when you would like to test something in a component that appers very high in the component hierarchy. @@ -77,7 +77,7 @@ test('stubs', () => { This will stub out *all* the `` components in the entire render tree, regardless of what level they appear at. That's why it is in the `global` mounting option. -## `shallow: true` or `shallowMount` +## Stubbing all children components Sometimes you might want to stub out *all* the custom components. For example you might have a component like this: @@ -113,7 +113,7 @@ But that's a lot of boilerplate. VTU has a `shallow` mounting option that will a ```js {5} test('shallow', () => { - const wrapper = shallow(ComplexComponent, { + const wrapper = monut(ComplexComponent, { shallow: true }) console.log(wrapper.html()) //

Welcome to Vue.js 3

@@ -124,7 +124,7 @@ test('shallow', () => { ## Default Slots and `shallow` -Since `shallow` stubs out all the render function of any custom components, any `` components are not rendered when using `shallow`. While this is not a problem in most cases, there are some scenarios where this isn't ideal. Maybe you have a custom button component in your app: +Since `shallow` stubs out all the content of a components, any `` won't get rendered when using `shallow`. While this is not a problem in most cases, there are some scenarios where this isn't ideal. ```js const CustomButton = { @@ -143,17 +143,10 @@ const App = { props: ['authenticated'], components: { CustomButton }, template: ` -
-

Welcome!

- -
- Log out -
-
- Log in -
-
-
+ +
Log out
+
Log in
+
` } ``` @@ -185,7 +178,7 @@ test('shallow with stubs', () => { Since this behavior is global, not on a `mount` by `mount` basis, you need to remember to enable/disable it before and after each test. -If you prefer this behavior, you can enable this globally by importing `config` in your test setup file, and setting `renderStubDefaultSlot` to `true`. Unfortunately, due to technical limitations, this behavior is not extended to slots other than the default slot. +:::: tip If you prefer this behavior, you can enable this globally by importing `config` in your test setup file, and setting `renderStubDefaultSlot` to `true`. Unfortunately, due to technical limitations, this behavior is not extended to slots other than the default slot. ## `mount`, `shallow` and `stubs`: which one and when? From 133011b8be5505a6a1b59658fdcf87bc43a186e7 Mon Sep 17 00:00:00 2001 From: Lachlan Date: Fri, 17 Jul 2020 21:42:11 +1000 Subject: [PATCH 3/4] Update src/guide/stubs-shallow-mount.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: AdriĆ  Fontcuberta --- src/guide/stubs-shallow-mount.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/guide/stubs-shallow-mount.md b/src/guide/stubs-shallow-mount.md index a1b5bf7..7c3c5b3 100644 --- a/src/guide/stubs-shallow-mount.md +++ b/src/guide/stubs-shallow-mount.md @@ -182,7 +182,11 @@ Since this behavior is global, not on a `mount` by `mount` basis, you need to re ## `mount`, `shallow` and `stubs`: which one and when? -Tests that use `mount` will render the entire component hierarchy, which is closer to what the user will experiene in a real browser. Tests using `shallow` are focused on a specific component. As a rule of thumb, the more your tests resemble the way your software is used, the more confidence they can give you. `shallow` can be useful for testing a specific component in complete isolation. If you just have one or two components that are not relevant to your tests, consider using `mount` in combination with `stubs` instead of `shallow`. The more you stub, the less production-like your test becomes. +As a rule of thumb, the more your tests resemble the way your software is used, the more confidence they can give you. + +Tests that use `mount` will render the entire component hierarchy, which is closer to what the user will experience in a real browser. + +On the other hand, tests using `shallow` are focused on a specific component. `shallow` can be useful for testing advanced components in complete isolation. If you just have one or two components that are not relevant to your tests, consider using `mount` in combination with `stubs` instead of `shallow`. The more you stub, the less production-like your test becomes. Keep in mind that whether you are doing a full mount or a shallow render, good tests focus on inputs (`props` and user interaction, such as with `trigger`) and outputs (in the case of a component, the DOM elements that are rendered), not implementation details. So regardless of which mounting method you choose, keep these guidelines in mind. From f37ea4265ae07d50a63d873321af47bb0748a64e Mon Sep 17 00:00:00 2001 From: Lachlan Date: Fri, 17 Jul 2020 21:43:04 +1000 Subject: [PATCH 4/4] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: AdriĆ  Fontcuberta --- src/guide/stubs-shallow-mount.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/guide/stubs-shallow-mount.md b/src/guide/stubs-shallow-mount.md index 7c3c5b3..a4a96d0 100644 --- a/src/guide/stubs-shallow-mount.md +++ b/src/guide/stubs-shallow-mount.md @@ -188,10 +188,12 @@ Tests that use `mount` will render the entire component hierarchy, which is clos On the other hand, tests using `shallow` are focused on a specific component. `shallow` can be useful for testing advanced components in complete isolation. If you just have one or two components that are not relevant to your tests, consider using `mount` in combination with `stubs` instead of `shallow`. The more you stub, the less production-like your test becomes. -Keep in mind that whether you are doing a full mount or a shallow render, good tests focus on inputs (`props` and user interaction, such as with `trigger`) and outputs (in the case of a component, the DOM elements that are rendered), not implementation details. So regardless of which mounting method you choose, keep these guidelines in mind. +Keep in mind that whether you are doing a full mount or a shallow render, good tests focus on inputs (`props` and user interaction, such as with `trigger`) and outputs (the DOM elements that are rendered, and events), not implementation details. + +So regardless of which mounting method you choose, we suggest keeping these guidelines in mind. ## Conclusion -- use `global.stubs` to replace a component with a dummy one that does nothing to simplify your tests -- use `shallow: true` (or `shallowMount`) to stub out all custom components +- use `global.stubs` to replace a component with a dummy one to simplify your tests +- use `shallow: true` (or `shallowMount`) to stub out all child components - use `config.stubRenderDefaultSlot` to render the default `` for a stubbed component