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.
Prerequisites
To follow along and complete this tutorial guide, you will need the following:
- Node and Npm installed.
- Strapi app installed on your system.
- Understand of how to customize Strapi app.
- A basic understanding of Jest and Supertest.
Why testing Strapi API?
Testing Strapi API is essential for several important reasons:
- Reliability: Testing helps ensure that your Strapi API functions as intended. It verifies that your endpoints return the expected results and perform correctly under various scenarios.
- Bug Detection: Testing helps identify and catch bugs, errors, or unexpected behaviors early in the development process. This allows you to address issues before they reach production, reducing the risk of critical errors affecting your users.
- Maintainability: Automated tests make it easier to maintain your Strapi API over time. When you make changes or refactor code, tests help ensure that your modifications do not introduce new issues.
- Performance: You can create performance tests to evaluate how well your Strapi API performs under various loads. This helps you optimize your application for better scalability and responsiveness.
What Is Jest?
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.
What is Supertest?
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.
What is SQLite?
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.
Installing Jest and Supertest
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
Setting up Jest and Supertest
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.
Configuring Sqlite
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 });
Set Up Strapi Testing Instance
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 };
Testing Strapi API
Testing Strapi Instance
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 });
Testing Strapi's API Response
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.
Testing GET Strapi Request
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.
Testing POST Strapi Request
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'
.
Testing Strapi auth Endpoint
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.
Conclusion
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.