From 6d5aefbb77435ec06592ac94f32ca98c43f9c0b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= Date: Mon, 19 Aug 2019 10:55:05 +0200 Subject: [PATCH 1/8] docs: update contributors (#90) --- README.md | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f01e3547..5c1cbc72 100644 --- a/README.md +++ b/README.md @@ -138,17 +138,20 @@ and bundled with Vue Testing Library. ## Contributors -[![dfcook](https://avatars0.githubusercontent.com/u/10348212?v=3&s=170)](https://github.com/dfcook) -[![afontcu](https://avatars3.githubusercontent.com/u/9197791?s=170&v=3)](https://github.com/afontcu) -[![eunjae-lee](https://avatars0.githubusercontent.com/u/499898?v=3&s=170)](https://github.com/eunjae-lee) -[![tim-maguire](https://avatars0.githubusercontent.com/u/29452317?v=3&s=170)](https://github.com/tim-maguire) -[![samdelacruz](https://avatars0.githubusercontent.com/u/2040007?v=3&s=170)](https://github.com/samdelacruz) -[![ankitsinghaniyaz](https://avatars0.githubusercontent.com/u/11331989?v=3&s=170)](https://github.com/ankitsinghaniyaz) -[![lindgr3n](https://avatars0.githubusercontent.com/u/24882614?v=3&s=170)](https://github.com/lindgr3n) -[![kentcdodds](https://avatars0.githubusercontent.com/u/1500684?v=3&s=170)](https://github.com/kentcdodds) -[![brennj](https://avatars2.githubusercontent.com/u/29227924?v=3&s=170)](https://github.com/brennj) -[![makeupsomething](https://avatars2.githubusercontent.com/u/7676733?v=3&s=170)](https://github.com/makeupsomething) -[![mb200](https://avatars2.githubusercontent.com/u/22549525?v=3&s=170)](https://github.com/mb200) +[![dfcook](https://avatars0.githubusercontent.com/u/10348212?v=3&s=120)](https://github.com/dfcook) +[![afontcu](https://avatars3.githubusercontent.com/u/9197791?v=3&s=120)](https://github.com/afontcu) +[![eunjae-lee](https://avatars0.githubusercontent.com/u/499898?v=3&s=120)](https://github.com/eunjae-lee) +[![tim-maguire](https://avatars0.githubusercontent.com/u/29452317?v=3&s=120)](https://github.com/tim-maguire) +[![samdelacruz](https://avatars0.githubusercontent.com/u/2040007?v=3&s=120)](https://github.com/samdelacruz) +[![ankitsinghaniyaz](https://avatars0.githubusercontent.com/u/11331989?v=3&s=120)](https://github.com/ankitsinghaniyaz) +[![lindgr3n](https://avatars0.githubusercontent.com/u/24882614?v=3&s=120)](https://github.com/lindgr3n) +[![kentcdodds](https://avatars0.githubusercontent.com/u/1500684?v=3&s=120)](https://github.com/kentcdodds) +[![brennj](https://avatars2.githubusercontent.com/u/29227924?v=3&s=120)](https://github.com/brennj) +[![makeupsomething](https://avatars2.githubusercontent.com/u/7676733?v=3&s=120)](https://github.com/makeupsomething) +[![mb200](https://avatars2.githubusercontent.com/u/22549525?v=3&s=120)](https://github.com/mb200) +[![Oluwasetemi](https://avatars2.githubusercontent.com/u/10030028?v=3&s=120)](https://github.com/Oluwasetemi) +[![cimbul](https://avatars2.githubusercontent.com/u/927923?v=3&s=120)](https://github.com/cimbul) +[![alexkrolick](https://avatars2.githubusercontent.com/u/1571667?v=3&s=120)](https://github.com/alexkrolick) [build-badge]: https://travis-ci.org/testing-library/vue-testing-library.svg?branch=master From 993c87f8742fcaaaa942c8ae04b63f503f4e5824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= Date: Mon, 19 Aug 2019 23:18:15 +0200 Subject: [PATCH 2/8] docs: improve wording and structure (#91) * Fix broken links * Improve wording * Fix TOC placement * Consistency is key --- README.md | 30 +++++++++----- .../__snapshots__/axios-mock.js.snap | 9 ----- src/__tests__/auto-cleanup-skip.js | 4 +- src/__tests__/auto-cleanup.js | 5 +-- src/__tests__/axios-mock.js | 13 ++++-- src/__tests__/components/Translations.vue | 19 +++++++++ src/__tests__/debug.js | 2 +- src/__tests__/disappearance.js | 5 ++- src/__tests__/form.js | 13 +++--- src/__tests__/functional.js | 4 +- src/__tests__/select.js | 10 ++--- src/__tests__/simple-button.js | 10 ++--- src/__tests__/stopwatch.js | 34 ++++++++-------- src/__tests__/update-props.js | 6 ++- src/__tests__/vue-i18n.js | 40 +++++++++++++++++++ 15 files changed, 134 insertions(+), 70 deletions(-) delete mode 100644 src/__tests__/__snapshots__/axios-mock.js.snap create mode 100644 src/__tests__/components/Translations.vue create mode 100644 src/__tests__/vue-i18n.js diff --git a/README.md b/README.md index 5c1cbc72..d83512d9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@

Vue Testing Library

+
+ -[**Read the Docs**][docs] | [Edit the docs][docs-edit] +[**Read the docs**][docs] | [Edit the docs][docs-edit]
@@ -36,6 +38,9 @@

Table of Contents

+ + + - [Installation](#installation) - [A simple example](#a-simple-example) - [More examples](#more-examples) @@ -44,9 +49,11 @@ - [License](#license) - [Contributors](#contributors) + + ## Installation -This module is distributed via npm and should be installed as one of your +This module is distributed via `npm` and should be installed as one of your project's `devDependencies`: ``` @@ -57,7 +64,7 @@ This library has `peerDependencies` listings for `Vue` and `vue-template-compiler`. You may also be interested in installing `jest-dom` so you can use -[the custom Jest matchers](https://github.com/gnapse/jest-dom#readme). +[the custom Jest matchers](https://github.com/testing-library/jest-dom#readme). ## A simple example @@ -90,7 +97,7 @@ import {render, fireEvent} from '@testing-library/vue' import TestComponent from './TestComponent.vue' test('increments value on click', async () => { - // The render method returns a collection of utilities to query your component. + // The render method returns a collection of utilities to query the component. const {getByText} = render(TestComponent) // getByText returns the first matching node for the provided text, and @@ -100,7 +107,7 @@ test('increments value on click', async () => { // `button` is the actual DOM element. const button = getByText('increment') - // Dispatch a native click event. + // Dispatch a couple of native click events. await fireEvent.click(button) await fireEvent.click(button) @@ -124,12 +131,12 @@ Feel free to contribute with more examples! ## Docs -[**Read the Docs**][docs] | [Edit the docs][docs-edit] +[**Read the docs**][docs] | [Edit the docs][docs-edit] ## Typings The TypeScript type definitions are in the -[DefinitelyTyped repo](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/testing-library__vue) +[DefinitelyTyped repo][types] and bundled with Vue Testing Library. ## License @@ -166,13 +173,14 @@ and bundled with Vue Testing Library. [npm]: https://badge.fury.io/js/%40testing-library%2Fvue [license-badge]: https://img.shields.io/github/license/testing-library/vue-testing-library.svg [license]: https://github.com/testing-library/vue-testing-library/blob/master/LICENSE +[types]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/testing-library__vue [docs]: https://testing-library.com/vue [docs-edit]: https://github.com/testing-library/testing-library-docs -[test-directory]: https://github.com/testing-library/vue-testing-library/tree/master/tests/__tests__ -[vuex-example]: https://github.com/testing-library/vue-testing-library/tree/master/tests/__tests__/vuex.js -[vue-router-example]: https://github.com/testing-library/vue-testing-library/tree/master/tests/__tests__/vue-router.js -[vee-validate-example]: https://github.com/testing-library/vue-testing-library/tree/master/tests/__tests__/validate-plugin.js +[test-directory]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__ +[vuex-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/vuex.js +[vue-router-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/vue-router.js +[vee-validate-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/validate-plugin.js [vue-i18n-example]: https://github.com/testing-library/vue-testing-library/blob/master/tests/__tests__/vueI18n.js diff --git a/src/__tests__/__snapshots__/axios-mock.js.snap b/src/__tests__/__snapshots__/axios-mock.js.snap deleted file mode 100644 index 8083a688..00000000 --- a/src/__tests__/__snapshots__/axios-mock.js.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`makes an API call and displays the greeting when load-greeting is clicked 1`] = ` -
- hello there -
-`; diff --git a/src/__tests__/auto-cleanup-skip.js b/src/__tests__/auto-cleanup-skip.js index 5423ef52..bcd4595a 100644 --- a/src/__tests__/auto-cleanup-skip.js +++ b/src/__tests__/auto-cleanup-skip.js @@ -5,8 +5,8 @@ beforeAll(async () => { render = vtl.render }) -// This one verifies that if VTL_SKIP_AUTO_CLEANUP is set -// then we DON'T auto-wire up the afterEach for folks +// This test verifies that if VTL_SKIP_AUTO_CLEANUP is set then we DON'T +// auto-wire up the afterEach cleanup for folks. test('first test render a vue component', () => { render({ template: `

Hello World

`, diff --git a/src/__tests__/auto-cleanup.js b/src/__tests__/auto-cleanup.js index 37fa8a29..cf3ebbdf 100644 --- a/src/__tests__/auto-cleanup.js +++ b/src/__tests__/auto-cleanup.js @@ -1,9 +1,8 @@ import {render} from '@testing-library/vue' import '@testing-library/jest-dom/extend-expect' -// This just verifies that by importing VTL in an -// environment which supports afterEach (like jest) -// we'll get automatic cleanup between tests. +// This just verifies that by importing VTL in an environment which supports +// afterEach (like jest) we'll get automatic cleanup between tests. test('render the first component', () => { render({ template: `

Hello World

`, diff --git a/src/__tests__/axios-mock.js b/src/__tests__/axios-mock.js index 93eff0f3..5687692e 100644 --- a/src/__tests__/axios-mock.js +++ b/src/__tests__/axios-mock.js @@ -1,9 +1,9 @@ +import '@testing-library/jest-dom/extend-expect' import axiosMock from 'axios' import {render, fireEvent} from '@testing-library/vue' import Component from './components/Fetch.vue' -import '@testing-library/jest-dom/extend-expect' -test('makes an API call and displays the greeting when load-greeting is clicked', async () => { +test('mocks an API call when load-greeting is clicked', async () => { axiosMock.get.mockImplementationOnce(() => Promise.resolve({ data: {greeting: 'hello there'}, @@ -12,7 +12,6 @@ test('makes an API call and displays the greeting when load-greeting is clicked' const {html, getByText} = render(Component, {props: {url: '/greeting'}}) - // Act await fireEvent.click(getByText('Fetch')) expect(axiosMock.get).toHaveBeenCalledTimes(1) @@ -23,5 +22,11 @@ test('makes an API call and displays the greeting when load-greeting is clicked' // that Snapshot Testing should not be treated as a replacement for regular // tests. // More about the topic: https://twitter.com/searls/status/919594505938112512 - expect(html()).toMatchSnapshot() + expect(html()).toMatchInlineSnapshot(` +
+ hello there +
+ `) }) diff --git a/src/__tests__/components/Translations.vue b/src/__tests__/components/Translations.vue new file mode 100644 index 00000000..0510b5d8 --- /dev/null +++ b/src/__tests__/components/Translations.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/__tests__/debug.js b/src/__tests__/debug.js index f3a33c56..89df1bb3 100644 --- a/src/__tests__/debug.js +++ b/src/__tests__/debug.js @@ -34,7 +34,7 @@ test('debug pretty prints the provided parameter', () => { expect.stringContaining('Lorem ipsum dolor sit amet'), ) - // Notice the 'not' particle + // Notice the 'not' particle. expect(console.log).not.toHaveBeenCalledWith( expect.stringContaining('Hello World'), ) diff --git a/src/__tests__/disappearance.js b/src/__tests__/disappearance.js index 228afe94..66ca8ed5 100644 --- a/src/__tests__/disappearance.js +++ b/src/__tests__/disappearance.js @@ -9,7 +9,8 @@ test('waits for the data to be loaded', async () => { getByText('Loading...') expect(queryByText(/Loaded this message/)).not.toBeInTheDocument() - // Line reads as follows: "Wait until element with text 'Loading...' is gone." + // Following line reads as follows: + // "Wait until element with text 'Loading...' is gone." await waitForElementToBeRemoved(() => queryByText('Loading...')) // It is equivalent to: // @@ -17,7 +18,7 @@ test('waits for the data to be loaded', async () => { // expect(queryByText('Loading...')).not.toBeInTheDocument() // }) // - // `wait()` waits until the callback function passes or times out. + // because `wait()` waits until the callback function passes or times out. // After 'Loading...' is gone, we can assert that fetched data is rendered. expect(queryByTestId('message')).toHaveTextContent(/Hello World/) diff --git a/src/__tests__/form.js b/src/__tests__/form.js index 2e984a9c..4d26da2f 100644 --- a/src/__tests__/form.js +++ b/src/__tests__/form.js @@ -24,7 +24,7 @@ test('Review form submits', async () => { const submitButton = getByText('Submit') - // Initially the submit button should be disabled + // Initially the submit button should be disabled. expect(submitButton).toBeDisabled() const titleInput = getByLabelText(/title of the movie/i) @@ -33,7 +33,7 @@ test('Review form submits', async () => { const reviewTextarea = getByPlaceholderText('Write an awesome review') await fireEvent.update(reviewTextarea, fakeReview.review) - // Rating Radio buttons + // Rating Radio buttons. const initiallySelectedInput = getByLabelText('Awful') const ratingSelect = getByLabelText('Wonderful') @@ -45,23 +45,20 @@ test('Review form submits', async () => { expect(ratingSelect.checked).toBe(true) expect(initiallySelectedInput.checked).toBe(false) - // Get the Input element by its implicit ARIA role + // Get the Input element by its implicit ARIA role. const recommendInput = getByRole('checkbox') expect(recommendInput.checked).toBe(false) await fireEvent.update(recommendInput) expect(recommendInput.checked).toBe(true) - // NOTE: in jsdom, it's not possible to trigger a form submission - // by clicking on the submit button. This is really unfortunate. - // So the next best thing is to fireEvent a submit on the form itself - // then ensure that there's a submit button + // Make sure the submit button is enabled. expect(submitButton).toBeEnabled() expect(submitButton).toHaveAttribute('type', 'submit') await fireEvent.click(submitButton) - // Assert event has been emitted + // Assert the right event has been emitted. expect(emitted()).toHaveProperty('submit') expect(emitted().submit[0][0]).toMatchObject(fakeReview) }) diff --git a/src/__tests__/functional.js b/src/__tests__/functional.js index 033677b1..06a58d41 100644 --- a/src/__tests__/functional.js +++ b/src/__tests__/functional.js @@ -8,13 +8,13 @@ const Functional = { }, } -test('renders functional comp', () => { +test('renders functional component', () => { const {getByText} = render(Functional) getByText('Hi!') }) -test('renders functional SFC comp', () => { +test('renders functional SFC component', () => { const {getByText} = render(FunctionalSFC) getByText('Hi!') diff --git a/src/__tests__/select.js b/src/__tests__/select.js index 437488a8..f83a8512 100644 --- a/src/__tests__/select.js +++ b/src/__tests__/select.js @@ -2,25 +2,25 @@ import {render, fireEvent} from '@testing-library/vue' import '@testing-library/jest-dom/extend-expect' import Select from './components/Select' -// In this test file we showcase several ways to interact with a Select element +// In this test file we showcase several ways to interact with a Select element. test('Select component', async () => { let optionElement const {getByDisplayValue, getByText} = render(Select) - // Get the Select element by using the initially displayed value + // Get the Select element by using the initially displayed value. const select = getByDisplayValue('Tyrannosaurus') expect(select.value).toBe('dino1') - // Update it by manually sending a valid option value + // Update it by manually sending a valid option value. await fireEvent.update(select, 'dino2') expect(select.value).toBe('dino2') - // We can trigger an update event by directly getting the + // ...even if option is within an . optionElement = getByText('Diplodocus') await fireEvent.update(optionElement) expect(select.value).toBe('dino4') diff --git a/src/__tests__/simple-button.js b/src/__tests__/simple-button.js index f02299b9..e8216dfd 100644 --- a/src/__tests__/simple-button.js +++ b/src/__tests__/simple-button.js @@ -5,28 +5,28 @@ import '@testing-library/jest-dom/extend-expect' test('renders button with text', () => { const text = "Click me; I'm sick" - // Set the prop value by using the second argument of `render()` + // Set the prop value by using the second argument of `render()`. const {getByRole} = render(Button, { props: {text}, }) - // Get the only element with a 'button' role + // Get the only element with a 'button' role. const button = getByRole('button') expect(button).toHaveTextContent(text) }) -test('click event is emitted when button is clicked', async () => { +test('emits click event when button is clicked', async () => { const text = 'Click me' const {getByRole, emitted} = render(Button, { props: {text}, }) - // Send a click event + // Send a click event. await fireEvent.click(getByRole('button')) // Expect that the event emitted a "click" event. We should test for emitted - // events has they are part of the public API of the component + // events has they are part of the public API of the component. expect(emitted()).toHaveProperty('click') }) diff --git a/src/__tests__/stopwatch.js b/src/__tests__/stopwatch.js index 3eba0c94..f57a68f1 100644 --- a/src/__tests__/stopwatch.js +++ b/src/__tests__/stopwatch.js @@ -1,22 +1,6 @@ +import '@testing-library/jest-dom/extend-expect' import {render, wait, fireEvent} from '@testing-library/vue' import StopWatch from './components/StopWatch.vue' -import '@testing-library/jest-dom/extend-expect' - -test('unmounts a component', async () => { - jest.spyOn(console, 'error').mockImplementation(() => {}) - - const {unmount, isUnmounted, getByText} = render(StopWatch) - await fireEvent.click(getByText('Start')) - - // Destroys a Vue component instance. - unmount() - - expect(isUnmounted()).toBe(true) - - await wait() - - expect(console.error).not.toHaveBeenCalled() -}) test('updates component state', async () => { const {getByTestId, getByText} = render(StopWatch) @@ -42,3 +26,19 @@ test('updates component state', async () => { // content has changed. expect(elapsedTime).not.toHaveTextContent('0ms') }) + +test('unmounts a component', async () => { + jest.spyOn(console, 'error').mockImplementation(() => {}) + + const {unmount, isUnmounted, getByText} = render(StopWatch) + await fireEvent.click(getByText('Start')) + + // Destroys a Vue component instance. + unmount() + + expect(isUnmounted()).toBe(true) + + await wait() + + expect(console.error).not.toHaveBeenCalled() +}) diff --git a/src/__tests__/update-props.js b/src/__tests__/update-props.js index 5bc2728c..19f13056 100644 --- a/src/__tests__/update-props.js +++ b/src/__tests__/update-props.js @@ -1,7 +1,11 @@ +import '@testing-library/jest-dom/extend-expect' import {render} from '@testing-library/vue' import NumberDisplay from './components/NumberDisplay.vue' -import '@testing-library/jest-dom/extend-expect' +// It'd probably be better if you test the component that's doing the prop +// updating to ensure that the props are being updated correctly. +// That said, if you'd prefer to update the props of a rendered component, this +// function can be used to update props of the rendered component. test('calling render with the same component but different props does not remount', async () => { const {getByTestId, updateProps} = render(NumberDisplay, { props: {number: 1}, diff --git a/src/__tests__/vue-i18n.js b/src/__tests__/vue-i18n.js new file mode 100644 index 00000000..70ab8f21 --- /dev/null +++ b/src/__tests__/vue-i18n.js @@ -0,0 +1,40 @@ +import '@testing-library/jest-dom/extend-expect' +import {render, fireEvent} from '@testing-library/vue' +import Vuei18n from 'vue-i18n' +import Translations from './components/Translations' + +const messages = { + en: { + Hello: 'Hello', + }, + ja: { + Hello: 'こんにちは', + }, +} + +test('renders translations', async () => { + const {queryByText, getByText} = render(Translations, {}, vue => { + // Let's register and configure Vuei18n normally + vue.use(Vuei18n) + + const i18n = new Vuei18n({ + locale: 'en', + fallbackLocale: 'en', + messages, + }) + + // Notice how we return an object from the callback function. It will be + // merged as an additional option on the created Vue instance. + return { + i18n, + } + }) + + expect(getByText('Hello')).toBeInTheDocument() + + await fireEvent.click(getByText('Japanese')) + + expect(getByText('こんにちは')).toBeInTheDocument() + + expect(queryByText('Hello')).toBeNull() +}) From 7ff3f92558d17e65f8d8e3e6bd9ad34b823c4d73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2019 21:01:53 +0100 Subject: [PATCH 3/8] Bump eslint-utils from 1.4.0 to 1.4.2 (#93) Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.4.0 to 1.4.2. - [Release notes](https://github.com/mysticatea/eslint-utils/releases) - [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.4.0...v1.4.2) Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0949b841..db128a05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4399,9 +4399,9 @@ } }, "eslint-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz", - "integrity": "sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", + "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", "dev": true, "requires": { "eslint-visitor-keys": "^1.0.0" From 66e591325d4f1a42d7701efd51da0f093db2093b Mon Sep 17 00:00:00 2001 From: Eduard <25011566+edufarre@users.noreply.github.com> Date: Tue, 27 Aug 2019 16:37:15 +0200 Subject: [PATCH 4/8] docs: fix vue-i18n-example README link (#94) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d83512d9..7261632a 100644 --- a/README.md +++ b/README.md @@ -182,5 +182,5 @@ and bundled with Vue Testing Library. [vuex-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/vuex.js [vue-router-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/vue-router.js [vee-validate-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/validate-plugin.js -[vue-i18n-example]: https://github.com/testing-library/vue-testing-library/blob/master/tests/__tests__/vueI18n.js +[vue-i18n-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/vueI18n.js From abc572b433ce4f2bb208e792ca5203b15a752f2a Mon Sep 17 00:00:00 2001 From: Eduard <25011566+edufarre@users.noreply.github.com> Date: Sat, 31 Aug 2019 10:34:11 +0200 Subject: [PATCH 5/8] docs: Add visibility example (#95) * Create collapsible component * Create collapsed elements visibility test * Add why we can use getByText explanation --- src/__tests__/components/Collapsible.vue | 23 +++++++++++++++++++ src/__tests__/visibility.js | 28 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/__tests__/components/Collapsible.vue create mode 100644 src/__tests__/visibility.js diff --git a/src/__tests__/components/Collapsible.vue b/src/__tests__/components/Collapsible.vue new file mode 100644 index 00000000..33766853 --- /dev/null +++ b/src/__tests__/components/Collapsible.vue @@ -0,0 +1,23 @@ + + + diff --git a/src/__tests__/visibility.js b/src/__tests__/visibility.js new file mode 100644 index 00000000..322c11eb --- /dev/null +++ b/src/__tests__/visibility.js @@ -0,0 +1,28 @@ +import {render, fireEvent} from '@testing-library/vue' +import '@testing-library/jest-dom/extend-expect' +import Collapsible from './components/Collapsible' + +// Using the query `getByText` here is completely right because +// we use `v-show` in the component, which means that the element +// will be rendered but not visible, whereas if we use `v-if` instead +// we should use the `queryByText` and expect it to be `null` because +// the element won't be rendered +test('Collapsible component', async () => { + const {getByText} = render(Collapsible) + + // Check that text element is not initially visible. + expect(getByText('Text')).not.toBeVisible() + + // Click button in order to display the collapsed text element + const button = getByText('Click me') + await fireEvent.click(button) + + // Check that text element is visible + expect(getByText('Text')).toBeVisible() + + // Click button to hide the visible text element + await fireEvent.click(button) + + // Check that text element is not visible again + expect(getByText('Text')).not.toBeVisible() +}) From 65a27dd554bfaf83e22621a21babc70abf12016e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= Date: Sat, 31 Aug 2019 10:43:05 +0200 Subject: [PATCH 6/8] chore: Add @edufarre as contributor --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7261632a..e8d01d2e 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,7 @@ and bundled with Vue Testing Library. [![Oluwasetemi](https://avatars2.githubusercontent.com/u/10030028?v=3&s=120)](https://github.com/Oluwasetemi) [![cimbul](https://avatars2.githubusercontent.com/u/927923?v=3&s=120)](https://github.com/cimbul) [![alexkrolick](https://avatars2.githubusercontent.com/u/1571667?v=3&s=120)](https://github.com/alexkrolick) +[![edufarre](https://avatars2.githubusercontent.com/u/25011566?v=3&s=120)](https://github.com/edufarre) [build-badge]: https://travis-ci.org/testing-library/vue-testing-library.svg?branch=master From 787a34a96ce5f1b9935e77459f426509a4000bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= Date: Fri, 20 Sep 2019 20:27:19 +0200 Subject: [PATCH 7/8] chore: fix broken link in comment (#97) --- src/vue-testing-library.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vue-testing-library.js b/src/vue-testing-library.js index 77316df0..ed072556 100644 --- a/src/vue-testing-library.js +++ b/src/vue-testing-library.js @@ -116,7 +116,7 @@ fireEvent.touch = async elem => { // Small utility to provide a better experience when working with v-model. // Related upstream issue: https://github.com/vuejs/vue-test-utils/issues/345#issuecomment-380588199 -// Examples: https://github.com/testing-library/vue-testing-library/blob/master/tests/__tests__/form.js +// Examples: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/form.js fireEvent.update = (elem, value) => { const tagName = elem.tagName const type = elem.type From c4eacd27af4fd0e1f28626bdd6a7bb6349ff2382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= Date: Wed, 9 Oct 2019 13:22:04 +0200 Subject: [PATCH 8/8] feat: Bound DTL queries to the base element (#100) Closes #98 BREAKING CHANGE: baseElement is no longer tied to the document body, and container is no longer the parent node of the element wrapper, but a wrapper div. These changes shouldn't affect you if you weren't relying on either `baseElement` or `container`. --- package-lock.json | 6 +++ package.json | 1 + src/__tests__/components/Vuetify.vue | 22 ++++++++ src/__tests__/render.js | 77 ++++++++++++++++++++++++++++ src/__tests__/vuetify.js | 33 ++++++++++++ src/vue-testing-library.js | 25 +++++---- 6 files changed, 155 insertions(+), 9 deletions(-) create mode 100644 src/__tests__/components/Vuetify.vue create mode 100644 src/__tests__/render.js create mode 100644 src/__tests__/vuetify.js diff --git a/package-lock.json b/package-lock.json index db128a05..ba279c77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11690,6 +11690,12 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "vuetify": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-2.0.19.tgz", + "integrity": "sha512-zBskf77Z+RH8+Qs1q0NIDv/1enVkOoVH2dcdjcs+ZUNOhnlG0IkDedmqE2+PNm0JvJdgpOaV8wq+Pl69TGD2Hg==", + "dev": true + }, "vuex": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.1.tgz", diff --git a/package.json b/package.json index 1a15eba0..cde5f72d 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "vue-jest": "^3.0.4", "vue-router": "^3.1.2", "vue-template-compiler": "^2.6.10", + "vuetify": "^2.0.19", "vuex": "^3.1.1" }, "peerDependencies": { diff --git a/src/__tests__/components/Vuetify.vue b/src/__tests__/components/Vuetify.vue new file mode 100644 index 00000000..3add64fa --- /dev/null +++ b/src/__tests__/components/Vuetify.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/__tests__/render.js b/src/__tests__/render.js new file mode 100644 index 00000000..4a48772a --- /dev/null +++ b/src/__tests__/render.js @@ -0,0 +1,77 @@ +import {render} from '@testing-library/vue' +import '@testing-library/jest-dom/extend-expect' + +test('baseElement defaults to document.body', () => { + const {baseElement} = render({template: '
'}) + expect(baseElement).toBe(document.body) +}) + +test('renders custom baseElement', () => { + const Component = {template: ''} + + const {baseElement, container} = render(Component, { + baseElement: document.createElement('blink'), + }) + + expect(baseElement).toMatchInlineSnapshot(` + +
+ +
+
+ `) + + expect(container).toMatchInlineSnapshot(` +
+ +
+ `) +}) + +test('renders container', () => { + const {container, getByTestId} = render({ + template: '
my content
', + }) + + expect(container.firstChild).toHaveTextContent( + getByTestId('myDiv').textContent, + ) +}) + +test('container defaults to div', () => { + const {container} = render({template: '
'}) + + expect(container.tagName).toBe('DIV') +}) + +test('renders custom container', () => { + const blink = document.createElement('blink') + const Component = {template: '
'} + + const {container} = render(Component, { + container: document.body.appendChild(blink), + }) + + expect(container).toBe(blink) +}) + +test('baseElement matches container if not custom baseElement is provided', () => { + const blink = document.createElement('blink') + const Component = {template: '
'} + + const {container, baseElement} = render(Component, { + container: document.body.appendChild(blink), + }) + + expect(container).toMatchInlineSnapshot(` + +
+ + `) + + expect(baseElement).toMatchInlineSnapshot(` + +
+ + `) +}) diff --git a/src/__tests__/vuetify.js b/src/__tests__/vuetify.js new file mode 100644 index 00000000..17d30e86 --- /dev/null +++ b/src/__tests__/vuetify.js @@ -0,0 +1,33 @@ +import Vue from 'vue' +import {render, fireEvent} from '@testing-library/vue' +import Vuetify from 'vuetify' +import VuetifyDemoComponent from './components/Vuetify' + +// We need to use a global Vue instance, otherwise Vuetify will complain about +// read-only attributes. +// More info: https://github.com/vuetifyjs/vuetify/issues/4068 +// https://vuetifyjs.com/en/getting-started/unit-testing +Vue.use(Vuetify) + +// Vuetify requires you to wrap you app with a v-app component that provides +// a
node. So you can do that, or you can also set the +// attribute to the DOM. +document.body.setAttribute('data-app', true) +// Another solution is to create a custom renderer that provides all the +// environment required by Vuetify. + +test('renders a Vuetify-powered component', async () => { + const {getByText} = render(VuetifyDemoComponent, { + vuetify: new Vuetify(), + }) + + await fireEvent.click(getByText('open')) + + expect(getByText('Lorem ipsum dolor sit amet.')).toMatchInlineSnapshot(` +
+ Lorem ipsum dolor sit amet. +
+ `) +}) diff --git a/src/vue-testing-library.js b/src/vue-testing-library.js index ed072556..acfb1176 100644 --- a/src/vue-testing-library.js +++ b/src/vue-testing-library.js @@ -11,9 +11,19 @@ const mountedWrappers = new Set() function render( TestComponent, - {store = null, routes = null, ...mountOptions} = {}, + { + store = null, + routes = null, + container: customContainer, + baseElement: customBaseElement, + ...mountOptions + } = {}, configurationCb, ) { + const div = document.createElement('div') + const baseElement = customBaseElement || customContainer || document.body + const container = customContainer || baseElement.appendChild(div) + const localVue = createLocalVue() let vuexStore = null let router = null @@ -53,15 +63,12 @@ function render( }) mountedWrappers.add(wrapper) - - const div = document.createElement('div') - wrapper.element.parentNode.insertBefore(div, wrapper.element) - div.appendChild(wrapper.element) + container.appendChild(wrapper.element) return { - container: wrapper.element.parentNode, - baseElement: document.body, - debug: (el = wrapper.element) => logDOM(el), + container, + baseElement, + debug: (el = baseElement) => logDOM(el), unmount: () => wrapper.destroy(), isUnmounted: () => wrapper.vm._isDestroyed, html: () => wrapper.html(), @@ -70,7 +77,7 @@ function render( wrapper.setProps(_) return wait() }, - ...getQueriesForElement(wrapper.element.parentNode), + ...getQueriesForElement(baseElement), } }