Mastering React Test-Driven Development - Second Edition

Book description

Learn test-driven and behavior-driven development techniques that will give you greater confidence when building React applications

Key Features

  • Explore the TDD process, how it works, and why it will help you write maintainable React apps
  • Develop a component testing framework from scratch, which will help you understand the mechanics of good unit testing
  • Reduce complexity by using unit tests and end-to-end acceptance tests to drive the design of your apps

Book Description

Test-driven development (TDD) is a programming workflow that helps you build your apps by specifying behavior as automated tests. The TDD workflow future-proofs apps so that they can be modified without fear of breaking existing functionality. Another benefit of TDD is that it helps software development teams communicate their intentions more clearly, by way of test specifications.

This book teaches you how to apply TDD when building React apps. You'll create a sample app using the same React libraries and tools that professional React developers use, such as Jest, React Router, Redux, Relay (GraphQL), Cucumber, and Puppeteer. The TDD workflow is supported by various testing techniques and patterns, which are useful even if you're not following the TDD process. This book covers these techniques by walking you through the creation of a component test framework. You'll learn automated testing theory which will help you work with any of the test libraries that are in standard usage today, such as React Testing Library. This second edition has been revised with a stronger focus on concise code examples and has been fully updated for React 18.

By the end of this TDD book, you'll be able to use React, Redux, and GraphQL to develop robust web apps.

What you will learn

  • Build test-driven applications using React 18 and Jest
  • Understand techniques and patterns for writing great automated tests
  • Use test doubles and mocks effectively
  • Test-drive browser APIs, including the Fetch API and the WebSocket API
  • Integrate with libraries such as React Router, Redux, and Relay (GraphQL)
  • Use Cucumber.js and Puppeteer to build Behaviour- Driven Development (BDD) style tests for your applications
  • Build and test async Redux code using redux-saga and expect-redux

Who this book is for

This book is for frontend developers who are looking to improve their testing practices and increase the quality and maintainability of their applications. To make the most of this book, you'll need knowledge of the JavaScript programming language.

Publisher resources

Download Example Code

