question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

GraphQL File Upload is not intercepted in NodeJS

See original GitHub issue

Environment

Name Version
msw 0.26.2
node 15.9.0
OS Ubuntu

Request handlers

/**
 * @jest-environment node
 */

import { createReadStream } from 'fs'

import FormData from 'form-data'
import { graphql } from 'msw'
import { setupServer } from 'msw/node'
import fetch from 'node-fetch'

const server = setupServer()

server.listen({ onUnhandledRequest: 'warn' })

it('file upload', async () => {
  const query = `
    mutation UploadFile($file: Upload!) {
      uploadFile(file: $file)
    }
  `

  server.use(
    graphql.mutation('UploadFile', (req, res, ctx) =>
      res(ctx.data({ uploadFile: true })),
    ),
  )

  const form = new FormData()

  form.append('operations', JSON.stringify({ query, variables: { file: null } }))
  form.append('map', JSON.stringify({ '0': ['variables.file'] }))
  form.append('0', createReadStream(__filename))

  const response = await fetch('http://localhost:1234/api/graphql', {
     method: 'POST',
     body: form,
  })
})

Current behavior

 [MSW] Warning: captured a request without a matching request handler:
    
      • POST http://localhost:1234/api/graphql

Expected behavior

Expected GraphQL File Upload request to be intercepted. What am I doing wrong?

P.S. Thanks for this awesome library!

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:1
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
lynxtaacommented, Feb 25, 2021

I’ve been experimenting with different FormData polyfills. Here are my observations:

@jest-environment node

import { readFileSync } from 'fs'

import FormData from 'form-data'
import { graphql, rest } from 'msw'
import { setupServer } from 'msw/node'
import fetch from 'node-fetch'

const server = setupServer()

beforeAll(() => {
	server.listen({ onUnhandledRequest: 'warn' })
})

beforeEach(() => {
	server.resetHandlers()
})

afterAll(() => {
	server.close()
})

const query = `
	mutation UploadFile($file: Upload!) {
		uploadFile(file: $file)
	}
`

// Doesn't work. Prints:
// [MSW] Warning: captured a request without a matching request handler:
// • POST http://localhost:1234/api/graphql
it('GRAPHQL file upload with node-fetch, form-data', async () => {
	server.use(
		graphql.mutation('UploadFile', (req, res, ctx) => {
			console.log(req.body)
			return res(ctx.data({ uploadFile: true }))
		}),
	)

	const form = new FormData()

	form.append('operations', JSON.stringify({ query, variables: { file: null } }))
	form.append('map', JSON.stringify({ '0': ['variables.file'] }))
	form.append('0', readFileSync(__filename))

	await fetch('http://localhost:1234/api/graphql', { method: 'POST', body: form })
})

// Works but req.body is a string
it('REST with node-fetch, form-data', async () => {
	server.use(
		rest.post('http://localhost:1234/api/graphql', (req, res, ctx) => {
			console.log(req.body) // ----------------------------638935769006777650385780  Content-Disposition: form-data; name="operations" ...
			return res(ctx.json({ data: { uploadFile: true } }))
		}),
	)

	const form = new FormData()

	form.append('operations', JSON.stringify({ query, variables: { file: null } }))
	form.append('map', JSON.stringify({ '0': ['variables.file'] }))
	form.append('0', readFileSync(__filename))

	const response = await fetch('http://localhost:1234/api/graphql', {
		method: 'POST',
		body: form,
	})
	expect(response.ok).toBe(true)
})

@jest-environment jsdom

import 'whatwg-fetch'
import { graphql, rest } from 'msw'
import { setupServer } from 'msw/node'

const server = setupServer()

beforeAll(() => {
	server.listen({ onUnhandledRequest: 'warn' })
})

beforeEach(() => {
	server.resetHandlers()
})

afterAll(() => {
	server.close()
})

const query = `
	mutation UploadFile($file: Upload!) {
		uploadFile(file: $file)
	}
`

// Works OK but prints:
// [MSW] Warning: captured a request without a matching request handler
// • POST http://localhost/api/graphql
it('GRAPHQL file upload with whatwg-fetch and JSDOM', async () => {
	server.use(
		graphql.mutation('UploadFile', (req, res, ctx) => {
			console.log(req.variables) //  { file: File {} }
			return res(ctx.data({ uploadFile: true }))
		}),
	)

	const form = new FormData()

	form.append('operations', JSON.stringify({ query, variables: { file: null } }))
	form.append('map', JSON.stringify({ '0': ['variables.file'] }))
	form.append('0', new File([''], 'image.png'))

	await fetch('/api/graphql', { method: 'POST', body: form })
})

// Works OK
it('REST file upload with whatwg-fetch and JSDOM', async () => {
	server.use(
		rest.post('/api/graphql', (req, res, ctx) => {
			console.log(req.body) // FormData {}
			return res(ctx.json({ data: { uploadFile: true } }))
		}),
	)

	const form = new FormData()

	form.append('operations', JSON.stringify({ query, variables: { file: null } }))
	form.append('map', JSON.stringify({ '0': ['variables.file'] }))
	form.append('0', new File([''], 'image.png'))

	await fetch('/api/graphql', { method: 'POST', body: form })
})
1reaction
lynxtaacommented, Feb 24, 2021

@kettanaito I’ve expected graphql upload to work since https://github.com/mswjs/msw/pull/543 is merged. In a real scenario I can’t send a JSON since I’m using external library for sending graphql requests which uses node-fetch and form-data.

Thanks for suggestions, I’ll try more digging and maybe send a PR

Read more comments on GitHub >

github_iconTop Results From Across the Web

Developers - GraphQL File Upload is not intercepted in NodeJS -
Environment. Name Version msw 0.26.2 node 15.9.0 OS Ubuntu. Request handlers. /** * @jest-environment node */ import { createReadStream } from 'fs' import...
Read more >
File uploads in Node.js < v8.5.0 - Apollo GraphQL Docs
File uploads are supported in Apollo Server 2.x through the third-party graphql-upload package. While Apollo Server 2.x aims to support Node.js LTS versions ......
Read more >
NestJS upload using GraphQL - node.js - Stack Overflow
Using Base64 to upload files is not scalable, if you have multiple files to upload or with huge file sizes. It's possible now...
Read more >
Upload File(s) to GraphQL Server using Postman, Axios and ...
In this video I've shown how to Upload Single/Multiple File to GraphQL Server using: -1. Postman2. Axios and3. Cypress (using XMLHttpRequest ...
Read more >
Handle file uploads using a GraphQL middleware - Medium
Add a new scalar type (to be called Upload) at the input of our mutation,; Develop middleware to intercept the HTTP POST multipart/form-data ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found