or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-react-hooks-testing-library

Simple and complete React hooks testing utilities that encourage good testing practices.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-hooks-testing-library@0.6.x

To install, run

npx @tessl/cli install tessl/npm-react-hooks-testing-library@0.6.0

0

# React Hooks Testing Library

1

2

React Hooks Testing Library provides simple and complete React hooks testing utilities that encourage good testing practices. It allows you to create a simple test harness for React hooks that handles running them within the body of a function component, providing various utility functions for updating inputs and retrieving outputs of custom hooks.

3

4

## Package Information

5

6

- **Package Name**: react-hooks-testing-library

7

- **Package Type**: npm

8

- **Language**: JavaScript with TypeScript definitions

9

- **Installation**: `npm install --save-dev react-hooks-testing-library`

10

11

**Dependencies:**

12

- `react` (peer dependency, ^16.8.0)

13

- `react-test-renderer` (peer dependency, ^16.8.0)

14

15

## Core Imports

16

17

```javascript

18

import { renderHook, act } from "react-hooks-testing-library";

19

// testHook is also available but deprecated - use renderHook instead

20

```

21

22

For CommonJS:

23

24

```javascript

25

const { renderHook, act } = require("react-hooks-testing-library");

26

// testHook is also available but deprecated - use renderHook instead

27

```

28

29

## Basic Usage

30

31

```javascript

32

import { renderHook, act } from "react-hooks-testing-library";

33

import { useState, useCallback } from "react";

34

35

// Example custom hook

36

function useCounter() {

37

const [count, setCount] = useState(0);

38

const increment = useCallback(() => setCount((x) => x + 1), []);

39

const decrement = useCallback(() => setCount((x) => x - 1), []);

40

return { count, increment, decrement };

41

}

42

43

// Test the hook

44

test("should increment counter", () => {

45

const { result } = renderHook(() => useCounter());

46

47

act(() => result.current.increment());

48

49

expect(result.current.count).toBe(1);

50

});

51

52

// Test with async operations

53

test("should handle async updates", async () => {

54

const { result, waitForNextUpdate } = renderHook(() => useAsyncHook());

55

56

expect(result.current.loading).toBe(true);

57

58

await waitForNextUpdate();

59

60

expect(result.current.loading).toBe(false);

61

});

62

```

63

64

## Capabilities

65

66

### Hook Rendering

67

68

Renders a test component that calls the provided hook callback every time it renders.

69

70

```typescript { .api }

71

/**

72

* Renders a test component that calls the provided callback, including any hooks it calls

73

* @param callback - Function to call each render that should call one or more hooks for testing

74

* @param options - Optional configuration object

75

* @returns Object with result, utilities for testing async hooks, rerendering, and unmounting

76

*/

77

function renderHook<P, R>(

78

callback: (props: P) => R,

79

options?: {

80

initialProps?: P;

81

wrapper?: React.ComponentType;

82

}

83

): {

84

readonly result: {

85

readonly current: R;

86

readonly error: Error;

87

};

88

readonly waitForNextUpdate: () => Promise<void>;

89

readonly unmount: () => boolean;

90

readonly rerender: (hookProps?: P) => void;

91

};

92

```

93

94

**Usage Examples:**

95

96

```javascript

97

// Basic hook testing

98

const { result } = renderHook(() => useState(0));

99

expect(result.current[0]).toBe(0);

100

101

// Testing hooks with props

102

const { result, rerender } = renderHook(

103

({ initialCount }) => useState(initialCount),

104

{ initialProps: { initialCount: 5 } }

105

);

106

expect(result.current[0]).toBe(5);

107

108

// Rerender with new props

109

rerender({ initialCount: 10 });

110

expect(result.current[0]).toBe(5); // State is preserved, initialCount only used on first render

111

112

// Testing hooks that require context

113

const wrapper = ({ children }) => (

114

<ThemeProvider theme="dark">{children}</ThemeProvider>

115

);

116

const { result } = renderHook(() => useTheme(), { wrapper });

117

expect(result.current.theme).toBe("dark");

118

```

119

120

### State Updates and Effects

121

122

Wrapper around react-test-renderer's act function for handling state updates and effects.

123

124

```typescript { .api }

125

/**

126

* Ensures that updates related to state changes, effects, and event handlers are properly flushed

127

* @param callback - Function to execute within act scope

128

* @returns void

129

*/

130

function act(callback: () => void): void;

131

```

132

133

**Usage Examples:**

134

135

```javascript

136

// Wrapping state updates

137

const { result } = renderHook(() => useCounter());

138

139

act(() => {

140

result.current.increment();

141

});

142

143

expect(result.current.count).toBe(1);

144

145

// Multiple state updates

146

act(() => {

147

result.current.increment();

148

result.current.increment();

149

});

150

151

expect(result.current.count).toBe(3);

152

```

153

154

### Async Hook Testing

155

156

Handle asynchronous operations in hooks with proper waiting mechanisms.

157

158

