1. Software requirements

This tutorial was only tested on Ubuntu 22.04.

2. Creating the project

$ mkdir -p game && cd $_

$ npm init -y

$ npm install express

$ cat > index.js <<'EOF'
const express = require('express')
const app = express()

const result = {
  "rounds": 1000,
  "playersBalances": [
    { "cautious": 100 },
    { "random": 80 },
    { "demanding": 40 },
    { "impulsive": 30 }
  ]
}

app.get('/', (req, res) => {
  res.setHeader('Content-Type', 'application/json')
  res.end(JSON.stringify(result))
})

app.listen(8080)
EOF

$ node index.js &> game.log &

$ http localhost:8080

$ kill %1

Initial commit:

$ git init

$ cat > .gitignore <<'EOF'
/node_modules
*.log
EOF

$ git add .
$ git status
$ git commit -m 'Initial commit'

3. Adding Jest and SuperTest

$ npm install -D jest supertest
$ git apply <<'EOF'
diff --git a/package.json b/package.json
index e7a65a7..e6c60fd 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
   "description": "",
   "main": "index.js",
   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "jest"
   },
   "keywords": [],
   "author": "",
@@ -15,5 +15,11 @@
   "devDependencies": {
     "jest": "^28.1.3",
     "supertest": "^6.2.4"
+  },
+  "jest": {
+    "testEnvironment": "node",
+    "coveragePathIgnorePatterns": [
+      "/node_modules"
+    ]
   }
 }
EOF
$ npm test

> game@1.0.0 test
> jest

No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In /home/pj/Downloads/desabio-bp/game
  3 files checked.
  testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 0 matches
  testPathIgnorePatterns: /node_modules/ - 3 matches
  testRegex:  - 0 matches
Pattern:  - 0 matches
$ cat > sample.test.js <<'EOF'
describe('Sample Test', () => {
  it('should test tha true === true', () => {
    expect(true).toBe(true)
  })
})
EOF

$ npm test
$ git add .
$ git status
$ git commit -m 'Added configuration for Jest and SuperTest'

4. Creating a basic API test

First, a little refactoring:

$ git apply <<'EOF'
diff --git a/index.js b/index.js
index c1a3811..f6682c5 100644
--- a/index.js
+++ b/index.js
@@ -16,4 +16,4 @@ app.get('/', (req, res) => {
   res.end(JSON.stringify(result))
 })

-app.listen(8080)
+module.exports = app
EOF
$ cat > app.js <<'EOF'
const app = require('./index')

app.listen(8080)
EOF
$ node app.js &> game.log &

$ http localhost:8080

$ kill %1

Now, let’s create a basic test:

$ cat > index.test.js <<'EOF'
const supertest = require('supertest')
const app = require('./index')

test('GET /', async () => {
  const response = await supertest(app).get('/')

  expect(response.statusCode).toEqual(200)
  expect(response.body.rounds).toEqual(1000)
})
EOF

Do our test again:

$ npm test

> game@1.0.0 test
> jest

 PASS  ./index.test.js
 PASS  ./sample.test.js

Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.429 s, estimated 1 s
Ran all test suites.

Remove sample.test.js (we don’t need it anymore):

$ rm sample.test.js

Let’s commit our basic test:

$ git add .
$ git status
$ git commit -m 'Added a first SuperTest'

5. Improving the API test

$ git apply <<'EOF'
diff --git a/index.test.js b/index.test.js
index 8498451..a9f5cbf 100644
--- a/index.test.js
+++ b/index.test.js
@@ -1,9 +1,12 @@
 const supertest = require('supertest')
 const app = require('./index')

-test('GET /', async () => {
-  const response = await supertest(app).get('/')
-
-  expect(response.statusCode).toEqual(200)
-  expect(response.body.rounds).toEqual(1000)
+describe('GET /', () => {
+  it('responds with json', (done) => {
+    supertest(app)
+      .get('/')
+      .set('Accept', 'application/json')
+      .expect('Content-Type', /json/)
+      .expect(200, done)
+  })
 })
EOF
$ npm test
$ git add .
$ git apply <<'EOF'
diff --git a/index.test.js b/index.test.js
index a9f5cbf..385822e 100644
--- a/index.test.js
+++ b/index.test.js
@@ -1,12 +1,28 @@
 const supertest = require('supertest')
 const app = require('./index')

+const isSorted = (arr) =>
+  !!arr.reduce((n, item) => n !== false && item >= n && item)
+
 describe('GET /', () => {
-  it('responds with json', (done) => {
-    supertest(app)
+  it('responds with a valid json', async () => {
+    const response = await supertest(app)
       .get('/')
       .set('Accept', 'application/json')
-      .expect('Content-Type', /json/)
-      .expect(200, done)
+    expect(response.headers['content-type']).toMatch(/json/)
+    expect(response.status).toEqual(200)
+
+    // check if the number of rounds was defined and it is numeric
+    expect(typeof response.body.rounds).toBe('number')
+
+    const playersBalances = response.body.playersBalances
+
+    // check if we have four players
+    expect(playersBalances).toBeDefined()
+    expect(playersBalances.length).toBe(4)
+
+    // create an array with balances and check if it is Sorted
+    const balances = playersBalances.map(o => Object.values(o)[0]).reverse()
+    expect(isSorted(balances)).toBe(true)
   })
 })
EOF
$ npm test
$ git add .
$ git commit 'Improved the API test'