I've taken the example from the Lighthouse(v6) documentation for uploading a file.
- Added the mutation
type Mutation { upload(file: Upload!): String }
- Then create a custom
Upload
mutation class
final readonly class Upload
{
/** @param array{} $args */
public function __invoke(null $_, array $args)
{
dd($args);
}
}
Went on to write the first test
public function upload_profile_photo_successfully(): void
{
$operations = [
'query' => /** @lang GraphQL */ '
mutation ($file: Upload!) {
upload(file: $file)
}
',
'variables' => [
'file' => null,
],
];
$map = [
'0' => ['variables.file'],
];
$file = [
'0' => UploadedFile::fake()->create('test.pdf', 500),
];
$user = $this->createRandomUser()->getUser();
$this->actingAs($user);
$this->multipartGraphQL($operations, $map, $file)->dd();
}
When I run the test the EnsureXHR
middleware throws the exception
Content-Type multipart/form-data; is forbidden
which is expected from the middleware code
public const FORM_CONTENT_TYPES = [
'application/x-www-form-urlencoded',
'multipart/form-data',
'text/plain',
];
...
if (Str::startsWith($contentType, static::FORM_CONTENT_TYPES)) {
throw new BadRequestHttpException("Content-Type {$contentType} is forbidden");
}
How can I do the file upload with the XHR in place?
I tried deactivating the XHR middleware and it works fine, but that's not what I want to accomplish.
When reading the middleware code I can see the following:
So the solution is to add the
X-Requested-With: XMLHttpRequest
header to your request to allow your request to pass theEnsureXHR
middleware.Alternatively, remove the
EnsureXHR
middleware when running your test suite since it makes no sense to force only XHR requests when testing unless you are doing browser testing.