Automated testing is important in software development, both during and after production, to ensure the reliability and robustness of applications. Most applications employ Jamstack
technology to separate their application backend from the frontend code, facilitating data exchange between both the frontend and backend through API calls.
For smooth interaction between the backend and frontend, it's important to test these APIs automatically. In this tutorial, we'll cover how to set up automated testing for a Strapi API using Jest and Supertest.
To follow along and complete this tutorial guide, you will need the following:
Testing Strapi API is essential for several important reasons:
Jest is a widely used JavaScript testing framework that plays an important role in the development of robust and reliable software applications. It is specifically designed to simplify and enhance the process of testing JavaScript code, making it a popular choice among developers. Jest is known for its simplicity, speed, and powerful features, empowering us to write and maintain tests efficiently, thereby contributing to the overall quality and reliability of our software applications.
Supertest is a JavaScript library commonly used for making HTTP requests and testing APIs in web applications. It is particularly valuable for testing RESTful and HTTP-based APIs in a simple and intuitive manner. Supertest is often used in conjunction with testing frameworks like Jest or Mocha to automate the process of sending HTTP requests to an API and making assertions about the responses.
SQLite is a lightweight, serverless, and self-contained relational database management system (RDBMS) that is frequently used in various software applications. Unlike traditional database systems, SQLite is known for its simplicity, portability, and compactness, which makes it a popular choice for embedded systems, mobile apps, and small-scale web applications. We will employ SQLite to establish and manage a separate, temporary database environment specifically designed for Jest tests. This temporary database ensures that the tests do not interfere with the actual data in the main database and provides a clean slate for each test run. This approach helps uphold the integrity and isolation of the tests, ensuring they consistently produce accurate results.
To install both Jest and Supertest, you need to already have a Strapi application installed. To do this, open your terminal, navigate to the folder where the Strapi app is installed, and then run the command below in the terminal.
npm install jest supertest sqlite3 --save-dev
After installing the packages, we must include Jest and Supertest in the package.json
configuration for our Strapi application. To do this, open your code editor, navigate to the root folder of your Strapi app, and open the package.json
file.
First, in the package.json
file, add the following Jest configuration to the scripts section.
1 "scripts": {
2 "develop": "strapi develop",
3 "start": "strapi start",
4 "build": "strapi build",
5 "strapi": "strapi",
6 "test": "jest --forceExit --detectOpenHandles"
7 },
Next, at the bottom of the package.json
file, add the following configurations as well.
1 "jest": {
2 "testPathIgnormnePatterns": [
3 "/node_modules/",
4 ".tmp",
5 ".cache"
6 ],
7 "testEnvironment": "node"
8 }
Your package.json
file should look similar to the one in the image below.
To set up SQLite in our Strapi application for testing with Jest, first navigate to the config
folder. Within this folder, create a new directory named env/test
. Then, create a file called database.js
in this directory. Open the database.js
file and insert the following code:
1 module.exports = ({ env }) => ({
2 connection: {
3 client: 'sqlite',
4 connection: {
5 filename: env('DATABASE_FILENAME', '.tmp/test.db'),
6 },
7 useNullAsDefault: true,
8 debug: false
9 },
10 });
To enable testing in Strapi, we need to create a specific, controllable instance of Strapi that operates in a virtual testing environment without affecting the main project.
First, let's create a folder to house all the test files. From the project's root directory, create a 'test'
folder; this folder will also contain the Strapi test installation file. Within this folder, create a strapi.js
file and add the following code.
1 const Strapi = require("@strapi/strapi");
2 const fs = require("fs");
3 let instance;
4 async function setupStrapi() {
5 if (!instance) {
6 await Strapi().load();
7 instance = strapi;
8
9 await instance.server.mount();
10 }
11 return instance;
12 }
13 async function cleanupStrapi() {
14 const dbSettings = strapi.config.get("database.connection");
15 //close server to release the db-file
16 await strapi.server.httpServer.close();
17 // close the connection to the database before deletion
18 await strapi.db.connection.destroy();
19 //delete test database after all tests have completed
20 if (dbSettings && dbSettings.connection && dbSettings.connection.filename) {
21 const tmpDbFile = dbSettings.connection.filename;
22 if (fs.existsSync(tmpDbFile)) {
23 fs.unlinkSync(tmpDbFile);
24 }
25 }
26 }
27 module.exports = { setupStrapi, cleanupStrapi };
Our first test is to verify whether the Strapi server and test instance are set up and running correctly. To accomplish this, create a test file named app.test.js
in the test folder and add the following code:
1 const fs = require('fs');
2 const { setupStrapi, cleanupStrapi } = require("./strapi");
3 beforeAll(async () => {
4 await setupStrapi();
5 });
6 afterAll(async () => {
7 await cleanupStrapi();
8 });
9 it("strapi is defined", () => {
10 expect(strapi).toBeDefined();
11 });
In this section, we will test the Strapi application's API to ensure that the GET and POST methods function as expected when making requests.
Let's create a simple collection type called ‘Book
' to be used for testing. From your Strapi dashboard menu, navigate to Content-Type Builder
→ Create new collection type
, name the collection type 'Book``,'
and then click on the Continue
button, as shown in the image below.
Next, add a "``booktitle``"
field to the collection type and then click on the "``Save``"
button.
Before we continue with our testing, let's make our book API endpoint public. To do that, navigate to Settings
→ USERS & PERMISSIONS PLUGIN
→ Roles
→ Public
→ book.
Under "book
," select all and then click on the "Save
" button, as shown below.
Let's test whether our Strapi API GET request method for the Book collection type is running successfully and returning the expected response.
Inside the 'test'
folder, create a 'get.test.js'
file and add the following code.
1const fs = require('fs');
2const { setupStrapi, cleanupStrapi } = require("./helpers/strapi");
3const request = require('supertest');
4beforeAll(async () => {
5 await setupStrapi();
6});
7afterAll(async () => {
8 await cleanupStrapi();
9});
10it("should return hello world", async () => {
11 const response = await request(strapi.server.httpServer).get("/api/books")
12 // .expect(200); // Expect response http code 200
13 .then((data) => {
14 expect(data.text).toContain('Strapi Tutorial');
15 });
16});
In the code above, we define a Jest test case that sends a GET request to the '/api/books'
endpoint of a Strapi API, expecting a 200
HTTP status code, and then verifies that the response text contains the string 'Strapi Tutorial'
.
Running the test command will show you the following output.
Let's run a test to check whether a POST request successfully inserts data into the ‘Article
' collection type.
In the 'test'
folder, create a 'post.test.js'
file and add the following code.
1const fs = require('fs');
2const { setupStrapi, cleanupStrapi } = require("./helpers/strapi");
3const request = require('supertest');
4beforeAll(async () => {
5 await setupStrapi();
6});
7afterAll(async () => {
8 await cleanupStrapi();
9});
10const mockData = {
11 data:{ fullname: "popoola"}
12 };
13it("should return hello world", async () => {
14 const response = await request(strapi.server.httpServer).post("/api/books")
15 .set("accept", "application/json")
16 .set("Content-Type", "application/json")
17 .send(mockData)
18 .then((data) => {
19 expect(data.text).toContain('Getting started with strapi');
20 });
21});
In the code above, we define a Jest test case that sends a POST request to the "/api/books"
endpoint of a Strapi API, with specific headers and data, and then verifies that the response text contains the string 'Getting started with strapi'
.
We can also test Strapi user authentication endpoints. First, we'll test the functionality of user login JWT by making a POST request to the 'api/auth/local'
endpoint. Create a new test file named 'auth.test.js'
and add the following.
1const fs = require('fs');
2const { setupStrapi, cleanupStrapi } = require("./strapi");
3const request = require('supertest');
4beforeAll(async () => {
5 await setupStrapi();
6});
7afterAll(async () => {
8 await cleanupStrapi();
9});
10// user mock data
11const mockUserData = {
12 username: "tester",
13 email: "tester@strapi.com",
14 provider: "local",
15 password: "1234abc",
16 confirmed: true,
17 blocked: null,
18};
19it("should login user and return jwt token", async () => {
20 /** Creates a new user and save it to the database */
21 await strapi.plugins["users-permissions"].services.user.add({
22 ...mockUserData,
23 });
24 await request(strapi.server.httpServer)
25 .post("/api/auth/local")
26 .set("accept", "application/json")
27 .set("Content-Type", "application/json")
28 .send({
29 identifier: mockUserData.email,
30 password: mockUserData.password,
31 })
32 .expect("Content-Type", /json/)
33 .expect(200)
34 .then((data) => {
35 expect(data.body.jwt).toBeDefined();
36 });
37});
In the code above,we used a Jest test case to verify the functionality of user login and JWT token generation by creating a new user with mock data and sending a POST request to the "/api/auth/local"
endpoint using the provided user credentials, expecting to receive a JWT token as a response.
This article guided you through setting up automated testing for a Strapi API with Jest and Supertest. By adopting this method of automated testing, we ensure rigorous monitoring and verification of the Strapi API endpoints, guaranteeing they operate as intended.