```typescript { .api }

159

/**

160

* Returns a Promise that resolves the next time the hook renders

161

* Commonly used when state is updated as the result of an asynchronous action

162

* @returns Promise that resolves on next hook render

163

*/

164

waitForNextUpdate(): Promise<void>;

165

```

166

167

**Usage Examples:**

168

169

```javascript

170

// Testing async hooks

171

const useAsyncData = () => {

172

const [data, setData] = useState(null);

173

const [loading, setLoading] = useState(true);

174

175

useEffect(() => {

176

fetchData().then((result) => {

177

setData(result);

178

setLoading(false);

179

});

180

}, []);

181

182

return { data, loading };

183

};

184

185

test("should load data asynchronously", async () => {

186

const { result, waitForNextUpdate } = renderHook(() => useAsyncData());

187

188

expect(result.current.loading).toBe(true);

189

expect(result.current.data).toBe(null);

190

191

await waitForNextUpdate();

192

193

expect(result.current.loading).toBe(false);

194

expect(result.current.data).toBeDefined();

195

});

196

```

197

198

### Hook Re-rendering

199

200

Re-render the hook with new props to test how it responds to prop changes.

201

202

```typescript { .api }

203

/**

204

* Function to rerender the test component including any hooks called in the callback function

205

* @param newProps - New props to pass to the callback function for future renders

206

* @returns void

207

*/

208

rerender(newProps?: P): void;

209

```

210

211

**Usage Examples:**

212

213

```javascript

214

// Testing prop changes

215

const useGreeting = (name) => {

216

return `Hello, ${name}!`;

217

};

218

219

const { result, rerender } = renderHook(

220

({ name }) => useGreeting(name),

221

{ initialProps: { name: "Alice" } }

222

);

223

224

expect(result.current).toBe("Hello, Alice!");

225

226

rerender({ name: "Bob" });

227

expect(result.current).toBe("Hello, Bob!");

228

```

229

230

### Hook Cleanup

231

232

Unmount the test component to trigger cleanup effects for useEffect hooks.

233

234

```typescript { .api }

235

/**

236

* Function to unmount the test component

237

* Commonly used to trigger cleanup effects for useEffect hooks

238

* @returns boolean indicating if unmount was successful

239

*/

240

unmount(): boolean;

241

```

242

243

**Usage Examples:**

244

245

```javascript

246

// Testing cleanup effects

247

const useTimer = () => {

248

const [count, setCount] = useState(0);

249

250

useEffect(() => {

251

const timer = setInterval(() => {

252

setCount((c) => c + 1);

253

}, 1000);

254

255

return () => clearInterval(timer);

256

}, []);

257

258

return count;

259

};

260

261

test("should cleanup timer on unmount", () => {

262

const { unmount } = renderHook(() => useTimer());

263

264

// Verify cleanup doesn't throw errors

265

expect(() => unmount()).not.toThrow();

266

});

267

```

268

269

### Error Handling

270

271

Access errors thrown during hook execution for testing error scenarios.

272

273

```typescript { .api }

274

/**

275

* Access to any error thrown during hook execution

276

*/

277

interface HookResult<R> {

278

readonly result: {

279

readonly current: R;

280

readonly error: Error;

281

};

282

}

283

```

284

285

**Usage Examples:**

286

287

```javascript

288

// Testing hook errors

289

const useErrorProneHook = (shouldThrow) => {

290

if (shouldThrow) {

291

throw new Error("Something went wrong");

292

}

293

return "success";

294

};

295

296

test("should capture hook errors", () => {

297

const { result } = renderHook(

298

({ shouldThrow }) => useErrorProneHook(shouldThrow),

299

{ initialProps: { shouldThrow: true } }

300

);

301

302

expect(result.error).toBeInstanceOf(Error);

303

expect(result.error.message).toBe("Something went wrong");

304

});

305

```

306

307

## Types

308

309

```typescript { .api }

310

/**

311

* Options for configuring hook rendering

312

*/

313

interface RenderHookOptions<P> {

314

/** Initial props passed to the hook callback */

315

initialProps?: P;

316

/** React component to wrap around the rendered hook */

317

wrapper?: React.ComponentType;

318

}

319

320

/**

321

* Result object returned by renderHook

322

*/

323

interface RenderHookResult<P, R> {

324

/** Container for hook return value and any errors */

325

readonly result: {

326

/** Current return value of the hook callback */

327

readonly current: R;

328

/** Error thrown during hook execution, if any */

329

readonly error: Error;

330

};

331

/** Promise that resolves on next hook render */

332

readonly waitForNextUpdate: () => Promise<void>;

333

/** Function to unmount the test component */

334

readonly unmount: () => boolean;

335

/** Function to rerender with optional new props */

336

readonly rerender: (hookProps?: P) => void;

337

}

338

```

339

340

## Deprecated APIs

341

342

### testHook (Deprecated)

343

344

```typescript { .api }

345

/**

346

* @deprecated Use renderHook instead. Will be removed in a future version.

347

* Legacy alias for renderHook function

348

*/

349

const testHook: typeof renderHook;

350

```

351

352

The `testHook` function is deprecated and shows a console warning. Use `renderHook` instead for all new code.