node.jsexpresschaichai-http

How to download a file with chai-http?


Here is my problem : I have to test a route which enriches files and makes them downloadable. The problem I have is that I cannot get the enriched file during my test.

I manage to recover this file with Axios (for a terminal command) but I have to use chai-http for the tests.

router.js

const router = require('express').Router();
const path = require('path');

const { enrichmentFileJSON } = require('../services/enrich/json');

router.post('/enrich/json', async (req, res) => {
  let { args } = req.query;
  await enrichmentFileJSON(req, args);
  return res.status(200).download(path.resolve(tmpDir, 'enriched.jsonl'));
});

testEnrichment.js

const chai = require('chai');
const chaiHttp = require('chai-http');
const fs = require('fs-extra');
const path = require('path');

chai.should();
chai.use(chaiHttp);

const url = 'http://localhost:8080';

describe('/enrich/json enrich a jsonl file', () => {
    it('should return the enriched file', async () => {
      const response = await chai.request(url)
        .post('/enrich/json')
        .attach('fileField', path.resolve(__dirname, 'enrichment', 'file.jsonl'), 'file.jsonl')
        .set('Access-Control-Allow-Origin', '*')
        .set('Content-Type', 'multipart/form-data')

      // i want to use something like this
      const writer = fs.createWriteStream(path.resolve(__dirname, 'tmp', 'enriched.jsonl'));
      response.data.pipe(writer);
    });
  });

Thank you in advance !


Solution

  • For "chai-http": "^4.3.0", Call .buffer() and .parse() methods on response object to get the buffer of the downloaded file.

    Then, use Readable.from(buffer) of stream module to convert the buffer to a readable stream.

    E.g.

    index.js:

    const express = require('express');
    const multer = require('multer');
    const path = require('path');
    const app = express();
    
    var upload = multer({ dest: path.resolve(__dirname, 'uploads/') });
    
    app.post('/enrich/json', upload.single('fileField'), async (req, res) => {
      return res.status(200).download(path.resolve(__dirname, 'file.jsonl'));
    });
    
    module.exports = app;
    

    index.test.js:

    const chai = require('chai');
    const chaiHttp = require('chai-http');
    const fs = require('fs');
    const path = require('path');
    const { Readable } = require('stream');
    const app = require('./');
    chai.use(chaiHttp);
    
    const binaryParser = function (res, cb) {
      res.setEncoding('binary');
      res.data = '';
      res.on('data', function (chunk) {
        res.data += chunk;
      });
      res.on('end', function () {
        cb(null, Buffer.from(res.data, 'binary'));
      });
    };
    
    describe('66245355', () => {
      it('should pass', async () => {
        const response = await chai
          .request(app)
          .post('/enrich/json')
          .attach('fileField', path.resolve(__dirname, 'file.jsonl'), 'file.jsonl')
          .set('Content-Type', 'multipart/form-data')
          .buffer()
          .parse(binaryParser);
    
        const writer = fs.createWriteStream(path.resolve(__dirname, 'enriched.jsonl'));
        Readable.from(response.body.toString()).pipe(writer);
      });
    });
    

    file.jsonl, the file you try to upload:

    {
      'ok': true
    }
    

    enriched.jsonl, the file you enriched and downloaded:

    {
      'ok': true
    }