React Router Hooks (test driven)

Before running

  • npm install
  • Make sure webdb is running, see instructions in that project

Scripts

  • ./scripts/sample-data.sh
    • create sample data for the application
  • ./scripts/prepare.sh
    • fetch dependencies for the application
  • ./scripts/run.sh
    • run the application
  • ./scripts/test.sh
    • test the application
  • ./scripts/coverage.sh
    • test coverage report for the application

Requirements

  • Profiles
    • Display all profiles
    • Add a profile
    • Remove a profile
    • Navigate to tasks associated with a particular profile
  • Tasks
    • Display all tasks for a particular profile
    • Add a task
    • Mark a task as complete
    • Clear all completed tasks
    • Navigate to profiles
  • Summary
    • Display the total number of profiles
    • Display the total number of tasks
    • Be visible on every page
    • Immediately update as the underlying data changes
  • Navigation
    • Profiles and Tasks are displayed on different pages
    • Bookmarked pages should work
    • Back button should work

Intent

You should know how write a front end application that handles all of the following in a testable way

  • presentation
  • state
  • side effects
  • multiple pages
  • back button
  • an event in one component triggering a state change in another, without coupling those components together

This is a fully test driven example project that shows one way of accomplishing this.

Design Goals

  • Easy to compose
  • Easy to test
  • Easy for components to interact with each other without knowledge of implementation details

Design Style

Original Readme File (generated)

README-generated.md

How this project was created

Create project and add dependencies

npx create-react-app react-router-hooks-test-driven
cd react-router-hooks-test-driven
npm install ramda --save
npm install react-router-dom --save
npm install http-proxy-middleware --save
npm install history@^4 --save

Test coverage setup

Add the following entry to package.json

{
  "jest": {
    "collectCoverageFrom": [
      "src/**/*.{js,jsx,ts,tsx}",
      "!src/*",
      "!<rootDir>/node_modules/",
      "!src/test-util/*"
    ],
    "coverageReporters": [
      "text"
    ]
  }
}
  • In general, collect test coverage from "src/**/*.{js,jsx,ts,tsx}"
  • Since business logic is being kept out the root directory, exclude "!src/*"
  • No need to test third party modules, so exclude "!/node_modules/"
  • Don't need to test utilities that are only used in tests, so exclude "!src/test-util/*"

Proxy setup

Create file src/setupProxy.js, with the following contents

const {createProxyMiddleware} = require('http-proxy-middleware');

module.exports = function (app) {
    const options = {
        target: 'http://localhost:8080',
        changeOrigin: true,
        pathRewrite: {
            '^/proxy/': '/',
        }
    };
    app.use(
        '/proxy/',
        createProxyMiddleware(options)
    );
};

The idea here is to be specific about which http paths should render something from the source directory vs. a proxy to elsewhere. This helps prevent urls from conflicting in case a path to a proxied resource happens to match a path to a resource in the src directory. The source code adds the 'proxy' prefix indicating this is a request that should be proxied, but when proxying out externally, the proxy middleware rewrites the url, removing the proxy prefix.

Css reset

Add the file reset.css, and import it from index.js import './reset.css'

The idea here is to preserve a consistent presentation in spite of different browser css defaults, and be more explicit and intentional about what css styles are applied

Infinite Recursion on useEffect explained

How to Fix the Infinite Loop Inside “useEffect” (React Hooks)

Technology Stack