Calling a resolver using createTestClient and a file gives a buffer instead of a promise like you would normally receiving from a client.
// test.js
it('UPLOAD', async () => {
const file = fs.readFileSync(path.join(__dirname, './test.txt'))
const UPLOAD = gql`
mutation upload($files: [Upload!]!) {
upload(files: $files) {
location
}
}
`
const { mutate } = createTestClient(server)
const res = await mutate({ query: UPLOAD, variables: { files: [file] } })
})
// resolver.js
Mutation: {
async upload (root, { files }) {
console.log('Files', files)
const medias = await Promise.all(files.map(async file => {
const { stream, mimetype } = await file
console.log('Info', stream, mimetype)
// ...
})).catch(console.error)
return medias
}
}
console.log resolver.js
Files [ <Buffer 49 20 61 6d 20 61 20 74 65 73 74 20 66 69 6c 65> ]
Info undefined undefined
Is the Upload scalar supported by createTestClient?
I'm also receiving undefined in stream. Did you solve this?
No, I had to leave it out until this is fixed
It feels a little hacky, but I got this to work by doing the following:
import { createReadStream } from 'fs';
const fileName = `${__dirname}/...`;
const response = await mutate({
mutation: UPLOAD_PRODUCT_IMAGE,
variables: {
file: {
createReadStream: () => createReadStream(fileName),
filename: 'image.jpg',
mimetype: 'image/jpeg',
},
},
});
Instead of using readFileSync, pass your own createReadStream function that creates a stream with the path to the file you want.
@joemckie does this still works for you?
I am getting the following error:
Received: [[GraphQLError: Variable "$file" got invalid value { createReadStream: [function createReadStream], filename: "image.jpg", mimetype: "image/jpeg" }; Expected type Upload. Upload value invalid.]]
Any ideas?
@loremaps I think I removed this code in a refactor when I moved to NestJS unfortunately so I wouldn't be able to test it out any more 馃槥
FWIW, I remember this being an issue during the refactor, and I found it was easier to test it by using supertest and using a multipart request
@loremaps I am getting the same error as you, did you find a solution?
EDIT: Okay, so digging into it I found graphql-upload expects to receive an instance of the Upload class. I got around it with ...
const fs = require('fs');
const path = require('path');
const Upload = require('graphql-upload/public/Upload');
let test_client;
beforeEach(async () => {
// Setup test_client
...
});
test('upload file', async () => {
const filename = 'test.txt';
const file = new Upload();
file.promise = new Promise(resolve => resolve({
createReadStream: () => fs.createReadStream(path.join(__dirname, '__fixtures__', filename)),
filename,
mimetype: 'text/plain'
}));
const upload_file = await test_client.mutate({ query: QUERY, variables: { file } });
expect(upload_file.errors).toBeUndefined();
});
We are removing the built-in graphql-upload integration in Apollo Server 3 and are also considering removing apollo-server-testing as a standalone package so I am going to close this issue.
createTestClient is a very thin wrapper around server.executeOperation, a function that lets you hook directly in to the Apollo Server request pipeline bypassing all HTTP-based processing. This does make doing things like graphql-upload which involve a pre-processing step in the HTTP process challenging. I think we should keep executeOperation around as a simple hook for running operations when we don't care about HTTP stuff, but also make it easier (through better documentation or improvements) to test your full HTTP server.
Most helpful comment
It feels a little hacky, but I got this to work by doing the following:
Instead of using
readFileSync, pass your owncreateReadStreamfunction that creates a stream with the path to the file you want.