Reputation: 101
I just started to learn do test with supertest and mocha. I've read the api document of supertest and it said that supertest support all lower-level API provided by superagent. SuperAgent said we can send a formData object by:
request.post('/user')
.send(new FormData(document.getElementById('myForm')))
.then(callback)
But when I try to send a formData object with supertest like this:
server
.post('/goal_model/images/' + userId + '/' + tmid)
.set('Authorization',`Bearer ${token}`)
.send(formData)
.expect("Content-type",/json/)
.expect(201)
.end(function(err,res){
should(res.status).equal(201);
console.log(res.message);
done();
});
Where the formData is like:
let file;
let formData = new FormData();
let fn = "../../../Downloads/Images/5k.jpg";
formData.append("image", file);
Then when I try to send this object it just said:
TypeError: "string" must be a string, Buffer, or ArrayBuffer
Does it possible to send a formData object in this way? What did I do wrong or how to do that? If not, why? I've searched many relative questions but none can solve my problem. I'm really in struglling now.
Upvotes: 10
Views: 10371
Reputation: 37
Recently went throught the same problem. Below is my working code . If you are sending both data and file to the api endpoint you should use .field()
to send values and .attach
to send files.
`
describe('Admin Routes', () => { let user, restaurant;
beforeAll(async () => {
user = await User.create({username: 'aman', password: 'password', email: '[email protected]', phone: 123, restaurantOwner: true});
restaurant = await Restaurant.create({name: 'taj', phone: 123, ownerId: user._id});
const mockPayload = { userId: user._id, restaurantOwner: true };
jest.spyOn(jwt, 'verify').mockReturnValue(mockPayload);
});
let dishId ;
it('should create dish with an image and form data', async () => {
// ... (rest of your test)
const res = await request(app)
.post('/admin/create')
.set({ Authorization: '123' })
.field('name', 'someName')
.field('restaurantId', restaurant._id.toString())
.field('price', String(10))
.field('description', 'Some Description')
.attach('image',path.resolve(__dirname, '../../images/dish.jpg'));
expect(res.status).toBe(201)
});`
If you get Error Like
Aborted
at Test.<anonymous> (node_modules/superagent/src/request-base.js:278:23)
at Test.abort (node_modules/superagent/src/request-base.js:510:8)
at FormData.<anonymous> (node_modules/superagent/src/node/index.js:288:12)
at FormData.Object.<anonymous>.CombinedStream._emitError (node_modules/combined-stream/lib/combined_stream.js:207:8)
at DelayedStream.<anonymous> (node_modules/combined-stream/lib/combined_stream.js:133:10)
at DelayedStream.Object.<anonymous>.DelayedStream._handleEmit (node_modules/delayed-stream/lib/delayed_stream.js:82:15)
at ReadStream.source.emit (node_modules/delayed-stream/lib/delayed_stream.js:29:19)
It is possibly due to the your image path being wrong. __dirname
is path of the folder where the test file is, so the next argument should be set accordingly.
Upvotes: 0
Reputation: 102597
You can use .attach()
method of supertest
to send your file to the server. Function signature of .attach
:
attach(field: string, file: MultipartValueSingle, options?: string | { filename?: string; contentType?: string }): this;
The data type of file
parameter can be:
type MultipartValueSingle = Blob | Buffer | fs.ReadStream | string | boolean | number;
Here I pass a file path to .attach
method.
E.g.
server.ts
:
import express from 'express';
import multer from 'multer';
import path from 'path';
const app = express();
const port = 3000;
const upload = multer({ dest: path.resolve(__dirname, 'uploads/') });
app.post('/upload', upload.single('avatar'), (req, res) => {
console.log('file:', req.file);
console.log('content-type:', req.get('Content-Type'));
res.sendStatus(200);
});
if (require.main === module) {
app.listen(port, () => {
console.log(`HTTP server is listening on http://localhost:${port}`);
});
}
export { app };
server.test.ts
:
import { app } from './server';
import request from 'supertest';
import path from 'path';
describe('52359964', () => {
it('should pass', () => {
return request(app)
.post('/upload')
.attach('avatar', path.resolve(__dirname, './downloads/5k.jpg'))
.expect(200);
});
});
integration test results:
52359964
file: { fieldname: 'avatar',
originalname: '5k.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination:
'/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/src/stackoverflow/52359964/uploads',
filename: '329756ab22bf7abe2d27866a322c2f30',
path:
'/Users/ldu020/workspace/github.com/mrdulin/expressjs-research/src/stackoverflow/52359964/uploads/329756ab22bf7abe2d27866a322c2f30',
size: 0 }
content-type: multipart/form-data; boundary=--------------------------777489367435889931561092
✓ should pass (42ms)
1 passing (48ms)
Upvotes: 5