End-to-End Testing with Node.js
Published: 2024-05-17 23:25:53

End-to-End (E2E) testing is like walking through your application as a user would. It helps you ensure that everything works together as expected. In this tutorial, we'll set up E2E testing for a Node.js application using Jest and Puppeteer. Let’s get started!

## Creating a New Node.js Project
First, we'll create a new directory for our project and initialize a new Node.js project.

Open your terminal and run the following commands:
```
mkdir e2e-testing
cd e2e-testing
npm init -y
```
This will create a new directory named e2e-testing and initialize a Node.js project inside it.

## Installing Express
Next, we'll install Express, a popular Node.js framework for building web applications.

```
npm install express
```
## Creating a Simple Express Server
Now, let's create a simple Express server. Create a file named `app.js` and add the following code:

```
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello, world!');
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});
```
This code sets up a basic server that responds with "Hello, world!" when you visit the root URL.

## Running Your Server
Run your server by executing the following command in your terminal:

```
node app.js
```
You should see a message saying Example app listening at `http://localhost:3000`. Open your browser and navigate to `http://localhost:3000` to see the message.

## Installing Jest and Puppeteer
We need Jest for our testing framework and Puppeteer to control a headless browser for our E2E tests.

```
npm install --save-dev jest puppeteer
```
## Configuring Jest
We'll configure Jest to use Puppeteer. In your package.json file, add the following Jest configuration:

```
"scripts": {
  "test": "jest"
},
"jest": {
  "preset": "jest-puppeteer"
}
```
## Installing Jest-Puppeteer Preset
We need to install the Jest-Puppeteer preset to integrate Jest with Puppeteer seamlessly.

```
npm install --save-dev jest-puppeteer
```
## Creating a Jest Configuration File
Create a file named `jest-puppeteer.config.js` with the following content:

```
module.exports = {
  launch: {
    headless: true, // set to false if you want to see the browser while testing
  },
};
```
This configuration tells Puppeteer to run in headless mode (without a visible browser).

## Creating a Test Directory
Create a directory named tests to store our test files.

```
mkdir tests
```
## Creating a Test File
Inside the tests directory, create a file named app.test.js and add the following code:

```
const puppeteer = require('puppeteer');

describe('App', () => {
  let browser;
  let page;

  beforeAll(async () => {
    browser = await puppeteer.launch();
    page = await browser.newPage();
  });

  afterAll(async () => {
    await browser.close();
  });

  test('should display "Hello, world!" on the home page', async () => {
    await page.goto('http://localhost:3000');
    await page.waitForSelector('body');
    const text = await page.$eval('body', (e) => e.textContent);
    expect(text).toContain('Hello, world!');
  });
});
```
## Running Your Test
Run your test by executing the following command:

```
npm test
```
Jest will start Puppeteer, open a browser, navigate to http://localhost:3000, and check if the text "Hello, world!" is present on the page. If everything is set up correctly, the test should pass.

## Advanced Testing
Now, let's add more functionality to our application and write tests for it.

## Update Your Express Server
Modify `app.js` to include a simple form that greets the user:

```
const express = require('express');
const app = express();
const port = 3000;

app.use(express.urlencoded({ extended: true }));

app.get('/', (req, res) => {
  res.send(`
    <form action="/greet" method="post">
      <input type="text" name="name" placeholder="Enter your name" />
      <button type="submit">Submit</button>
    </form>
  `);
});

app.post('/greet', (req, res) => {
  const name = req.body.name;
  res.send(`Hello, ${name}!`);
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});
```
## Writing a Test for the Form
Add a new test in `app.test.js`:

```
test('should submit the form and display a greeting', async () => {
  await page.goto('http://localhost:3000');
  await page.type('input[name=name]', 'John');
  await page.click('button[type=submit]');
  await page.waitForSelector('body');
  const text = await page.$eval('body', (e) => e.textContent);
  expect(text).toBe('Hello, John!');
});
```
## Running Your Tests Again
Run your tests by executing the command:

```
npm test
```
Puppeteer will open the form, type a name into the input field, submit the form, and check if the greeting message is displayed correctly.

## Conclusion
You've successfully set up and run End-to-End tests for a Node.js application using Jest and Puppeteer! We covered: