How to test image loading (stream) using supertest and jest?

I have an image upload endpoint in my API that accepts application/octet-stream requests and processes these streams. I would like to write test coverage for this endpoint, but I canโ€™t figure out how to use supertest to stream images.

Here is my code:

 import request from 'supertest' const testImage = `${__dirname}/../../../assets/test_image.jpg` describe('Upload endpoint', () => { test('Successfully uploads jpg image', async () => request(app) .post(`${ROOT_URL}${endpoints.add_image.route}`) .set('Authorization', `Bearer ${process.env.testUserJWT}`) .set('content-type', 'application/octet-stream') .pipe(fs.createReadStream(testImage)) .on('finish', (something) => { console.log(something) })) }) 

This code does not produce anything, the finish event is never raised, nothing is written to the console, and this test suite actually passes because nothing is expected. I cannot bind .expect to this request, otherwise I get this runtime error:

TypeError: (0, _supertest2.default) (...). post (...). set (...). set (...). pipe (...). expect is not a function

How is this achieved?

+5
source share
4 answers

I think you really want to use fs.createReadStream(testImage) to read this image into your request, since fs.createWriteStream(testImage) will write data to the provided file descriptor (in this case testImage ). Be sure to check out Node Streams to see how they work in more detail.

I'm not quite sure where you get the finish event from supertest from, but you can see how to use the .pipe() method.

You may also consider using supertest multipart attachments if this is better suited to your test.

0
source
 const testImage = `${__dirname}/../../../assets/test_image.jpg` describe('Upload endpoint', () => { test('Successfully uploads jpg image', async () => request(app) .post(`${ROOT_URL}${endpoints.add_image.route}`) .set('Authorization', `Bearer ${process.env.testUserJWT}`) .attach("name",testImage,{ contentType: 'application/octet-stream' }) .expect(200) .then(response => { console.log("response",response); }) ); }); 
0
source

That should work. To pass data to a request, you must tell the readable stream in the request to request. Another way is to get data from the server. It also uses done instead of async , since pipes do not work with async / await.

It also costs nothing that by default the pipe will call end , and then the superspy will call end , resulting in an error about end being end . To solve this problem, you must tell the pipe call not to do this, and then end the call at the end of the stream event.

 import request from 'supertest' const testImage = `${__dirname}/../../../assets/test_image.jpg` describe('Upload endpoint', () => { test('Successfully uploads jpg image', (done) => { const req = request(app) .post(`${ROOT_URL}${endpoints.add_image.route}`) .set('Authorization', `Bearer ${process.env.testUserJWT}`) .set('content-type', 'application/octet-stream') const imgStream = fs.createReadStream(testImage); imgStream.on('end', () => req.end(done)); imgStream.pipe(req, {end: false}) }) }) 

Edited to add: this worked for me with small files. If I try to test it with a large test_image.jpg, the request will expire.

0
source

I had to make assumptions about the loading method, taking the body as input instead of multi-part form data. So below is an example where the original body is passed in for download

 const request = require('supertest'); const express = require('express'); const fs = require('fs') const app = express(); var bodyParser = require('body-parser') app.use(bodyParser.raw({type: 'application/octet-stream'})) app.post('/user', function(req, res) { res.status(200).json({ name: 'tobi' }); }); testImage = './package.json' resp = request(app) .post('/user') resp.set('Authorization', `Bearer Test`).set('Content-Type', 'application/octet-stream') resp.send(fs.readFileSync(testImage, 'utf-8')) resp.expect(200) .then(response => { console.log("response",response); }).catch((err) => { console.log(err) }) 

If you use multipart/form-data , then the code below shows an example

 const request = require('supertest'); const express = require('express'); const fs = require('fs') const app = express(); app.post('/user', function(req, res) { // capture the encoded form data req.on('data', (data) => { console.log(data.toString()); }); // send a response when finished reading // the encoded form data req.on('end', () => { res.status(200).json({ name: 'tobi' }); }); }); testImage = './package.json' resp = request(app) .post('/user') resp.set('Authorization', `Bearer Test`) resp.attach("file", testImage) resp.expect(200) .then(response => { console.log("response",response); }).catch((err) => { console.log(err) }) 
0
source

Source: https://habr.com/ru/post/1276106/


All Articles