From 7f7ca2bd3c6aa486530cc2acefff01b105f6a7a2 Mon Sep 17 00:00:00 2001 From: otofu-square Date: Thu, 28 Feb 2019 21:55:22 +0900 Subject: [PATCH 01/10] $ npm i --save-dev typescript typings-tester @types/react --- package-lock.json | 43 ++++++++++++++++++++++++++++++++++++++++--- package.json | 5 ++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 88e301c9..6a48268e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1058,6 +1058,22 @@ "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz", "integrity": "sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==" }, + "@types/prop-types": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.0.tgz", + "integrity": "sha512-eItQyV43bj4rR3JPV0Skpl1SncRCdziTEK9/v8VwXmV6d/qOUO8/EuWeHBbCZcsfSHfzI5UyMJLCSXtxxznyZg==", + "dev": true + }, + "@types/react": { + "version": "16.8.5", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.5.tgz", + "integrity": "sha512-8LRySaaSJVLNZb2dbOGvGmzn88cbAfrgDpuWy+6lLgQ0OJFgHHvyuaCX4/7ikqJlpmCPf4uazJAZcfTQRdJqdQ==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", @@ -2115,6 +2131,12 @@ "cssom": "0.3.x" } }, + "csstype": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.2.tgz", + "integrity": "sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow==", + "dev": true + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -6349,6 +6371,12 @@ "string-width": "^2.1.1" } }, + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + }, "write": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", @@ -8155,9 +8183,9 @@ "dev": true }, "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "version": "3.3.3333", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3333.tgz", + "integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==", "dev": true }, "typescript-eslint-parser": { @@ -8178,6 +8206,15 @@ } } }, + "typings-tester": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/typings-tester/-/typings-tester-0.3.2.tgz", + "integrity": "sha512-HjGoAM2UoGhmSKKy23TYEKkxlphdJFdix5VvqWFLzH1BJVnnwG38tpC6SXPgqhfFGfHY77RlN1K8ts0dbWBQ7A==", + "dev": true, + "requires": { + "commander": "^2.12.2" + } + }, "uglify-js": { "version": "3.4.9", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", diff --git a/package.json b/package.json index 6a4dda5b..c5e61b57 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.2.0", "@babel/preset-env": "^7.3.4", "@babel/preset-react": "^7.0.0", + "@types/react": "^16.8.5", "all-contributors-cli": "^6.1.2", "babel-eslint": "^10.0.1", "babel-plugin-module-resolver": "^3.2.0", @@ -39,7 +40,9 @@ "prettier-eslint": "^8.8.2", "prettier-eslint-cli": "^4.7.1", "react": "^16.8.3", - "react-dom": "^16.8.3" + "react-dom": "^16.8.3", + "typescript": "^3.3.3333", + "typings-tester": "^0.3.2" }, "peerDependencies": { "react": "^16.8.0", From ae2d9907a6d406621df1a6cbcbf98ff378064180 Mon Sep 17 00:00:00 2001 From: otofu-square Date: Thu, 28 Feb 2019 23:34:52 +0900 Subject: [PATCH 02/10] Add index.d.ts --- index.d.ts | 19 +++++++++++++++++++ package.json | 1 + 2 files changed, 20 insertions(+) create mode 100644 index.d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 00000000..958bc713 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,19 @@ +import { cleanup, act, RenderOptions, RenderResult } from 'react-testing-library' + +export function renderHook any>( + callback: T, + options?: { + initialProps?: Parameters[0] + options?: RenderOptions + } +): { + readonly result: { + current: ReturnType + } + readonly unmount: RenderResult['unmount'] + readonly rerender: (hookProps?: Parameters[0]) => void +} + +export const testHook: typeof renderHook + +export { cleanup, act } diff --git a/package.json b/package.json index c5e61b57..d3c4c589 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.3.4", "description": "Simple component wrapper for testing React hooks", "main": "lib/index.js", + "typings": "./index.d.ts", "author": "Michael Peyper", "repository": { "type": "git", From bbfb0ff42dca1ad8dbc738e5ee6c571cc7d4e7a9 Mon Sep 17 00:00:00 2001 From: otofu-square Date: Thu, 28 Feb 2019 23:35:46 +0900 Subject: [PATCH 03/10] Add test for TS types --- test/typescript.test.js | 7 ++++ test/typescript/renderHook.ts | 60 +++++++++++++++++++++++++++++++++++ test/typescript/tsconfig.json | 10 ++++++ 3 files changed, 77 insertions(+) create mode 100644 test/typescript.test.js create mode 100644 test/typescript/renderHook.ts create mode 100644 test/typescript/tsconfig.json diff --git a/test/typescript.test.js b/test/typescript.test.js new file mode 100644 index 00000000..e2f25f19 --- /dev/null +++ b/test/typescript.test.js @@ -0,0 +1,7 @@ +import { checkDirectory } from 'typings-tester' + +describe('TypeScript definitions', function() { + it('should compile against index.d.ts', () => { + checkDirectory(__dirname + '/typescript') + }) +}) diff --git a/test/typescript/renderHook.ts b/test/typescript/renderHook.ts new file mode 100644 index 00000000..0985bf38 --- /dev/null +++ b/test/typescript/renderHook.ts @@ -0,0 +1,60 @@ +import { useState, createContext, useContext, useMemo } from 'react' +import { renderHook } from 'react-hooks-testing-library' + +const DARK: 'dark' = 'dark' +const LIGHT: 'light' = 'light' + +type InitialTheme = typeof DARK | typeof LIGHT | undefined + +const themes = { + light: { primaryLight: '#FFFFFF', primaryDark: '#000000' }, + dark: { primaryLight: '#000000', primaryDark: '#FFFFFF' } +} + +const ThemesContext = createContext(themes) + +const useTheme = (initialTheme: InitialTheme = DARK) => { + const themes = useContext(ThemesContext) + const [theme, setTheme] = useState(initialTheme) + const toggleTheme = () => { + setTheme(theme === 'light' ? 'dark' : 'light') + } + return useMemo(() => ({ ...themes[theme], toggleTheme }), [theme]) +} + +type InitialProps = { initialTheme: InitialTheme } + +function checkTypesWithNoInitialProps() { + const { result, unmount, rerender } = renderHook(() => useTheme()) + + // check types + const _result: { + current: { + primaryDark: string + primaryLight: string + toggleTheme: () => void + } + } = result + const _unmount: () => boolean = unmount + const _rerender: () => void = rerender +} + +function checkTypesWithInitialProps() { + const { result, unmount, rerender } = renderHook( + ({ initialTheme }: InitialProps) => useTheme(initialTheme), + { + initialProps: { initialTheme: DARK } + } + ) + + // check types + const _result: { + current: { + primaryDark: string + primaryLight: string + toggleTheme: () => void + } + } = result + const _unmount: () => boolean = unmount + const _rerender: (_: InitialProps) => void = rerender +} diff --git a/test/typescript/tsconfig.json b/test/typescript/tsconfig.json new file mode 100644 index 00000000..9d5e6686 --- /dev/null +++ b/test/typescript/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "lib": ["es2015", "dom"], + "strict": true, + "baseUrl": "../../", + "paths": { + "react-hooks-testing-library": ["index.d.ts"] + } + } +} From 1ba1bd9458a0453753e752fb2236389c99373c9e Mon Sep 17 00:00:00 2001 From: otofu-square Date: Fri, 1 Mar 2019 07:54:35 +0900 Subject: [PATCH 04/10] Improve typings to infer initialProps type --- index.d.ts | 8 ++++---- test/typescript/renderHook.ts | 13 ++++--------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/index.d.ts b/index.d.ts index 958bc713..69263457 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,9 +1,9 @@ import { cleanup, act, RenderOptions, RenderResult } from 'react-testing-library' -export function renderHook any>( - callback: T, +export function renderHook

any>( + callback: (_: P) => ReturnType, options?: { - initialProps?: Parameters[0] + initialProps?: P options?: RenderOptions } ): { @@ -11,7 +11,7 @@ export function renderHook any>( current: ReturnType } readonly unmount: RenderResult['unmount'] - readonly rerender: (hookProps?: Parameters[0]) => void + readonly rerender: (hookProps?: P) => void } export const testHook: typeof renderHook diff --git a/test/typescript/renderHook.ts b/test/typescript/renderHook.ts index 0985bf38..3c51ca43 100644 --- a/test/typescript/renderHook.ts +++ b/test/typescript/renderHook.ts @@ -22,8 +22,6 @@ const useTheme = (initialTheme: InitialTheme = DARK) => { return useMemo(() => ({ ...themes[theme], toggleTheme }), [theme]) } -type InitialProps = { initialTheme: InitialTheme } - function checkTypesWithNoInitialProps() { const { result, unmount, rerender } = renderHook(() => useTheme()) @@ -40,12 +38,9 @@ function checkTypesWithNoInitialProps() { } function checkTypesWithInitialProps() { - const { result, unmount, rerender } = renderHook( - ({ initialTheme }: InitialProps) => useTheme(initialTheme), - { - initialProps: { initialTheme: DARK } - } - ) + const { result, unmount, rerender } = renderHook(({ theme }) => useTheme(theme), { + initialProps: { theme: DARK } + }) // check types const _result: { @@ -56,5 +51,5 @@ function checkTypesWithInitialProps() { } } = result const _unmount: () => boolean = unmount - const _rerender: (_: InitialProps) => void = rerender + const _rerender: (_?: { theme: typeof DARK }) => void = rerender } From eaee298d43c32df2a3fe128100ab90b64faa844d Mon Sep 17 00:00:00 2001 From: otofu-square Date: Fri, 1 Mar 2019 08:23:02 +0900 Subject: [PATCH 05/10] fix renderHook options type to intersect RenderOptions type --- index.d.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index 69263457..4bbbd106 100644 --- a/index.d.ts +++ b/index.d.ts @@ -4,8 +4,7 @@ export function renderHook

any>( callback: (_: P) => ReturnType, options?: { initialProps?: P - options?: RenderOptions - } + } & RenderOptions ): { readonly result: { current: ReturnType From 3cb8f92caca0dc7f7908f34aab872e92acc74b1c Mon Sep 17 00:00:00 2001 From: otofu-square Date: Fri, 1 Mar 2019 09:56:39 +0900 Subject: [PATCH 06/10] simplify typing test & fix type definitions --- index.d.ts | 6 ++-- test/typescript/renderHook.ts | 58 +++++++++++++++++------------------ 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/index.d.ts b/index.d.ts index 4bbbd106..2acdba92 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,13 +1,13 @@ import { cleanup, act, RenderOptions, RenderResult } from 'react-testing-library' -export function renderHook

any>( - callback: (_: P) => ReturnType, +export function renderHook

( + callback: (...args: [P]) => R, options?: { initialProps?: P } & RenderOptions ): { readonly result: { - current: ReturnType + current: R } readonly unmount: RenderResult['unmount'] readonly rerender: (hookProps?: P) => void diff --git a/test/typescript/renderHook.ts b/test/typescript/renderHook.ts index 3c51ca43..6dfa5f18 100644 --- a/test/typescript/renderHook.ts +++ b/test/typescript/renderHook.ts @@ -1,36 +1,36 @@ -import { useState, createContext, useContext, useMemo } from 'react' +import { useState, useCallback } from 'react' import { renderHook } from 'react-hooks-testing-library' -const DARK: 'dark' = 'dark' -const LIGHT: 'light' = 'light' - -type InitialTheme = typeof DARK | typeof LIGHT | undefined - -const themes = { - light: { primaryLight: '#FFFFFF', primaryDark: '#000000' }, - dark: { primaryLight: '#000000', primaryDark: '#FFFFFF' } -} - -const ThemesContext = createContext(themes) - -const useTheme = (initialTheme: InitialTheme = DARK) => { - const themes = useContext(ThemesContext) - const [theme, setTheme] = useState(initialTheme) - const toggleTheme = () => { - setTheme(theme === 'light' ? 'dark' : 'light') +const useCounter = (initialCount: number = 0) => { + const [count, setCount] = useState(initialCount) + const incrementBy = useCallback( + (n: number) => { + setCount(count + n) + }, + [count] + ) + const decrementBy = useCallback( + (n: number) => { + setCount(count - n) + }, + [count] + ) + return { + count, + incrementBy, + decrementBy } - return useMemo(() => ({ ...themes[theme], toggleTheme }), [theme]) } function checkTypesWithNoInitialProps() { - const { result, unmount, rerender } = renderHook(() => useTheme()) + const { result, unmount, rerender } = renderHook(() => useCounter()) // check types const _result: { current: { - primaryDark: string - primaryLight: string - toggleTheme: () => void + count: number + incrementBy: (_: number) => void + decrementBy: (_: number) => void } } = result const _unmount: () => boolean = unmount @@ -38,18 +38,18 @@ function checkTypesWithNoInitialProps() { } function checkTypesWithInitialProps() { - const { result, unmount, rerender } = renderHook(({ theme }) => useTheme(theme), { - initialProps: { theme: DARK } + const { result, unmount, rerender } = renderHook(({ count }) => useCounter(count), { + initialProps: { count: 10 } }) // check types const _result: { current: { - primaryDark: string - primaryLight: string - toggleTheme: () => void + count: number + incrementBy: (_: number) => void + decrementBy: (_: number) => void } } = result const _unmount: () => boolean = unmount - const _rerender: (_?: { theme: typeof DARK }) => void = rerender + const _rerender: (_?: { count: number }) => void = rerender } From 36604a178283dfceb5e782a3c2fb2f1e72f50f7c Mon Sep 17 00:00:00 2001 From: otofu-square Date: Fri, 1 Mar 2019 09:58:15 +0900 Subject: [PATCH 07/10] $ yarn contributors:add --- .all-contributorsrc | 9 +++++++++ README.md | 5 ++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 969492a6..fd8b11c6 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -24,6 +24,15 @@ "test", "tool" ] + }, + { + "login": "otofu-square", + "name": "otofu-square", + "avatar_url": "https://avatars0.githubusercontent.com/u/10118235?v=4", + "profile": "https://github.com/otofu-square", + "contributions": [ + "code" + ] } ] } diff --git a/README.md b/README.md index 84b0efc8..3c055967 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Simple component wrapper and utilities for testing React hooks. [![downloads](https://img.shields.io/npm/dm/react-hooks-testing-library.svg?style=flat-square)](http://www.npmtrends.com/react-hooks-testing-library) [![MIT License](https://img.shields.io/npm/l/react-hooks-testing-library.svg?style=flat-square)](https://github.com/mpeyper/react-hooks-testing-library/blob/master/LICENSE.md) -[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square)](#contributors) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Code of Conduct](https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square)](https://github.com/mpeyper/react-hooks-testing-library/blob/master/CODE_OF_CONDUCT.md) @@ -156,8 +156,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds -| [
Michael Peyper](https://github.com/mpeyper)
[💻](https://github.com/mpeyper/react-hooks-testing-library/commits?author=mpeyper "Code") [🎨](#design-mpeyper "Design") [📖](https://github.com/mpeyper/react-hooks-testing-library/commits?author=mpeyper "Documentation") [🤔](#ideas-mpeyper "Ideas, Planning, & Feedback") [🚇](#infra-mpeyper "Infrastructure (Hosting, Build-Tools, etc)") [📦](#platform-mpeyper "Packaging/porting to new platform") [⚠️](https://github.com/mpeyper/react-hooks-testing-library/commits?author=mpeyper "Tests") [🔧](#tool-mpeyper "Tools") | -| :---: | +
Michael Peyper
Michael Peyper

💻 🎨 📖 🤔 🚇 📦 ⚠️ 🔧
otofu-square
otofu-square

💻
From 2bdb78a08214808af222bcc55964999b4f3207be Mon Sep 17 00:00:00 2001 From: otofu-square Date: Sat, 2 Mar 2019 00:53:37 +0900 Subject: [PATCH 08/10] Remove unnecessary `extend` --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index 2acdba92..40ec1c54 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,6 +1,6 @@ import { cleanup, act, RenderOptions, RenderResult } from 'react-testing-library' -export function renderHook

( +export function renderHook( callback: (...args: [P]) => R, options?: { initialProps?: P From b2478e810677e5bd33d52e847339383cc4f9cf40 Mon Sep 17 00:00:00 2001 From: otofu-square Date: Sat, 2 Mar 2019 00:55:11 +0900 Subject: [PATCH 09/10] Add test case for the case hook returns void --- test/typescript/renderHook.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/typescript/renderHook.ts b/test/typescript/renderHook.ts index 6dfa5f18..78892a53 100644 --- a/test/typescript/renderHook.ts +++ b/test/typescript/renderHook.ts @@ -1,4 +1,4 @@ -import { useState, useCallback } from 'react' +import { useState, useCallback, useEffect } from 'react' import { renderHook } from 'react-hooks-testing-library' const useCounter = (initialCount: number = 0) => { @@ -53,3 +53,14 @@ function checkTypesWithInitialProps() { const _unmount: () => boolean = unmount const _rerender: (_?: { count: number }) => void = rerender } + +function checkTypesWhenHookReturnsVoid() { + const { result, unmount, rerender } = renderHook(() => useEffect(() => {})) + + // check types + const _result: { + current: void + } = result + const _unmount: () => boolean = unmount + const _rerender: () => void = rerender +} From a16d3a303bfcfdd08ed007e524198b061b89d6ef Mon Sep 17 00:00:00 2001 From: Daniel K Date: Sun, 3 Mar 2019 11:05:23 +0900 Subject: [PATCH 10/10] Simplify the way to extract first argument type Co-Authored-By: otofu-square --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index 40ec1c54..b5ba0267 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,7 +1,7 @@ import { cleanup, act, RenderOptions, RenderResult } from 'react-testing-library' export function renderHook( - callback: (...args: [P]) => R, + callback: (props: P) => R, options?: { initialProps?: P } & RenderOptions