From d1ab9ffe55f152680b3227900f1788cc41c3d1b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= <afontcu@gmail.com>
Date: Sun, 1 Nov 2020 10:25:09 +0100
Subject: [PATCH 1/5] Add required dependencies

---
 package.json | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index d579d2f3..de573e11 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
   "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",
@@ -10,12 +11,14 @@
     "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"
   ],
@@ -42,7 +45,6 @@
   "dependencies": {
     "@babel/runtime": "^7.11.2",
     "@testing-library/dom": "^7.24.3",
-    "@types/testing-library__vue": "^5.0.0",
     "@vue/test-utils": "^1.1.0"
   },
   "devDependencies": {
@@ -51,6 +53,7 @@
     "apollo-boost": "^0.4.9",
     "apollo-cache-inmemory": "^1.6.6",
     "axios": "^0.20.0",
+    "dtslint": "^4.0.4",
     "eslint-plugin-vue": "^6.2.2",
     "graphql": "^15.3.0",
     "graphql-tag": "^2.11.0",
@@ -60,6 +63,7 @@
     "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",

From 6e2ce45bd4bd27ec9fe67ae812638c465c4db9f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= <afontcu@gmail.com>
Date: Sun, 1 Nov 2020 10:25:32 +0100
Subject: [PATCH 2/5] Add types

---
 types/index.d.ts    |  71 +++++++++++++++++++++++++
 types/test.ts       | 124 ++++++++++++++++++++++++++++++++++++++++++++
 types/tsconfig.json |  17 ++++++
 types/tslint.json   |   7 +++
 4 files changed, 219 insertions(+)
 create mode 100644 types/index.d.ts
 create mode 100644 types/test.ts
 create mode 100644 types/tsconfig.json
 create mode 100644 types/tslint.json

diff --git a/types/index.d.ts b/types/index.d.ts
new file mode 100644
index 00000000..8441b13d
--- /dev/null
+++ b/types/index.d.ts
@@ -0,0 +1,71 @@
+// TypeScript Version: 3.8
+
+import Vue, {ComponentOptions} from 'vue'
+import {ThisTypedMountOptions, VueClass} from '@vue/test-utils'
+import {Store, StoreOptions} from 'vuex'
+import Router, {RouteConfig} from 'vue-router'
+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
+  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,
+  store: Store<any>,
+  router: Router,
+) => Partial<ThisTypedMountOptions<V>> | void
+
+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
diff --git a/types/test.ts b/types/test.ts
new file mode 100644
index 00000000..dd2a5ff2
--- /dev/null
+++ b/types/test.ts
@@ -0,0 +1,124 @@
+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: Number,
+    bar: String,
+  },
+})
+
+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(elem) // $ExpectType void
+  debug([elem, elem], 100, {highlight: false}) // $ExpectType void
+}
+
+async function testRenderOptions() {
+  const container = document.createElement('div')
+  const options = {container}
+  render({template: 'div'}, options)
+}
+
+async function testFireEvent() {
+  const {container} = render({template: 'button'})
+  await fireEvent.click(container)
+}
+
+async 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'))
+}
+
+async function testScreen() {
+  render({template: 'button'})
+
+  await screen.findByRole('button')
+}
+
+async function testWaitFor() {
+  const {container} = render({template: 'button'})
+  fireEvent.click(container)
+  await waitFor(() => {})
+}
+
+async 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),
+      },
+    ],
+  })
+}
+
+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))
+  })
+}
diff --git a/types/tsconfig.json b/types/tsconfig.json
new file mode 100644
index 00000000..4c48bf28
--- /dev/null
+++ b/types/tsconfig.json
@@ -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": ["."]
+    }
+  }
+}
diff --git a/types/tslint.json b/types/tslint.json
new file mode 100644
index 00000000..c7b428f3
--- /dev/null
+++ b/types/tslint.json
@@ -0,0 +1,7 @@
+{
+  "extends": ["dtslint/dtslint.json"],
+  "rules": {
+    "semicolon": false,
+    "whitespace": false
+  }
+}

From ad510b2706d150337d1387f04b1cd965853b3ba6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= <afontcu@gmail.com>
Date: Sun, 1 Nov 2020 10:28:07 +0100
Subject: [PATCH 3/5] Update readme

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index ab3bcab2..4382388c 100644
--- a/README.md
+++ b/README.md
@@ -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)
@@ -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
 
@@ -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
@@ -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

From cc07d23ab54e1b1981d480ddd73b7e37e76ba852 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= <afontcu@gmail.com>
Date: Sat, 14 Nov 2020 20:09:03 +0100
Subject: [PATCH 4/5] Bump deps and fix build

