Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move types from DefinitelyTyped to this repository #165

Merged
merged 6 commits into from
Nov 14, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support for this is now built-in to the latest version of kcd-scripts (actually, eslint-config-kentcdodds, but that's what kcd-scripts uses).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I assumed when I checked the changelogs, but sadly enough eslint-plugin-vue requires us to use parserOptions.parser option instead of parser, because the latest needs to be used internally to parse Vue files.

SFC are cool but come with their own headaches 😅

},
extends: [
'./node_modules/kcd-scripts/eslint.js',
'plugin:vue/recommended',
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->


- [Installation](#installation)
- [A basic example](#a-basic-example)
- [More examples](#more-examples)
Expand Down Expand Up @@ -173,8 +174,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 @@ -248,7 +248,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 @@ -262,6 +261,7 @@ 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
Expand Down
20 changes: 13 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@
"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",
"types": "types/index.d.ts",
"scripts": {
"format": "kcd-scripts format",
"build": "kcd-scripts build",
"lint": "kcd-scripts lint",
"test": "kcd-scripts test",
"test:update": "npm test -- --updateSnapshot --coverage",
"validate": "kcd-scripts validate",
"typecheck": "dtslint ./types/",
"setup": "npm install && npm run validate -s"
},
"engines": {
"node": ">10.18"
},
"files": [
"types",
"dist",
"cleanup-after-each.js"
],
Expand All @@ -40,34 +43,37 @@
"author": "Daniel Cook",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@testing-library/dom": "^7.24.3",
"@types/testing-library__vue": "^5.0.0",
"@babel/runtime": "^7.12.5",
"@testing-library/dom": "^7.26.6",
"@vue/test-utils": "^1.1.0"
},
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.11.5",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/jest-dom": "^5.11.6",
"@types/estree": "0.0.45",
"apollo-boost": "^0.4.9",
"apollo-cache-inmemory": "^1.6.6",
"axios": "^0.20.0",
"dtslint": "^4.0.5",
"eslint": "^7.13.0",
"eslint-plugin-vue": "^6.2.2",
"graphql": "^15.3.0",
"graphql-tag": "^2.11.0",
"isomorphic-unfetch": "^3.0.0",
"jest-serializer-vue": "^2.0.2",
"kcd-scripts": "^6.5.1",
"kcd-scripts": "^7.0.3",
"lodash.merge": "^4.6.2",
"msw": "^0.21.2",
"portal-vue": "^2.1.7",
"typescript": "^4.0.5",
"vee-validate": "^2.2.15",
"vue": "^2.6.12",
"vue-apollo": "^3.0.4",
"vue-i18n": "^8.21.1",
"vue-jest": "^4.0.0-rc.0",
"vue-router": "^3.4.5",
"vue-router": "^3.4.9",
"vue-template-compiler": "^2.6.12",
"vuetify": "^2.3.10",
"vuetify": "^2.3.17",
"vuex": "^3.5.1"
},
"peerDependencies": {
Expand Down
74 changes: 74 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// TypeScript Version: 4.0

import Vue, {ComponentOptions} from 'vue'
import {ThisTypedMountOptions, VueClass} from '@vue/test-utils'
import {Store, StoreOptions} from 'vuex'
import Router, {RouteConfig} from 'vue-router'
// eslint-disable-next-line import/no-extraneous-dependencies
import {OptionsReceived as PrettyFormatOptions} from 'pretty-format'
import {queries, EventType, BoundFunctions} from '@testing-library/dom'

// NOTE: fireEvent is overridden below
export * from '@testing-library/dom'

export interface RenderResult extends BoundFunctions<typeof queries> {
container: HTMLElement
baseElement: HTMLElement
debug: (
baseElement?:
| HTMLElement
| DocumentFragment
| Array<HTMLElement | DocumentFragment>,
maxLength?: number,
options?: PrettyFormatOptions,
) => void
unmount(): void
isUnmounted(): boolean
html(): string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
emitted(): {[name: string]: any[][]}
updateProps(props: object): Promise<void>
}

export interface RenderOptions<V extends Vue, S = {}>
// The props and store options special-cased by Vue Testing Library and NOT passed to mount().
extends Omit<ThisTypedMountOptions<V>, 'store' | 'props'> {
props?: object
store?: StoreOptions<S>
routes?: RouteConfig[]
container?: HTMLElement
baseElement?: HTMLElement
}

export type ConfigurationCallback<V extends Vue> = (
localVue: typeof Vue,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
store: Store<any>,
router: Router,
) => Partial<ThisTypedMountOptions<V>> | void
Copy link
Member Author

@afontcu afontcu Nov 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line productes the following warning with latest config:

void is only valid as a return type or generic type variable
@typescript-eslint/no-invalid-void-type

not entirely sure I should be worried about this?


export function render<V extends Vue>(
TestComponent: VueClass<V> | ComponentOptions<V>,
options?: RenderOptions<V>,
configure?: ConfigurationCallback<V>,
): RenderResult

export type AsyncFireObject = {
[K in EventType]: (
element: Document | Element | Window,
options?: {},
) => Promise<void>
}

export interface VueFireEventObject extends AsyncFireObject {
(element: Document | Element | Window, event: Event): Promise<void>
touch(element: Document | Element | Window): Promise<void>
update(element: HTMLOptionElement): Promise<void>
update(
element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement,
value: string,
): Promise<void>
update(element: HTMLElement, value?: string): Promise<void>
}

export const fireEvent: VueFireEventObject
137 changes: 137 additions & 0 deletions types/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import Vue from 'vue'
import {render, fireEvent, screen, waitFor} from '@testing-library/vue'

declare const elem: HTMLElement

const SomeComponent = Vue.extend({
name: 'SomeComponent',
props: {
foo: {type: Number, default: 0},
bar: {type: String, default: '0'},
},
})

export async function testRender() {
const page = render({template: '<div />'})

// single queries
page.getByText('foo')
page.queryByText('foo')
await page.findByText('foo')

// multiple queries
page.getAllByText('bar')
page.queryAllByText('bar')
await page.findAllByText('bar')

// helpers
const {container, unmount, debug} = page

debug(container)

debug(elem) // $ExpectType void
debug([elem, elem], 100, {highlight: false}) // $ExpectType void

unmount()
}

export function testRenderOptions() {
const container = document.createElement('div')
const options = {container}
render({template: 'div'}, options)
}

export async function testFireEvent() {
const {container} = render({template: 'button'})
await fireEvent.click(container)
}

export function testDebug() {
const {debug, getAllByTestId} = render({
render(h) {
return h('div', [
h('h1', {attrs: {'data-testId': 'testid'}}, 'hello world'),
h('h2', {attrs: {'data-testId': 'testid'}}, 'hello world'),
])
},
})

debug(getAllByTestId('testid'))
}

export async function testScreen() {
render({template: 'button'})

await screen.findByRole('button')
}

export async function testWaitFor() {
const {container} = render({template: 'button'})
await fireEvent.click(container)
await waitFor(() => {})
}

export function testOptions() {
render(SomeComponent, {
// options for new Vue()
name: 'SomeComponent',
methods: {
glorb() {
return 42
},
},
// options for vue-test-utils mount()
slots: {
quux: '<p>Baz</p>',
},
mocks: {
isThisFake() {
return true
},
},
// options for Vue Testing Library render()
container: elem,
baseElement: elem,
props: {
foo: 9,
bar: 'x',
},
store: {
state: {
foos: [4, 5],
bars: ['a', 'b'],
},
getters: {
fooCount() {
return this.foos.length
},
},
},
routes: [
{path: '/', name: 'home', component: SomeComponent},
{
path: '/about',
name: 'about',
component: () => Promise.resolve(SomeComponent),
},
],
})
}

export function testConfigCallback() {
const ExamplePlugin: Vue.PluginFunction<never> = () => {}
render(SomeComponent, {}, (localVue, store, router) => {
localVue.use(ExamplePlugin)
store.replaceState({foo: 'bar'})
router.onError(error => console.log(error.message))
})
}

/*
eslint
testing-library/prefer-explicit-assert: "off",
testing-library/no-wait-for-empty-callback: "off",
testing-library/no-debug: "off",
testing-library/prefer-screen-queries: "off",
@typescript-eslint/unbound-method: "off",
*/
17 changes: 17 additions & 0 deletions types/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// this additional tsconfig is required by dtslint
// see: https://github.com/Microsoft/dtslint#typestsconfigjson
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es6", "dom"],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"@testing-library/vue": ["."]
}
}
}
7 changes: 7 additions & 0 deletions types/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": ["dtslint/dtslint.json"],
"rules": {
"semicolon": false,
"whitespace": false
}
}