Graphql: How to proper test E2E file upload using Graphql + supertest

Created on 24 Jul 2020  路  5Comments  路  Source: nestjs/graphql

Hello all!

First I would like to thanks you all for the awesome work, I really enjoy programming with NestJS. I'm building a SaaS application and has been a breeze. So congrats on all the good and hard work!

I'm writing a support question here because I've been trying to solve a problem by myself, asking on discord, posting on stackoverflow, and I don't seem to get anywhere so I really would like to ask you for some help.

I'm using NestJS + GraphQL for my project and I don't seem to be able to write a proper E2E test for file upload using supertest.

this is an example of a basic upload image test

it("should create a image", async () => {
  const fixturePath = path.join(__dirname, "./fixtures/image.png");

  const imageStream = fs.createReadStream(fixturePath);

    await request(app.getHttpServer())
      .post("/graphql")
      .set({ Authorization: `Bearer ${token}` })
      .send({
        operationName: null,
        query: /* GraphQL */ `
          mutation(
            $image: Upload
          ) {
            createMutation(
              image: $image
            ) {
              publicUuid
            }
          }
        `,
        variables: {
          image: imageStream,
        },
      })
      .expect(({ body }) => {
        console.log(body);
        expect(body.data.createMutation).toBeDefined();
      })
      .expect(200); 
})

On the resolver side I have this error:

{
  errors: [
    {
      message: 'image.createReadStream is not a function',
      locations: [Array],
      path: [Array],
      extensions: [Object]
    }
  ],
  data: null
}

I know that this might not be entirely from NestJS side, but I thought I might try and see if anyone already had a similar problem.

Thanks in advance 馃檹 and please do not send me to discord because the question just gets lost in the endless stream of messages, I did it once and that's what happened.

Most helpful comment

Hi @DiogoBatista you could try:

```request(app.getHttpServer())
.post('/graphql')
.field('operations', JSON.stringify({ query }))
.field('map', JSON.stringify({ '0': ['variables.file'] }))
.attach('0', fixturePath)

All 5 comments

Does anyone have an idea on this one??

Thanks in advance

Hi @DiogoBatista you could try:

```request(app.getHttpServer())
.post('/graphql')
.field('operations', JSON.stringify({ query }))
.field('map', JSON.stringify({ '0': ['variables.file'] }))
.attach('0', fixturePath)

@djaircarvalho Thank you very much 馃檹 this really helped me, I've seen this approach before but you really unblocked me, many many thanks!! Im posting the final version that worked for me below

it("should create a image", async () => {
  const fixturePath = path.join(__dirname, "./fixtures/image.png");

  const query = /* GraphQL */ ` mutation(
              $image: Upload
            ) {
              createMutation(
                image: $image
              ) {
                publicUuid
              }
            }`

    await request(app.getHttpServer())
      .post("/graphql")
      .set({ Authorization: `Bearer ${token}` })
      .set("Content-Type", "multipart/form-data")
      .field(
        "operations",
        JSON.stringify({
          query,
          variables: {
            image: null,
          },
        })
      )
      .field(
        "map",
        JSON.stringify({
          image: ["variables.image"],
        })
      )
      .attach("image", fixturePath)
      .expect(({ body }) => {
        expect(body.data.createMutation).toBeDefined();
      })
      .expect(200); 
})

@djaircarvalho I actually have a weird scenario that I wanted to ask you, I would like to send the files via an Input instead of the Upload directly in the mutation like the one I'm showing below. With your approach, I tried a couple oftimes to attach it to the correct field but I couldn't make it work. Do you by any chance know how could this work, I think it could be useful since sometimes you do want to send multiple files and have some identifier.

input FileInput {
file: Upload
type: String
}

## MUTATION
create(
  files: [FileInput]
)


.field(
        "operations",
        JSON.stringify({
          query,
          variables: {
            files: [
              { file: null, type: 'something'}
            ],
          },
        })
      )
      .field(
        "map",
        JSON.stringify({
          file: ["variables.files[0].file"], OR even ["variables.files[0][file]"]
        })
      )
      .attach("file", fixturePath) ---> this do not attach to the array 


@djaircarvalho like in this case -> https://github.com/jaydenseric/graphql-upload/issues/117 how could we test this via attaching the file?

Thanks for posting your solution @DiogoBatista. However, we are using GitHub to track bugs, feature requests, and potential improvements. Please, use StackOverflow for such questions in the future.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

galkin picture galkin  路  4Comments

liudonghua123 picture liudonghua123  路  3Comments

harm-less picture harm-less  路  4Comments

Warchant picture Warchant  路  4Comments

ghost picture ghost  路  5Comments