1
votes

I am trying to generate istanbul code coverage for my api.I have looked into many answers in SO and also the doc of istanbul but nothing is working for me. mocha tests are running fine and everything is getting passed, even istanbul is creating the coverage folder also, but it is not creating the report within it.My app is simple express app and I am using chai,chai-http and mocha for it. below is my code for test/app.js file and package.json file.

const app=require('../app');
const chai=require('chai');
const chaiHttp=require('chai-http');
const should=chai.should();
const tokenForToday="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImFudXJhbmJhcm1hbkBnbWFpbC5jb20iLCJpYXQiOjE1MTc1Mzg4ODcsImV4cCI6MTUxNzYyNTI4N30.8YJ35mwWhzz4kT-fruhcPANUXyZJYvCsKKHTejZNnWA";
chai.use(chaiHttp);

describe('CB API',()=>{
    /**
     * Test /api route
     */

    describe('/GET api',()=>{
      it('it should GET the api default content', (done) => {
      chai.request(app)
          .get('/api')
          .end((err, res) => {
              res.should.have.status(200);
              res.body.should.be.eql({message:'Welcome to Cloudboost API'});
            done();
          });
      });
    })

    /**
     * Test /login POST route
     */
     describe('/POST login',()=>{
       it('it should return the authentication token', (done) => {
         let bdy={
           email:"[email protected]",
           password:"anuran"
         }
       chai.request(app)
           .post('/api/login')
           .send(bdy)
           .end((err, res) => {
               res.should.have.status(200);
               res.body.should.have.property('token');
               res.body.should.have.property('auth').eql(true);
             done();
           });
       });
     })

     /**
      * Test /login POST without email field
      */
      describe('/POST login',()=>{
        it('it should return false success', (done) => {
          let bdy={
            password:"anuran"
          }
        chai.request(app)
            .post('/api/login')
            .send(bdy)
            .end((err, res) => {
                res.should.have.status(422);
                res.body.should.have.property('auth').eql(false);
              done();
            });
        });
      })

      /**
       * Test /image route without token
       */
       describe('/POST image without token',()=>{
         it('it should return false success', (done) => {
           let bdy={
             url:"https://d1qb2nb5cznatu.cloudfront.net/startups/i/490103-917cc2864d0246e313e9521971422f09-medium_jpg.jpg?buster=1430997518"
           }
         chai.request(app)
             .post('/api/image')
             .send(bdy)
             .end((err, res) => {
                 res.should.have.status(401);
                 res.body.should.have.property('success').eql(false);
               done();
             });
         });
       })

       /**
        * Test /image with token but with invalid url
        */
        describe('/POST image with invalid url',()=>{
          it('it should return false success', (done) => {
            let bdy={
              url:"https://d1qb2nb5cznatu.cloudfrt.net/startups/i/490103-917cc2864d0246e313e9521971422f09-medium_jpg.jpg?buster=1430997518"
            }
          chai.request(app)
              .post('/api/image')
              .set('token',tokenForToday)
              .send(bdy)
              .end((err, res) => {
                  res.should.have.status(500);
                  res.body.should.have.property('success').eql(false);
                done();
              });
          });
        })

        /**
         * Test /image with token but with NO url
         */
         describe('/POST image with no url',()=>{
           it('it should return false success', (done) => {

           chai.request(app)
               .post('/api/image')
               .set('token',tokenForToday)
               .end((err, res) => {
                   res.should.have.status(422);
                   res.body.should.have.property('success').eql(false);
                 done();
               });
           });
         })

         /**
          * Test /image with token and with valid url
          */
          describe('/POST image',()=>{
            it('it should return false success', (done) => {
              let bdy={
                url:"https://d1qb2nb5cznatu.cloudfront.net/startups/i/490103-917cc2864d0246e313e9521971422f09-medium_jpg.jpg?buster=1430997518"
              }
            chai.request(app)
                .post('/api/image')
                .set('token',tokenForToday)
                .send(bdy)
                .end((err, res) => {
                    res.should.have.status(200);
                  done();
                });
            });
          })


          /**
           * Test /image with invalid token but with valid url
           */
           describe('/POST image',()=>{
             it('it should return false success', (done) => {
               let bdy={
                 url:"https://d1qb2nb5cznatu.cloudfront.net/startups/i/490103-917cc2864d0246e313e9521971422f09-medium_jpg.jpg?buster=1430997518"
               }
             chai.request(app)
                 .post('/api/image')
                 .set('token','tokenForToday')
                 .send(bdy)
                 .end((err, res) => {
                     res.should.have.status(500);
                     res.body.should.have.property('success').eql(false);
                   done();
                 });
             });
           })

           /**
            * Test /patch with token and data and patch
            */
            describe('/PATCH patch',()=>{
              it('it should return success', (done) => {
                const dataString=JSON.stringify({
                        name: "dante",
                        age: "22"
                });
                const patchString=JSON.stringify([
                  { "op": "replace", "path": "/name", "value": "anuran" },
                  { "op": "add", "path": "/position", "value": "NodeJS Developer" }
                ])
                let bdy={
                  data:dataString,
                  patch:patchString
                }

              chai.request(app)
                  .patch('/api/patch')
                  .set('token',tokenForToday)
                  .set('content-type', 'application/x-www-form-urlencoded')
                  .send(bdy)
                  .end((err, res) => {
                    console.log(res.body);
                      res.should.have.status(200);
                      res.body.should.have.property('success').eql(true);
                    done();
                  });
              });
            })


            /**
             * Test /patch without token
             */
             describe('/PATCH patch',()=>{
               it('it should return false success', (done) => {
                 const dataString=JSON.stringify({
                         name: "dante",
                         age: "22"
                 });
                 const patchString=JSON.stringify([
                   { "op": "replace", "path": "/name", "value": "anuran" },
                   { "op": "add", "path": "/position", "value": "NodeJS Developer" }
                 ])
                 let bdy={
                   data:dataString,
                   patch:patchString
                 }

               chai.request(app)
                   .patch('/api/patch')
                   .set('content-type', 'application/x-www-form-urlencoded')
                   .send(bdy)
                   .end((err, res) => {
                     console.log(res.body);
                       res.should.have.status(422);
                       res.body.should.have.property('success').eql(false);
                     done();
                   });
               });
             })


             /**
              * Test /patch without data field
              */
              describe('/PATCH patch',()=>{
                it('it should return false', (done) => {

                  const patchString=JSON.stringify([
                    { "op": "replace", "path": "/name", "value": "anuran" },
                    { "op": "add", "path": "/position", "value": "NodeJS Developer" }
                  ])
                  let bdy={
                    patch:patchString
                  }

                chai.request(app)
                    .patch('/api/patch')
                    .set('token',tokenForToday)
                    .set('content-type', 'application/x-www-form-urlencoded')
                    .send(bdy)
                    .end((err, res) => {
                      console.log(res.body);
                        res.should.have.status(422);
                        res.body.should.have.property('success').eql(false);
                      done();
                    });
                });
              })

              /**
               * Test /patch with invalid patch object
               */
               describe('/PATCH patch',()=>{
                 it('it should return false success', (done) => {
                   const dataString=JSON.stringify({
                           name: "dante",
                           age: "22"
                   });
                   const patchString=JSON.stringify([
                     { "op": "INVALID", "path": "/name", "value": "anuran" },
                     { "op": "add", "path": "/position", "value": "NodeJS Developer" }
                   ])
                   let bdy={
                     data:dataString,
                     patch:patchString
                   }

                 chai.request(app)
                     .patch('/api/patch')
                     .set('token',tokenForToday)
                     .set('content-type', 'application/x-www-form-urlencoded')
                     .send(bdy)
                     .end((err, res) => {
                       console.log(res.body);
                         res.should.have.status(200);
                         res.body.should.have.property('success').eql(false);
                       done();
                     });
                 });
               })
})

