Skip to content

Commit

Permalink
feat: Add types for Vue 3 (#180)
Browse files Browse the repository at this point in the history
* Add basic types

* Rename main file to properly get types

* Fix import statement

* Fix compiler options lib

* Extract temporary-defined types to its own file

* Remove duplicate test

* Fix link

* Improve tests

* Remove unnecessary chars

* Add support for file inputs

* Update deps

* Fix rerender typing test

* Remove typecheck step until we figure out how to overcome ts-ignore in node_modules. lol

* Update deps
  • Loading branch information
afontcu committed Dec 3, 2020
1 parent 7e1882a commit 3ef7112
Show file tree
Hide file tree
Showing 40 changed files with 286 additions and 139 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
module.exports = {
parserOptions: {
parser: '@typescript-eslint/parser',
},
extends: [
'./node_modules/kcd-scripts/eslint.js',
'plugin:vue/vue3-recommended',
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ light-weight, simple, and understandable.

## Typings

The TypeScript type definitions are in the [DefinitelyTyped repo][types] and
bundled with Vue Testing Library.
The TypeScript type definitions are in the [types][types-directory] directory.

## ESLint support

Expand Down Expand Up @@ -247,7 +246,6 @@ instead of filing an issue on GitHub.
[license]: https://github.com/testing-library/vue-testing-library/blob/master/LICENSE
[discord]: https://testing-library.com/discord
[discord-badge]: https://img.shields.io/discord/723559267868737556.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2&style=flat-square
[types]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/testing-library__vue
[jest-dom]: https://github.com/testing-library/jest-dom
[which-query]: https://testing-library.com/docs/guide-which-query
[guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
Expand All @@ -261,10 +259,11 @@ instead of filing an issue on GitHub.
[add-issue-bug]: https://github.com/testing-library/vue-testing-library/issues/new?assignees=&labels=bug&template=bug_report.md&title=
[add-issue]: (https://github.com/testing-library/vue-testing-library/issues/new)

[types-directory]: https://github.com/testing-library/vue-testing-library/blob/master/types
[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/src/__tests__/vueI18n.js
[vue-i18n-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/vue-i18n.js
[vuetify-example]: https://github.com/testing-library/vue-testing-library/blob/master/src/__tests__/vuetify.js
<!-- prettier-ignore-end -->
3 changes: 0 additions & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ const config = require('kcd-scripts/jest')
module.exports = merge(config, {
testEnvironment: 'jsdom',
moduleFileExtensions: ['js', 'vue'],
moduleNameMapper: {
'@testing-library/vue': '<rootDir>/src/vue-testing-library.js',
},
coverageDirectory: './coverage',
collectCoverageFrom: ['**/src/**/*.js', '!**/src/__tests__/**'],
transform: {
Expand Down
28 changes: 16 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"name": "@testing-library/vue",
"version": "0.0.0-semantically-released",
"description": "Simple and complete Vue DOM testing utilities that encourage good testing practices.",
"main": "dist/vue-testing-library.js",
"main": "dist/index.js",
"types": "types/index.d.ts",
"scripts": {
"format": "kcd-scripts format",
"build": "kcd-scripts build",
Expand All @@ -16,6 +17,7 @@
"node": ">10.18"
},
"files": [
"types",
"dist",
"cleanup-after-each.js"
],
Expand Down Expand Up @@ -45,36 +47,38 @@
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@testing-library/dom": "^7.26.3",
"@vue/test-utils": "^2.0.0-beta.10",
"@testing-library/dom": "^7.28.1",
"@vue/test-utils": "^2.0.0-beta.12",
"lodash.merge": "^4.6.2"
},
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.12.1",
"@testing-library/jest-dom": "^5.11.5",
"@testing-library/user-event": "^12.2.2",
"@vue/compiler-sfc": "^3.0.2",
"@testing-library/user-event": "^12.4.0",
"@types/estree": "0.0.45",
"@vue/compiler-sfc": "^3.0.4",
"apollo-boost": "^0.4.9",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"axios": "^0.20.0",
"dtslint": "^4.0.6",
"eslint-plugin-vue": "^7.1.0",
"graphql": "^15.4.0",
"graphql-tag": "^2.11.0",
"isomorphic-unfetch": "^3.1.0",
"jest-serializer-vue": "^2.0.2",
"kcd-scripts": "^7.0.3",
"kcd-scripts": "^7.5.1",
"msw": "^0.21.3",
"portal-vue": "^2.1.7",
"typescript": "^4.1.2",
"vee-validate": "^4.0.0-beta.16",
"vue": "^3.0.2",
"vee-validate": "^4.0.2",
"vue": "^3.0.4",
"vue-apollo": "^3.0.5",
"vue-i18n": "^9.0.0-beta.6",
"vue-jest": "^5.0.0-alpha.5",
"vue-router": "^4.0.0-rc.1",
"vuetify": "^2.3.16",
"vuex": "^4.0.0-rc.1"
"vue-jest": "^5.0.0-alpha.7",
"vue-router": "^4.0.0-rc.6",
"vuetify": "^2.3.19",
"vuex": "^4.0.0-rc.2"
},
"peerDependencies": {
"vue": ">= 3",
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/auto-cleanup-skip.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
let render
beforeAll(async () => {
beforeAll(() => {
process.env.VTL_SKIP_AUTO_CLEANUP = 'true'
const vtl = await require('@testing-library/vue')
const vtl = require('..')
render = vtl.render
})

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/auto-cleanup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {render} from '@testing-library/vue'
import {render} from '..'
import '@testing-library/jest-dom'

// This verifies that by importing VTL in an environment which supports
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/axios-mock.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@testing-library/jest-dom'
import axiosMock from 'axios'
import {render, fireEvent} from '@testing-library/vue'
import {render, fireEvent} from '..'
import Component from './components/Fetch.vue'

test('mocks an API call when load-greeting is clicked', async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/cleanup-throw.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
test.todo('check if this test still makes sense')

// import {render, cleanup} from '@testing-library/vue'
// import {render, cleanup} from '..'
// import {nextTick} from 'vue'

// test('cleanup re-throws errors from async lifecycle hooks', async () => {
Expand Down
10 changes: 5 additions & 5 deletions src/__tests__/components/Translations.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<h2>{{ $t('hello') }}</h2>
<select v-model="$i18n.locale">
<option value="en">English</option>
<option value="ja">Japanese</option>
</select>
<h2>{{ $t('hello') }}</h2>
<select v-model="$i18n.locale">
<option value="en">English</option>
<option value="ja">Japanese</option>
</select>
</template>

<script>
Expand Down
21 changes: 0 additions & 21 deletions src/__tests__/components/VueI18n.vue

This file was deleted.

2 changes: 1 addition & 1 deletion src/__tests__/debug.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable testing-library/no-debug */
import {render} from '@testing-library/vue'
import {render} from '..'
import HelloWorld from './components/HelloWorld'

beforeEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/directive.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {render} from '@testing-library/vue'
import {render} from '..'
import '@testing-library/jest-dom'
import {uppercaseDirective} from './directives/uppercase-directive'
import ComponentUsingDirective from './components/Directive'
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/disappearance.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {render, waitForElementToBeRemoved} from '@testing-library/vue'
import {render, waitForElementToBeRemoved} from '..'
import Disappearance from './components/Disappearance'
import '@testing-library/jest-dom'

Expand Down
19 changes: 18 additions & 1 deletion src/__tests__/fire-event.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {h} from 'vue'
import {render, fireEvent} from '@testing-library/vue'
import {render, fireEvent} from '..'
import Button from './components/Button'

const eventTypes = [
Expand Down Expand Up @@ -231,3 +231,20 @@ test('fireEvent.update does not crash if non-input element is passed in', async

expect(console.warn).not.toHaveBeenCalled()
})

test('fireEvent.update handles input file', async () => {
const {getByTestId} = render({
template: `<input type="file" data-testid="test-update" />`,
})

const file = new File(['(⌐□_□)'], 'chucknorris.png', {type: 'image/png'})

const inputEl = getByTestId('test-update')

// You could replace the lines below with
// userEvent.upload(inputEl, file)
Object.defineProperty(inputEl, 'files', {value: [file]})
await fireEvent.update(inputEl)

expect(console.warn).not.toHaveBeenCalled()
})
2 changes: 1 addition & 1 deletion src/__tests__/form.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {render, fireEvent} from '@testing-library/vue'
import {render, fireEvent} from '..'
import '@testing-library/jest-dom'
import Form from './components/Form'

Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/functional.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {render} from '@testing-library/vue'
import '@testing-library/jest-dom'
import {h} from 'vue'
import {render} from '..'
import '@testing-library/jest-dom'

// From docs: Performance gains from 2.x for functional components are now
// negligible in 3.x, so we recommend just using stateful components.
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/render.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {render} from '@testing-library/vue'
import {render} from '..'
import '@testing-library/jest-dom'

test('baseElement defaults to document.body', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/rerender.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@testing-library/jest-dom'
import {defineComponent, h, computed} from 'vue'
import {render} from '@testing-library/vue'
import {render} from '..'
import NumberDisplay from './components/NumberDisplay'

// It'd probably be better if you test the component that's doing the rerendering
Expand Down
10 changes: 5 additions & 5 deletions src/__tests__/select.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {render, fireEvent} from '@testing-library/vue'
import {render, fireEvent} from '..'
import '@testing-library/jest-dom'
import Select from './components/Select'

Expand All @@ -9,19 +9,19 @@ test('Select component', async () => {

// Get the Select element by using the initially displayed value.
const select = getByDisplayValue('Tyrannosaurus')
expect(select.value).toBe('dino1')
expect(select).toHaveValue('dino1')

// Update it by manually sending a valid option value.
await fireEvent.update(select, 'dino2')
expect(select.value).toBe('dino2')
expect(select).toHaveValue('dino2')

// We can trigger an update event by directly getting the <option> element.
optionElement = getByText('Deinonychus')
await fireEvent.update(optionElement)
expect(select.value).toBe('dino3')
expect(select).toHaveValue('dino3')

// ...even if option is within an <optgroup>.
optionElement = getByText('Diplodocus')
await fireEvent.update(optionElement)
expect(select.value).toBe('dino4')
expect(select).toHaveValue('dino4')
})
2 changes: 1 addition & 1 deletion src/__tests__/simple-button.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {render, fireEvent} from '@testing-library/vue'
import {render, fireEvent} from '..'
import Button from './components/Button'
import '@testing-library/jest-dom'

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/slots.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import '@testing-library/jest-dom'
import {render} from '@testing-library/vue'
import {render} from '..'
import Card from './components/Card'

// Usage is the same as Vue Test Utils, since slots values are passed using the `slots`
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/stopwatch.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import '@testing-library/jest-dom'
import {render, waitFor, fireEvent} from '@testing-library/vue'
import {render, waitFor, fireEvent} from '..'
import StopWatch from './components/StopWatch.vue'

const sleep = ms =>
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/stubs.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {render} from '@testing-library/vue'
import {render} from '..'
import '@testing-library/jest-dom'
import Stubs from './components/Stubs'

Expand Down
40 changes: 20 additions & 20 deletions src/__tests__/user-event.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@testing-library/jest-dom'
import {render} from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import {render, waitFor} from '..'
import Form from './components/Form'
import Select from './components/Select'

Expand All @@ -24,49 +24,49 @@ test('User events in a form', async () => {
expect(submitButton).toBeDisabled()

const titleInput = getByLabelText(/title of the movie/i)
await userEvent.type(titleInput, fakeReview.title)
expect(titleInput.value).toEqual(fakeReview.title)
userEvent.type(titleInput, fakeReview.title)
expect(titleInput).toHaveValue(fakeReview.title)

const textArea = getByLabelText(/Your review/i)
await userEvent.type(textArea, 'The t-rex went insane!')
expect(textArea.value).toEqual('The t-rex went insane!')
userEvent.type(textArea, 'The t-rex went insane!')
expect(textArea).toHaveValue('The t-rex went insane!')

await userEvent.clear(textArea)
expect(textArea.value).toEqual('')
await userEvent.type(textArea, fakeReview.review)
expect(textArea.value).toEqual(fakeReview.review)
userEvent.clear(textArea)
expect(textArea).toHaveValue('')
userEvent.type(textArea, fakeReview.review)
expect(textArea).toHaveValue(fakeReview.review)

const initialSelectedRating = getByLabelText(/Awful/i)
const wonderfulRadioInput = getByLabelText(/Wonderful/i)
expect(initialSelectedRating).toBeChecked()
expect(wonderfulRadioInput).not.toBeChecked()

await userEvent.click(wonderfulRadioInput)
userEvent.click(wonderfulRadioInput)
expect(wonderfulRadioInput).toBeChecked()
expect(initialSelectedRating).not.toBeChecked()
await waitFor(() => expect(initialSelectedRating).not.toBeChecked())

const recommendInput = getByLabelText(/Would you recommend this movie?/i)
await userEvent.click(recommendInput)
userEvent.click(recommendInput)
expect(recommendInput).toBeChecked()

userEvent.tab()
expect(submitButton).toHaveFocus()
expect(submitButton).toBeEnabled()
await userEvent.type(submitButton, '{enter}')
userEvent.type(submitButton, '{enter}')
expect(emitted().submit[0][0]).toMatchObject(fakeReview)

expect(console.warn).not.toHaveBeenCalled()
})

test('selecting option with user events', async () => {
test('selecting option with user events', () => {
const {getByDisplayValue} = render(Select)
const select = getByDisplayValue('Tyrannosaurus')
expect(select.value).toBe('dino1')
expect(select).toHaveValue('dino1')

await userEvent.selectOptions(select, 'dino2')
expect(select.value).toBe('dino2')
userEvent.selectOptions(select, 'dino2')
expect(select).toHaveValue('dino2')

await userEvent.selectOptions(select, 'dino3')
expect(select.value).not.toBe('dino2')
expect(select.value).toBe('dino3')
userEvent.selectOptions(select, 'dino3')
expect(select).not.toHaveValue('dino2')
expect(select).toHaveValue('dino3')
})
Loading

0 comments on commit 3ef7112

Please sign in to comment.