From 8c2ed70e2d9b94f03ad8690d9259c647cdc0d0a8 Mon Sep 17 00:00:00 2001
From: Michael Hensler <mhensler@microsoft.com>
Date: Mon, 26 Jul 2021 16:19:14 -0700
Subject: [PATCH 1/2] Add `setDefaultWaitOptions` method

---
 .all-contributorsrc             | 12 ++++++++++++
 README.md                       |  1 +
 docs/api-reference.md           | 24 ++++++++++++++++++++++++
 src/__tests__/asyncHook.test.ts | 30 ++++++++++++++++++++++++++++++
 src/core/asyncUtils.ts          | 19 +++++++++++--------
 src/core/index.ts               | 11 +++++++++--
 src/dom/pure.ts                 |  8 +++++++-
 src/native/pure.ts              |  8 +++++++-
 src/pure.ts                     | 22 +++++++++++++++++++---
 src/server/pure.ts              |  8 +++++++-
 src/types/react.ts              |  4 +++-
 11 files changed, 130 insertions(+), 17 deletions(-)

diff --git a/.all-contributorsrc b/.all-contributorsrc
index 9c318f40..6292aa7c 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -566,6 +566,18 @@
         "bug",
         "review"
       ]
+    },
+    {
+      "login": "orokanasaru",
+      "name": "Michael Hensler",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5751627?v=4",
+      "profile": "https://github.com/orokanasaru",
+      "contributions": [
+        "code",
+        "doc",
+        "ideas",
+        "test"
+      ]
     }
   ],
   "skipCi": true,
diff --git a/README.md b/README.md
index e3bba708..e4d7ad62 100644
--- a/README.md
+++ b/README.md
@@ -246,6 +246,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
     <td align="center"><a href="https://matan.io"><img src="https://avatars.githubusercontent.com/u/12711091?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matan Borenkraout</b></sub></a><br /><a href="#maintenance-MatanBobi" title="Maintenance">🚧</a></td>
     <td align="center"><a href="https://github.com/andyrooger"><img src="https://avatars.githubusercontent.com/u/420834?v=4?s=100" width="100px;" alt=""/><br /><sub><b>andyrooger</b></sub></a><br /><a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=andyrooger" title="Code">💻</a></td>
     <td align="center"><a href="https://github.com/bdwain"><img src="https://avatars.githubusercontent.com/u/3982094?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bryan Wain</b></sub></a><br /><a href="https://github.com/testing-library/react-hooks-testing-library/issues?q=author%3Abdwain" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/react-hooks-testing-library/pulls?q=is%3Apr+reviewed-by%3Abdwain" title="Reviewed Pull Requests">👀</a></td>
+    <td align="center"><a href="https://github.com/orokanasaru"><img src="https://avatars.githubusercontent.com/u/5751627?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Hensler</b></sub></a><br /><a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=orokanasaru" title="Code">💻</a> <a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=orokanasaru" title="Documentation">📖</a> <a href="#ideas-orokanasaru" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/testing-library/react-hooks-testing-library/commits?author=orokanasaru" title="Tests">⚠️</a></td>
   </tr>
 </table>
 
diff --git a/docs/api-reference.md b/docs/api-reference.md
index 7416d1f7..19b89a2d 100644
--- a/docs/api-reference.md
+++ b/docs/api-reference.md
@@ -271,6 +271,30 @@ _Default: 1000_
 
 The maximum amount of time in milliseconds (ms) to wait.
 
+### `setDefaultWaitOptions`
+
+```ts
+function setDefaultWaitOptions({
+  interval?: number | false
+  timeout?: number | false
+}): void
+```
+
+Updates the default values for `interval` and `timeout` used by the `waitFor*` functions.
+
+#### `interval`
+
+_Default: 50_
+
+The amount of time in milliseconds (ms) to wait between checks of the callback if no renders occur.
+Interval checking is disabled if `interval` is not provided as a `falsy`.
+
+#### `timeout`
+
+_Default: 1000_
+
+The maximum amount of time in milliseconds (ms) to wait.
+
 ---
 
 ## `console.error`
