Getting Tests to Clear the DB

Fix the integration tests and add some scripts to clear the database (DB) on test runs.

We'll cover the following

We are almost done fixing the integration test for the persistence feature. As you recall, we:

  1. Wrote an integration test that verifies that tasks persist between sessions
  2. Wrote unit tests for API functions and the useTasks hook, which implements the required features
  3. Implemented the API functions and the useTasks hook.

Now we just need to make use of this hook in App.js, and the test should pass:

// /src/App.js
import React from 'react';
import TaskInput from './components/TaskInput';
import TaskList from './components/TaskList';
import useTasks from './hooks/useTasks';
import './App.css';

function App() {
  const [tasks, {createTask, toggleTask}] = useTasks();

    return (
        <div>
          <TaskInput onSubmit={createTask}/>
          <TaskList tasks={tasks} onToggleTask={toggleTask}/>
        </div>
    );
}

export default App;

Note: You do not need to have the App.css import. You just add it to ease testing.

Hotfix

Upon reaching this section, I realized that I made a small mistake that you undoubtedly followed. It is in the file api/index.js. When we send the requests to create or update tasks, it is important to include Content-Type: application/json in headers or json-server will ignore this request. Create a header object like this:

const HEADERS = {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
};

And include it into fetch calls like this:

const result = await fetch(ROOT, {
    method: 'POST',
    body: JSON.stringify(newTask),
    headers: HEADERS,
});

// and

const result = await fetch(`${ROOT}/${updatedTask.id}`, {
    method: 'PUT',
    body: JSON.stringify(updatedTask),
    headers: HEADERS,
});

Final testing

Now, you can run the app (remember, you have to npm run json-server first). You can test the persistence feature yourself. Try creating tasks, completing them, and refreshing the page. They should now be intact. However, if you run the integration tests, they will fail yet again.

If the integration tests do not fail, try running them again.

This is happening because we do not clear the database between runs. On each run, the integration tests will create the same tasks and clutter the DB. So when Selenium tries to find a specific task, it may find the old one and fail the test.

To fix this, we will create a script. A script is a file where each line is a command for the command prompt. On macOS/Linux systems, .sh files and BASH are used, whereas we will use .bat files on Windows.

PowerShell can also be used on Windows, but I think it is overkill for this particular case.

If you are on macOS/Linux, create a file called reset-db.sh in project root with this content:

#!/bin/bash
rm -f ./db.json
cp ./db.json.bak ./db.json

If you are on Windows, create a file called reset-db.bat in project root with this content:

del db.json >nul 2>&1
echo f | xcopy db.json.bak db.json

Every time you run this script, it will delete the db.json file and restore a brand new one from the backup. This means you also need to create a backup. Create a file db.json.bak in project root with this content (the initial contents of db.json):

{
  "tasks": [
    {
      "id": 1,
      "label": "Do this",
      "completed": false
    }
  ]
}

Try running the script from the command line. Do you see the db.json file being restored? Change its contents or delete the file altogether to verify that the script is working.

To run this script automatically, we will modify the scripts section of the package.json file. Find the integration-tests entry and change it to (macOS/Linux):

"integration-tests": "reset-db.sh && jest integration-tests && reset-db.sh",

Windows:

"integration-tests": "reset-db.bat && jest integration-tests && reset-db.bat",

There are many ways to achieve cross-platform config here, but they are out of the scope of this course.

Finally, once you have your npm run json-server and npm start commands running, you can run npm run integration-tests and witness all three integration tests passing! Congratulations, give yourself a pat on the back!

There may be an issue with timeouts when you run the integration tests for the very first time. This is happening because JS compiler takes time to produce a build. To get around that, run the tests one more time or add this line to jest.config.bat:

module.exports = {
  transform: {
    "^.+\\.jsx?$": "babel-jest"
  },
  testTimeout: 15000 // <<< this line
};

Here is the finalized project, for reference (Github):

Get hands-on with 1200+ tech skills courses.