Table of contents

  1. Mastering React Test-Driven Development
  2. Second Edition
  3. Foreword
  4. Contributors
  5. About the author
  6. About the reviewer
  7. Preface
    1. Who this book is for
    2. What this book covers
    3. To get the most out of this book
    4. Download the example code files
    5. Download the color images
    6. Conventions used
      1. Code snippet conventions
      2. JavaScript conventions
    7. Get in touch
    8. Share Your Thoughts
  8. Part 1 – Exploring the TDD Workflow
  9. Chapter 1: First Steps with Test-Driven Development
    1. Technical requirements
    2. Creating a new React project from scratch
      1. Installing npm
      2. Creating a new Jest project
      3. Bringing in React and Babel
    3. Displaying data with your first test
      1. Writing a failing test
      2. Make it pass
      3. Making use of the act test helper
      4. Triangulating to remove hardcoding
      5. Backtracking on ourselves
    4. Refactoring your work
      1. Sharing setup code between tests
      2. Extracting methods
    5. Writing great tests
      1. Red, green, refactor
      2. Streamlining your testing process
    6. Summary
    7. Further reading
  10. Chapter 2: Rendering Lists and Detail Views
    1. Technical requirements
    2. Sketching a mock-up
    3. Creating the new component
    4. Specifying list item content
    5. Selecting data to view
      1. Initial selection of data
      2. Adding events to a functional component
    6. Manually testing our changes
      1. Adding an entry point
      2. Putting it all together with webpack
    7. Summary
    8. Exercises
    9. Further reading
  11. Chapter 3: Refactoring the Test Suite
    1. Technical requirements
    2. Pulling out reusable rendering logic
    3. Creating a Jest matcher using TDD
    4. Extracting DOM helpers
    5. Summary
    6. Exercises
    7. Further reading
  12. Chapter 4: Test-Driving Data Input
    1. Technical requirements
    2. Adding a form element
    3. Accepting text input
    4. Submitting a form
      1. Submitting without any changes
      2. Preventing the default submit action
      3. Submitting changed values
    5. Duplicating tests for multiple form fields
      1. Nesting describe blocks
      2. Generating parameterized tests
      3. Solving a batch of tests
      4. Modifying handleChange so that it works with multiple fields
      5. Testing it out
    6. Summary
    7. Exercises
  13. Chapter 5: Adding Complex Form Interactions
    1. Technical requirements
    2. Choosing a value from a select box
      1. Providing select box options
      2. Preselecting a value
    3. Constructing a calendar view
      1. Adding the table
      2. Adding a header column
      3. Adding a header row
    4. Test-driving radio button groups
      1. Hiding input controls
      2. Selecting a radio button in a group
      3. Handling field changes through a component hierarchy
    5. Reducing effort when constructing components
      1. Extracting test data builders for time and date functions
      2. Extracting a test props object
    6. Summary
    7. Exercises
    8. Further reading
  14. Chapter 6: Exploring Test Doubles
    1. Technical requirements
    2. What is a test double?
      1. Learning to avoid fakes
    3. Submitting forms using spies
      1. Untangling AAA
      2. Making a reusable spy function
      3. Using a matcher to simplify spy expectations
    4. Spying on the fetch API
      1. Replacing global functions with spies
      2. Test-driving fetch argument values
      3. Reworking existing tests with the side-by-side implementation
      4. Improving spy expectations with helper functions
    5. Stubbing fetch responses
      1. Upgrading spies to stubs
      2. Acting on the fetch response
      3. Displaying errors to the user
      4. Grouping stub scenarios in nested describe contexts
    6. Migrating to Jest’s built-in test double support
      1. Using Jest to spy and stub
      2. Migrating the test suite to use Jest’s test double support
      3. Extracting fetch test functionality
    7. Summary
    8. Exercises
    9. Further reading
  15. Chapter 7: Testing useEffect and Mocking Components
    1. Technical requirements
    2. Mocking child components
      1. How to mock components, and why?
      2. Testing the initial component props
    3. Fetching data on mount with useEffect
      1. Understanding the useEffect hook
      2. Adding the renderAndWait helper
      3. Adding the useEffect hook
      4. Testing the useEffect dependency list
    4. Building matchers for component mocks
    5. Variants of the jest.mock call
      1. Removing the spy function
      2. Rendering the children of mocked components
      3. Checking multiple instances of the rendered component
      4. Alternatives to module mocks
    6. Summary
    7. Exercises
    8. Further reading
  16. Chapter 8: Building an Application Component
    1. Technical requirements
    2. Formulating a plan
    3. Using state to control the active view
    4. Test-driving callback props
    5. Making use of callback values
    6. Summary
    7. Exercises
  17. Part 2 – Building Application Features
  18. Chapter 9: Form Validation
    1. Technical requirements
    2. Performing client-side validation
      1. Validating a required field
      2. Generalizing validation for multiple fields
      3. Submitting the form
      4. Extracting non-React functionality into a new module
    3. Handling server errors
    4. Indicating form submission status
      1. Testing state before promise completion
      2. Refactoring long methods
    5. Summary
    6. Exercises
    7. Further reading
  19. Chapter 10: Filtering and Searching Data
    1. Technical requirements
    2. Displaying tabular data fetched from an endpoint
    3. Paging through a large dataset
      1. Adding a button to move to the next page
      2. Adjusting the design
      3. Adding a button to move to the previous page
      4. Forcing design changes using tests
    4. Filtering data
      1. Refactoring to simplify the component design
    5. Performing actions with render props
      1. Testing render props in additional render contexts
    6. Summary
    7. Exercises
  20. Chapter 11: Test-Driving React Router
    1. Technical requirements
    2. Designing React Router applications from a test-first perspective
      1. A list of all the React Router pieces
      2. Splitting tests when the window location changes
      3. Up-front design for our new routes
    3. Testing components within a router
      1. The Router component and its test equivalent
      2. Using the Routes component to replace a switch statement
      3. Using intermediate components to translate URL state
    4. Testing router links
      1. Checking the page for hyperlinks
      2. Mocking the Link component
    5. Testing programmatic navigation
    6. Summary
    7. Exercise
    8. Further reading
  21. Chapter 12: Test-Driving Redux
    1. Technical requirements
    2. Up-front design for a reducer and a saga
      1. Why Redux?
      2. Designing the store state and actions
    3. Test-driving a reducer
      1. Pulling out generator functions for reducer actions
      2. Setting up a store and an entry point
    4. Test-driving a saga
      1. Using expect-redux to write expectations
      2. Making asynchronous requests with sagas
    5. Switching component state for Redux state
      1. Submitting a React form by dispatching a Redux action
      2. Making use of store state within a component
      3. Navigating router history in a Redux saga
    6. Summary
    7. Exercise
    8. Further reading
  22. Chapter 13: Test-Driving GraphQL
    1. Technical requirements
    2. Compiling the schema before you begin
    3. Testing the Relay environment
      1. Building a performFetch function
      2. Test-driving the Environment object construction
      3. Test-driving a singleton instance of Environment
    4. Fetching GraphQL data from within a component
    5. Summary
    6. Exercises
    7. Further reading
  23. Part 3 – Interactivity
  24. Chapter 14: Building a Logo Interpreter
    1. Technical requirements
    2. Studying the Spec Logo user interface
    3. Undoing and redoing user actions in Redux
      1. Building the reducer
      2. Building buttons
    4. Saving to local storage via Redux middleware
      1. Building middleware
    5. Changing keyboard focus
      1. Writing the reducer
      2. Focusing the prompt
      3. Requesting focus in other components
    6. Summary
    7. Further reading
  25. Chapter 15: Adding Animation
    1. Technical requirements
    2. Designing animation
    3. Building an animated line component
    4. Animating with requestAnimationFrame
    5. Canceling animations with cancelAnimationFrame
    6. Varying animation behavior
    7. Summary
    8. Exercises
  26. Chapter 16: Working with WebSockets
    1. Technical requirements
    2. Designing a WebSocket interaction
      1. The sharing workflow
      2. The new UI elements
      3. Splitting apart the saga
    3. Test-driving a WebSocket connection
    4. Streaming events with redux-saga
    5. Updating the app
    6. Summary
    7. Exercises
    8. Further reading
  27. Part 4 – Behavior-Driven Development with Cucumber
  28. Chapter 17: Writing Your First Cucumber Test
    1. Technical requirements
    2. Integrating Cucumber and Puppeteer into your code base
    3. Writing your first Cucumber test
    4. Using data tables to perform setup
    5. Summary
  29. Chapter 18: Adding Features Guided by Cucumber Tests
    1. Technical requirements
    2. Adding Cucumber tests for a dialog box
    3. Fixing Cucumber tests by test-driving production code
      1. Adding a dialog box
      2. Updating sagas to a reset or replay state
    4. Avoiding timeouts in test code
      1. Adding HTML classes to mark animation status
      2. Updating step definitions to use waitForSelector
    5. Summary
    6. Exercise
  30. Chapter 19: Understanding TDD in the Wider Testing Landscape
    1. Test-driven development as a testing technique
      1. Best practices for your unit tests
      2. Improving your technique
    2. Manual testing
      1. Demonstrating software
      2. Testing the whole product
      3. Exploratory testing
      4. Debugging in the browser
    3. Automated testing
      1. Integration tests
      2. System tests and end-to-end tests
      3. Acceptance tests
      4. Property-based and generative testing
      5. Snapshot testing
      6. Canary testing
    4. Not testing at all
      1. When quality doesn’t matter
      2. Spiking and deleting code
    5. Summary
    6. Further reading
  31. Index
    1. Why subscribe?
  32. Other Books You May Enjoy
    1. Packt is searching for authors like you

Product information

  • Title: Mastering React Test-Driven Development - Second Edition
  • Author(s): Daniel Irvine, Justin Searls
  • Release date: September 2022
  • Publisher(s): Packt Publishing
  • ISBN: 9781803247120