Skip to content

Commit

Permalink
feat(cleanup): automatically cleanup if afterEach is detected (#80)
Browse files Browse the repository at this point in the history
You can disable this with the VTL_SKIP_CLEANUP environment variable, but it's recommended to have cleanup work this way.

Closes #77 

BREAKING CHANGE: If your tests were not isolated before (and you referenced the same component between tests) then this change will break your tests. You should keep your tests isolated, but if you're unable/unwilling to do that right away, then you can run your tests with the environment variable VTL_SKIP_AUTO_CLEANUP set to true.
  • Loading branch information
Oluwasetemi authored and afontcu committed Aug 19, 2019
1 parent 297c1c1 commit 394bde7
Show file tree
Hide file tree
Showing 13 changed files with 81 additions and 32 deletions.
4 changes: 3 additions & 1 deletion cleanup-after-each.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
afterEach(require('./dist/vue-testing-library').cleanup)
console.warn(
'The module `@testing-library/vue/cleanup-after-each` has been deprecated and no longer does anything (it is not needed). You no longer need to import this module and can safely remove any import or configuration which imports this module',
)
28 changes: 28 additions & 0 deletions src/__tests__/auto-cleanup-skip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
let render
beforeAll(async () => {
process.env.VTL_SKIP_AUTO_CLEANUP = 'true'
const vtl = await require('@testing-library/vue')
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
test('first test render a vue component', () => {
render({
template: `<h1>Hello World</h1>`,
})

expect(document.body.innerHTML).toMatchInlineSnapshot(`
<div>
<h1>Hello World</h1>
</div>
`)
})

test('no cleanup should have happened, renders the first component still', () => {
expect(document.body.innerHTML).toMatchInlineSnapshot(`
<div>
<h1>Hello World</h1>
</div>
`)
})
20 changes: 20 additions & 0 deletions src/__tests__/auto-cleanup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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.
test('render the first component', () => {
render({
template: `<h1>Hello World</h1>`,
})
expect(document.body.innerHTML).toMatchInlineSnapshot(`
<div>
<h1>Hello World</h1>
</div>
`)
})

test('cleans up after each test by default', () => {
expect(document.body.innerHTML).toMatchInlineSnapshot(`""`)
})
3 changes: 1 addition & 2 deletions src/__tests__/debug.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {cleanup, render} from '@testing-library/vue'
import {render} from '@testing-library/vue'
import HelloWorld from './components/HelloWorld'

beforeEach(() => {
jest.spyOn(console, 'log').mockImplementation(() => {})
})

afterEach(() => {
cleanup()
console.log.mockRestore()
})

Expand Down
8 changes: 3 additions & 5 deletions src/__tests__/functional.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {cleanup, render} from '@testing-library/vue'
import {render} from '@testing-library/vue'
import FunctionalSFC from './components/FunctionalSFC'

const Functional = {
Expand All @@ -8,15 +8,13 @@ const Functional = {
},
}

afterEach(cleanup)

it('renders functional comp', () => {
test('renders functional comp', () => {
const {getByText} = render(Functional)

getByText('Hi!')
})

it('renders functional SFC comp', () => {
test('renders functional SFC comp', () => {
const {getByText} = render(FunctionalSFC)

getByText('Hi!')
Expand Down
4 changes: 1 addition & 3 deletions src/__tests__/simple-button.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {render, cleanup, fireEvent} from '@testing-library/vue'
import {render, fireEvent} from '@testing-library/vue'
import Button from './components/Button'
import '@testing-library/jest-dom/extend-expect'

afterEach(cleanup)

test('renders button with text', () => {
const text = "Click me; I'm sick"

Expand Down
4 changes: 1 addition & 3 deletions src/__tests__/stopwatch.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {cleanup, render, wait, fireEvent} from '@testing-library/vue'
import {render, wait, fireEvent} from '@testing-library/vue'
import StopWatch from './components/StopWatch.vue'
import '@testing-library/jest-dom/extend-expect'

afterEach(cleanup)

test('unmounts a component', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {})

Expand Down
4 changes: 1 addition & 3 deletions src/__tests__/stubs.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {render, cleanup} from '@testing-library/vue'
import {render} from '@testing-library/vue'
import Stubs from './components/Stubs'

afterEach(cleanup)

test('Form contains search button', () => {
const {getByText} = render(Stubs, {
stubs: ['FontAwesomeIcon'],
Expand Down
4 changes: 1 addition & 3 deletions src/__tests__/vue-router.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@testing-library/jest-dom/extend-expect'
import {render, fireEvent} from '@testing-library/vue'

import {cleanup, render, fireEvent} from '@testing-library/vue'
import App from './components/Router/App.vue'
import Home from './components/Router/Home.vue'
import About from './components/Router/About.vue'
Expand All @@ -11,8 +11,6 @@ const routes = [
{path: '*', redirect: '/about'},
]

afterEach(cleanup)

test('full app rendering/navigating', async () => {
// Notice how we pass a `routes` object to our render function.
const {queryByTestId} = render(App, {routes})
Expand Down
12 changes: 7 additions & 5 deletions src/__tests__/vueI18n.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import '@testing-library/jest-dom/extend-expect'
import {cleanup, render, fireEvent} from '@testing-library/vue'
import {render, fireEvent} from '@testing-library/vue'
import Vuei18n from 'vue-i18n'
import VueI18n from './components/VueI18n'

afterEach(cleanup)

const messages = {
en: {
Hello: 'Hello',
Expand All @@ -14,15 +12,19 @@ const messages = {
},
}

test('can render en and ja text in header', async () => {
test('renders translations', async () => {
const {queryByText, getByText} = render(VueI18n, {}, vue => {
// Let's register Vuei18n normally
vue.use(Vuei18n)

const i18n = new Vuei18n({
locale: 'en',
fallbackLocale: 'en',
messages,
})
//return i18n object so that it will be available as an additional option on the created vue instance

// Notice how we return an object from the callback function. It will be
// available as an additional option on the created Vue instance.
return {i18n}
})

Expand Down
4 changes: 1 addition & 3 deletions src/__tests__/vuex.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import '@testing-library/jest-dom/extend-expect'
import {cleanup, render, fireEvent} from '@testing-library/vue'
import {render, fireEvent} from '@testing-library/vue'

import VuexTest from './components/Store/VuexTest'
import {store} from './components/Store/store'

afterEach(cleanup)

// A common testing pattern is to create a custom renderer for a specific test
// file. This way, common operations such as registering a Vuex store can be
// abstracted out while avoiding sharing mutable state.
Expand Down
8 changes: 4 additions & 4 deletions tests/__tests__/within.js → src/__tests__/within.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { render, within } from '@testing-library/vue'
import {render, within} from '@testing-library/vue'

test('within() returns an object with all queries bound to the DOM node', () => {
const { getByTestId, getByText } = render({
const {getByTestId, getByText} = render({
template: `
<div>
<p>repeated text</p>
<div data-testid="div">repeated text</div>
</div>
`
`,
})

// getByText() provided by render() fails because it finds multiple elements
// with the same text (as expected).
expect(() => getByText('repeated text')).toThrow(
'Found multiple elements with the text: repeated text'
'Found multiple elements with the text: repeated text',
)

const divNode = getByTestId('div')
Expand Down
10 changes: 10 additions & 0 deletions src/vue-testing-library.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,15 @@ fireEvent.update = (elem, value) => {
return null
}

// If we're running in a test runner that supports afterEach then we'll
// automatically run cleanup after each test. This ensures that tests run in
// isolation from each other.
// If you don't like this, set the VTL_SKIP_AUTO_CLEANUP variable to 'true'.
if (typeof afterEach === 'function' && !process.env.VTL_SKIP_AUTO_CLEANUP) {
afterEach(() => {
cleanup()
})
}

export * from '@testing-library/dom'
export {cleanup, render, fireEvent}

0 comments on commit 394bde7

Please sign in to comment.