---
 .eslintrc.js     |  3 +++
 package.json     | 16 +++++++++-------
 types/index.d.ts |  5 ++++-
 types/test.ts    | 35 ++++++++++++++++++++++++-----------
 4 files changed, 40 insertions(+), 19 deletions(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index 612dd456..ab4c94dd 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,4 +1,7 @@
 module.exports = {
+  parserOptions: {
+    parser: '@typescript-eslint/parser',
+  },
   extends: [
     './node_modules/kcd-scripts/eslint.js',
     'plugin:vue/recommended',
diff --git a/package.json b/package.json
index de573e11..2d9b84c3 100644
--- a/package.json
+++ b/package.json
@@ -43,23 +43,25 @@
   "author": "Daniel Cook",
   "license": "MIT",
   "dependencies": {
-    "@babel/runtime": "^7.11.2",
-    "@testing-library/dom": "^7.24.3",
+    "@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.4",
+    "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",
@@ -69,9 +71,9 @@
     "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": {
diff --git a/types/index.d.ts b/types/index.d.ts
index 8441b13d..f50ac952 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -1,9 +1,10 @@
-// TypeScript Version: 3.8
+// 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'
 
@@ -24,6 +25,7 @@ export interface RenderResult extends BoundFunctions<typeof queries> {
   unmount(): void
   isUnmounted(): boolean
   html(): string
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
   emitted(): {[name: string]: any[][]}
   updateProps(props: object): Promise<void>
 }
@@ -40,6 +42,7 @@ export interface RenderOptions<V extends Vue, S = {}>
 
 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
diff --git a/types/test.ts b/types/test.ts
index dd2a5ff2..6663d3c7 100644
--- a/types/test.ts
+++ b/types/test.ts
@@ -6,12 +6,12 @@ declare const elem: HTMLElement
 const SomeComponent = Vue.extend({
   name: 'SomeComponent',
   props: {
-    foo: Number,
-    bar: String,
+    foo: {type: Number, default: 0},
+    bar: {type: String, default: '0'},
   },
 })
 
-async function testRender() {
+export async function testRender() {
   const page = render({template: '<div />'})
 
   // single queries
@@ -27,22 +27,26 @@ async function testRender() {
   // helpers
   const {container, unmount, debug} = page
 
+  debug(container)
+
   debug(elem) // $ExpectType void
   debug([elem, elem], 100, {highlight: false}) // $ExpectType void
+
+  unmount()
 }
 
-async function testRenderOptions() {
+export function testRenderOptions() {
   const container = document.createElement('div')
   const options = {container}
   render({template: 'div'}, options)
 }
 
-async function testFireEvent() {
+export async function testFireEvent() {
   const {container} = render({template: 'button'})
   await fireEvent.click(container)
 }
 
-async function testDebug() {
+export function testDebug() {
   const {debug, getAllByTestId} = render({
     render(h) {
       return h('div', [
@@ -55,19 +59,19 @@ async function testDebug() {
   debug(getAllByTestId('testid'))
 }
 
-async function testScreen() {
+export async function testScreen() {
   render({template: 'button'})
 
   await screen.findByRole('button')
 }
 
-async function testWaitFor() {
+export async function testWaitFor() {
   const {container} = render({template: 'button'})
-  fireEvent.click(container)
+  await fireEvent.click(container)
   await waitFor(() => {})
 }
 
-async function testOptions() {
+export function testOptions() {
   render(SomeComponent, {
     // options for new Vue()
     name: 'SomeComponent',
@@ -114,7 +118,7 @@ async function testOptions() {
   })
 }
 
-function testConfigCallback() {
+export function testConfigCallback() {
   const ExamplePlugin: Vue.PluginFunction<never> = () => {}
   render(SomeComponent, {}, (localVue, store, router) => {
     localVue.use(ExamplePlugin)
@@ -122,3 +126,12 @@ function testConfigCallback() {
     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",
+*/

From 34594ebc2b200716e970845d636cc46ad3ad902b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= <afontcu@gmail.com>
Date: Sat, 14 Nov 2020 20:16:06 +0100
Subject: [PATCH 5/5] Bump eslint to fix node 15

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 2d9b84c3..6c977fd9 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,7 @@
     "axios": "^0.20.0",
     "dtslint": "^4.0.5",
     "eslint": "^7.13.0",
-    "eslint-plugin-vue": "^6.2.2",
+    "eslint-plugin-vue": "^7.1.0",
     "graphql": "^15.3.0",
     "graphql-tag": "^2.11.0",
     "isomorphic-unfetch": "^3.0.0",