package.json

{
  "name": "cb-assignment",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node app.js",
    "test": "mocha --timeout 10000 --exit"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.18.2",
    "chai": "^4.1.2",
    "chai-http": "^3.0.0",
    "easyimage": "^3.0.0",
    "express": "^4.16.2",
    "express-session": "^1.15.6",
    "imagemagick": "^0.1.3",
    "jsonpatch": "^3.0.1",
    "jsonwebtoken": "^8.1.1",
    "mocha": "^5.0.0",
    "node-image-resize": "0.0.2",
    "request": "^2.83.0"
  },
  "devDependencies": {
    "istanbul": "^0.4.5"
  }
}

i am running it from command line with this command:

sudo ./node_modules/istanbul cover ./node_modules/.bin/_mocha

2
In your test script I only see mocha and not istanbul/coverage ?An-droid
I am running istanbul from terminal like istanbul cover ./node_modules/.bin/_mochaAnuran Barman
Note that with my first answer it should generate the full repportAn-droid

2 Answers

3
votes

For my node.js (typescript) project I use this kind of script for tests + coverage :

"test": npm-run-all --parallel build:watch cross-env DOTENV_FILE=.env.test nodemon -e ts --exec mocha build/**/unit/**/*.spec.js --recursive --inspect --watch --reporter spec --bail

Start it simply with npm run test

EDIT :

For istanbul :

Step 1 - Run your server under istanbul

$ ./node_modules/.bin/istanbul cover --handle-sigint  server.js

Step 2 - Run your tests, no need to run under istanbul

$ ./node_modules/.bin/_mocha  -R spec ./.instrument/test/** --recursive

The full report is under coverage/lcov-report/index.html

1
votes

You can add the --exit flag after your coverage script