Strapi Jest Testing with Gitlab CI.
Edit. After publishing this article I was contacted by Strapi team which ended with this official tutorial as part of Strapi 3 documentation. Thank you Strapi team for that.
More examples are covered in the next article.
Recently I started working with amazing Strapi Headless CMS. After reading all the documentation I was quite shocked that there is not even one sentence about any kind of testing (unit, e2e, whatsoever) with that software. Also after reading comments in Github issues, Slack channel, Stack Overflow and similar resources I realised that this topic is very much neglected. This is really a shame and should be fix as soon as possible by Strapi team if they want this framework to be consider mature and professional.
Yet, I haven’t gave up on Strapi, still finding it as a great tool for rapid programming, one of the most promising in node.js world in terms of Headless CMSes. So I’ve decided to do a research on my own and write done straight forward tutorial on how to achieve easy testing. In this article I will cover topic of creating a simplest API endpoint — a heartbeat check and it’s unit test.
Installing new Strapi instance and dependencies.
I’m creating a new default settings Strapi instance by running command
yarn create strapi-app my-project --quickstart
which creates a default Strapi instance in my-project
folder. Once this is done we need some additional npm
packages, for jest testing purpose
yarn add --dev jest jest-junit junit supertest
jest
is our testing frameworkjunit
is required by Gitlab CI to display each test in Merge Request viewsupertest
will be used to test our heartbeat endpoint
Jest
when called is switching NODE_ENV
to test
which requires additional Strapi environment configuration.
Copy contents of my-project/config/environments/production
into my-project/config/environments/test
and put some changes. Edit my-project/config/environments/test/database.json
and add value "filename": ".tmp/test.db"
— reason of that is that we want to have a separate sqlite
database for tests, so our test will not touch real data. The whole file will look like this:
Getting Strapi instance for tests.
This part is one that people have most problem with, and it is the main reason this article is written.
I’ll create a folder tests
where all the tests will be put and inside it, I’ll create another folder helpers
where I’ll add main Strapi helper in file strapi.js
. File my-project/tests/helpers/strapi.js
contents is as follows.
This is all we need for writing a simple API endpoint unit test.
Heartbeat endpoint
Now let’s create a simple endpoint we’re going to test. Endpoint will serve simple purpose will expose /heartbeat
GET request that will return Hello World
. You can create this easily with Strapi CLI and the result will be as follows:
You can launch the app with npm run start
and under http://localhost:1337/heartbeat
you should see “Hello World”. This is an endpoint we’re going to unit test.
Jest unit endpoint test
I’ll write as simple Jest unit test that will test if the /heartbeat
GET request is returning Hello World
. Here is a test. Descriptions are in the comments.
Have a look on beforeAll
jest method where I call the helper mentioned in section above.
Thats the whole test, save it in file my-project/tests/app.test.js
and run it with the command:
./node_modules/.bin/jest --detectOpenHandles
which should return an output similar to
and that’s it — you’ve just created a first unit test for Strapi.
Appendix. Continuous Integration
Those test are best used within the Continuous Integration environment. Here I’ll explain how to append this to Gitlab CI, yet it would be easy to implement into any CI framework.
First of all lets add our testing commands into package.json
scripts sections:
"scripts": {
"develop": "strapi develop",
"start": "strapi start",
"build": "strapi build",
"strapi": "strapi",
"test": "./node_modules/.bin/jest --detectOpenHandles",
"test-ci": "./node_modules/.bin/jest --detectOpenHandles --forceExit --watchAll=false --reporters='jest-junit'"
}
which will allows us to run client test with npm run test
and run CI test with npm run test-ci
, please note a custom jest reporter jest-junit
.
The JUnit testing framework has introduced a XML file format to report about the test suite execution. These XML files can be processed by programs like Jenkins to display results of the tests.
My intention is that each push of code will launch a Gitlab runner, that calls all of the tests and displays result of the tests in Merge Request view:
Only when all of the tests pass user can merge code. To achieve this you need to have Gitlab with working runner(s). Here is an example gitlab.yml
configuration. You need to put this file in the main folder.
After that code is pushed each next push will trigger a pipeline that will
- Attach
node:alpine
docker with our files - Install dependencies
npm install
- Run test with
npm run test-ci
- Tests will generate junit.xml file
- Junit file will be uploaded to gitlab and displayed as a test report
- In case any test will fail, Merge Request report will give you exact details of which test failed and why
What’s next
- Here is mine github repository with some other straight forward example regarding more samples of unit testing in Strapi.
- I’ve covered the simplest possible example, yet with more sophisticated cases you would need to write some more complex helpers. In my opinion this should be delivered as a part of Strapi out of the box.
- Most components of Strapi are based on
koa
, web framework for node.js When there are no decent articles about testing for Strapi there are many on testing forkoa
— this is when you start if you want to write test for your controllers. - Code coverage is note covered in this article yet it is an essential part of Continuous Integration which is both supported by JUnit and Gitlab.