DEV Community

Cover image for How to create integration test with Cypress in your Next.js project
Alexandre C.
Alexandre C.

Posted on

How to create integration test with Cypress in your Next.js project

In this tutorial we'll describe how you can use Cypress to test your Next.js application, so that you can be more confident when writing or refactoring code.

What is Cypress ?

Cypress is a Javascript end-to-end test framework. It allows you to test your application directly in the browser, with React it's a perfect match because you can test each of your component in the browser and visually see what's wrong and where.
You can learn more about it and how it works here

Generate a Next.js app

npx create-next-app
or
yarn create next-app
and follow the instructions

If you prefer to use Typescript

npx create-next-app --typescript
or
yarn create next-app --typescript

Install Cypress

npm install cypress --save-dev or yarn add cypress -D

In your package.json add a script line

"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "cypress:open": "cypress open"
  },
Enter fullscreen mode Exit fullscreen mode

If you use Typescript make sure you add cypress types in your tsconfig.json file

"compilerOptions": {
    ...
    "types": ["cypress"]
  },
Enter fullscreen mode Exit fullscreen mode

Run Cypress

npm run cypress:open or yarn cypress:open will run Cypress for the first time. It will generate automatically every necessary files for you and tests examples in a cypress folder at the root of your project, and open a dedicated page in your browser

Cypress in browser screenshot

You can try running the integration tests examples

Integration tests examples running screenshot

These files can be found in your cypress/integration folder. You can delete all of them as we'll write our own one.

Write your first integration test

Under cypress/integration folder create a home.spec.js file (or home.spec.tsx if you use typescript) and add

/// <reference types="cypress"/>

context("Home Page", () => {
  beforeEach(() => {
    cy.visit("http://localhost:3000");
  });

  it("should render the home page and display a message", () => {
    cy.get("h1").contains("Welcome");
  });
});
Enter fullscreen mode Exit fullscreen mode

If you use Typescript add export {} to bypass Eslint compilation error

/// <reference types="cypress"/>

context("Home Page", () => {
  beforeEach(() => {
    cy.visit("http://localhost:3000");
  });

  it("should render the home page and display a message", () => {
    cy.get("h1").contains("Welcome");
  });
});

export {}
Enter fullscreen mode Exit fullscreen mode

Here we are telling Cypress each time it runs the test it should first navigate to the homepage, and search for a <h1> tag containing "Welcome"

If your run this test now it will fail and that's normal

Failed test

To make it work we need to run our server first and launch the tests, to automate this behavior we will install a library called start-server-and-test

npm install start-server-and-test --save-dev
or
yarn add start-server-and-test -D

Add a script in your package.json

"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "cypress:open": "cypress open",
    "test": "start-server-and-test dev 3000 cypress:open"
  },
Enter fullscreen mode Exit fullscreen mode

You can now run
npm run test
or
yarn test

To execute your test and it should work

Working test

I will make the test fail again by replacing the word "Welcome" by "Bonjour" and Cypress automatically detect where the test has failed

Second test failed

Now that you understand how Cypress is testing your component you can write your own tests based on what you want to test, and enjoy the visual regression tool in the browser embedded by Cypress 🥳

How to test getStaticProps

To show how we can perform Cypress test on props coming from getStaticProps I have created a file called stack.js under pages folder

// stack.js

const Stack = (props) => {
  const favorites = props.stack;

  return (
    <div style={{display: 'flex', justifyContent: 'center', padding: '2rem'}}>
      <main>
        <h1>My Favorites Stack</h1>
        <ul>
          {favorites.map((favorite) => {
            return <li key={favorite}>{favorite}</li>;
          })}
        </ul>
      </main>
    </div>
  );
};

export default Stack;

export async function getStaticProps() {
  const favoriteStack = [
    'Javascript',
    'TypeScript',
    'React.js',
    'Next.js',
    'GraphQL',
    'Amazon Web Services',
    'Firebase',
  ];

  return {
    props: {
      stack: favoriteStack
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The goal is to make sure that we receive the correct props, so
we can create a stack.spec.js

/// <reference types="cypress"/>

const favoriteStack = [
  'Javascript',
  'TypeScript',
  'React.js',
  'Next.js',
  'GraphQL',
  'Amazon Web Services',
  'Firebase',
];

context('Stack', () => {
  beforeEach(() => {
    cy.visit('http://localhost:3000/stack');
  });

  it('should render the stack page and display the favorite stack', () => {
    cy.get('ul>li').each((item, index) => {
      cy.wrap(item).should('contain.text', favoriteStack[index]);
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

Here the test should pass because we are receiving the exact same props that we are passing in our component

Stack test

You can make the test fails by modifying any of the array item and Cypress should show you where it failed, for example here I expect to find "MongoDB" value instead of "Firebase"

Stack test failed

How to test getServerSideProps

It should work the same way as for getStaticProps. To demonstrate this we create a new file under pages platforms.js

const Platforms = (props) => {
  const favorites = props.stack;

  return (
    <div style={{display: 'flex', justifyContent: 'center', padding: '2rem'}}>
      <main>
        <h1>My Favorites Freelance platforms</h1>
        <ul>
          {favorites.map((favorite) => {
            return <li key={favorite}>{favorite}</li>;
          })}
        </ul>
      </main>
    </div>
  );
};

export default Platforms;

export async function getServerSideProps() {
  const favoritesPlatforms = [
    'Toptal',
    'Upwork',
    'Malt',
    'Comet'
  ];

  return {
    props: {
      stack: favoritesPlatforms
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Then we add our test platforms.spec.js

/// <reference types="cypress"/>

const favoritePlatforms = ['Toptal', 'Upwork', 'Malt', 'Comet'];

context('Platforms', () => {
  beforeEach(() => {
    cy.visit('http://localhost:3000/platforms');
  });

  it('should render the platforms page and display the favorite platforms', () => {
    cy.get('ul>li').each((item, index) => {
      cy.wrap(item).should('contain.text', favoritePlatforms[index]);
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

And you can see it's working 🎉

getServerSideProps test

Conclusion

Now you understand how Cypress can work with your Next.js project you can create your own tests based on your scenarios. Enjoy it!

Top comments (2)

Collapse
 
franciscokloganb profile image
Francisco Barros

This guide really does not teach how you mock requests made by getServerSide and getStaticProps. Hard-coded it works, but once you add api/routes or requests to third-party services on those page methods, this fails.

Collapse
 
glennriney profile image
Glennriney

Thanks so much for your toturial and for the screenshots especially! Never worked with Cypress before, but that was very informative