diff --git a/src/__tests__/asyncHook.test.ts b/src/__tests__/asyncHook.test.ts
index 17979ae2..f8e2b39f 100644
--- a/src/__tests__/asyncHook.test.ts
+++ b/src/__tests__/asyncHook.test.ts
@@ -1,6 +1,11 @@
+import { setDefaultWaitOptions } from 'core'
 import { useState, useRef, useEffect } from 'react'
 
 describe('async hook tests', () => {
+  beforeEach(() => {
+    setDefaultWaitOptions({ interval: 50, timeout: 1000 })
+  })
+
   const useSequence = (values: string[], intervalMs = 50) => {
     const [first, ...otherValues] = values
     const [value, setValue] = useState(() => first)
@@ -59,6 +64,17 @@ describe('async hook tests', () => {
       )
     })
 
+    test('should reject if custom default timeout exceeded when waiting for next update', async () => {
+      setDefaultWaitOptions({ timeout: 10 })
+      const { result, waitForNextUpdate } = renderHook(() => useSequence(['first', 'second']))
+
+      expect(result.current).toBe('first')
+
+      await expect(waitForNextUpdate()).rejects.toThrow(
+        Error('Timed out in waitForNextUpdate after 10ms.')
+      )
+    })
+
     test('should not reject when waiting for next update if timeout has been disabled', async () => {
       const { result, waitForNextUpdate } = renderHook(() => useSequence(['first', 'second'], 1100))
 
@@ -185,6 +201,20 @@ describe('async hook tests', () => {
       expect(checks).toBe(3)
     })
 
+    test('should check on custom default interval when waiting for expectation to pass', async () => {
+      setDefaultWaitOptions({ interval: 100 })
+      const { result, waitFor } = renderHook(() => useSequence(['first', 'second', 'third']))
+
+      let checks = 0
+
+      await waitFor(() => {
+        checks++
+        return result.current === 'third'
+      })
+
+      expect(checks).toBe(3)
+    })
+
     test('should wait for value to change', async () => {
       const { result, waitForValueToChange } = renderHook(() =>
         useSequence(['first', 'second', 'third'])
diff --git a/src/core/asyncUtils.ts b/src/core/asyncUtils.ts
index fe44c715..6032edeb 100644
--- a/src/core/asyncUtils.ts
+++ b/src/core/asyncUtils.ts
@@ -10,8 +10,13 @@ import {
 import { resolveAfter, callAfter } from '../helpers/promises'
 import { TimeoutError } from '../helpers/error'
 
-const DEFAULT_INTERVAL = 50
-const DEFAULT_TIMEOUT = 1000
+let defaultInterval: number | false = 50
+let defaultTimeout: number | false = 1000
+
+function setDefaultWaitOptions({ interval, timeout }: WaitOptions) {
+  defaultInterval = interval ?? defaultInterval
+  defaultTimeout = timeout ?? defaultTimeout
+}
 
 function asyncUtils(act: Act, addResolver: (callback: () => void) => void): AsyncUtils {
   const wait = async (callback: () => boolean | void, { interval, timeout }: WaitOptions) => {
@@ -55,7 +60,7 @@ function asyncUtils(act: Act, addResolver: (callback: () => void) => void): Asyn
 
   const waitFor = async (
     callback: () => boolean | void,
-    { interval = DEFAULT_INTERVAL, timeout = DEFAULT_TIMEOUT }: WaitForOptions = {}
+    { interval = defaultInterval, timeout = defaultTimeout }: WaitForOptions = {}
   ) => {
     const safeCallback = () => {
       try {
@@ -73,7 +78,7 @@ function asyncUtils(act: Act, addResolver: (callback: () => void) => void): Asyn
 
   const waitForValueToChange = async (
     selector: () => unknown,
-    { interval = DEFAULT_INTERVAL, timeout = DEFAULT_TIMEOUT }: WaitForValueToChangeOptions = {}
+    { interval = defaultInterval, timeout = defaultTimeout }: WaitForValueToChangeOptions = {}
   ) => {
     const initialValue = selector()
 
@@ -83,9 +88,7 @@ function asyncUtils(act: Act, addResolver: (callback: () => void) => void): Asyn
     }
   }
 
-  const waitForNextUpdate = async ({
-    timeout = DEFAULT_TIMEOUT
-  }: WaitForNextUpdateOptions = {}) => {
+  const waitForNextUpdate = async ({ timeout = defaultTimeout }: WaitForNextUpdateOptions = {}) => {
     let updated = false
     addResolver(() => {
       updated = true
@@ -104,4 +107,4 @@ function asyncUtils(act: Act, addResolver: (callback: () => void) => void): Asyn
   }
 }
 
-export { asyncUtils }
+export { asyncUtils, setDefaultWaitOptions }
diff --git a/src/core/index.ts b/src/core/index.ts
index ccd81b94..24ede8ca 100644
--- a/src/core/index.ts
+++ b/src/core/index.ts
@@ -1,6 +1,6 @@
 import { CreateRenderer, Renderer, RenderResult, RenderHookOptions } from '../types'
 
-import { asyncUtils } from './asyncUtils'
+import { asyncUtils, setDefaultWaitOptions } from './asyncUtils'
 import { cleanup, addCleanup, removeCleanup } from './cleanup'
 import { suppressErrorOutput } from './console'
 
@@ -82,4 +82,11 @@ function createRenderHook<
   return renderHook
 }
 
-export { createRenderHook, cleanup, addCleanup, removeCleanup, suppressErrorOutput }
+export {
+  createRenderHook,
+  cleanup,
+  addCleanup,
+  removeCleanup,
+  suppressErrorOutput,
+  setDefaultWaitOptions
+}
diff --git a/src/dom/pure.ts b/src/dom/pure.ts
index 42d66072..53509c85 100644
--- a/src/dom/pure.ts
+++ b/src/dom/pure.ts
@@ -37,6 +37,12 @@ const renderHook = createRenderHook(createDomRenderer)
 
 export { renderHook, act }
 
-export { cleanup, addCleanup, removeCleanup, suppressErrorOutput } from '../core'
+export {
+  cleanup,
+  addCleanup,
+  removeCleanup,
+  setDefaultWaitOptions,
+  suppressErrorOutput
+} from '../core'
 
 export * from '../types/react'
diff --git a/src/native/pure.ts b/src/native/pure.ts
index d033a312..01234064 100644
--- a/src/native/pure.ts
+++ b/src/native/pure.ts
@@ -36,6 +36,12 @@ const renderHook = createRenderHook(createNativeRenderer)
 
 export { renderHook, act }
 
-export { cleanup, addCleanup, removeCleanup, suppressErrorOutput } from '../core'
+export {
+  cleanup,
+  addCleanup,
+  removeCleanup,
+  setDefaultWaitOptions,
+  suppressErrorOutput
+} from '../core'
 
 export * from '../types/react'
diff --git a/src/pure.ts b/src/pure.ts
index ec72c6fe..0231505a 100644
--- a/src/pure.ts
+++ b/src/pure.ts
@@ -32,8 +32,24 @@ function getRenderer() {
   }
 }
 
-const { renderHook, act, cleanup, addCleanup, removeCleanup, suppressErrorOutput } = getRenderer()
-
-export { renderHook, act, cleanup, addCleanup, removeCleanup, suppressErrorOutput }
+const {
+  renderHook,
+  act,
+  cleanup,
+  addCleanup,
+  removeCleanup,
+  setDefaultWaitOptions,
+  suppressErrorOutput
+} = getRenderer()
+
+export {
+  renderHook,
+  act,
+  cleanup,
+  addCleanup,
+  removeCleanup,
+  setDefaultWaitOptions,
+  suppressErrorOutput
+}
 
 export * from './types/react'
diff --git a/src/server/pure.ts b/src/server/pure.ts
index 1978f2d0..fffe3fb8 100644
--- a/src/server/pure.ts
+++ b/src/server/pure.ts
@@ -61,6 +61,12 @@ const renderHook = createRenderHook(createServerRenderer)
 
 export { renderHook, act }
 
-export { cleanup, addCleanup, removeCleanup, suppressErrorOutput } from '../core'
+export {
+  cleanup,
+  addCleanup,
+  removeCleanup,
+  setDefaultWaitOptions,
+  suppressErrorOutput
+} from '../core'
 
 export * from '../types/react'
diff --git a/src/types/react.ts b/src/types/react.ts
index c03ad33d..a6f34e7d 100644
--- a/src/types/react.ts
+++ b/src/types/react.ts
@@ -5,7 +5,8 @@ import {
   RenderHookResult,
   ServerRenderHookResult,
   Act,
-  CleanupCallback
+  CleanupCallback,
+  WaitOptions
 } from '.'
 
 export type WrapperComponent<TProps> = ComponentType<TProps>
@@ -27,6 +28,7 @@ export type ReactHooksRenderer = {
   cleanup: () => Promise<void>
   addCleanup: (callback: CleanupCallback) => () => void
   removeCleanup: (callback: CleanupCallback) => void
+  setDefaultWaitOptions: (options: WaitOptions) => void
   suppressErrorOutput: () => () => void
 }
 

From 62fa16d6165de9ab3a2f38f0b01e0759f2486cee Mon Sep 17 00:00:00 2001
From: Michael Hensler <mhensler@microsoft.com>
Date: Fri, 30 Jul 2021 09:38:21 -0700
Subject: [PATCH 2/2] Update src/core/index.ts

Co-authored-by: Michael Peyper <mpeyper7@gmail.com>
---
 src/core/index.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/core/index.ts b/src/core/index.ts
index 24ede8ca..45f7a914 100644
--- a/src/core/index.ts
+++ b/src/core/index.ts
@@ -87,6 +87,6 @@ export {
   cleanup,
   addCleanup,
   removeCleanup,
-  suppressErrorOutput,
-  setDefaultWaitOptions
+  setDefaultWaitOptions,
+  suppressErrorOutput
 }