I'm writing a feature test for a simple photo upload to S3 using Laravel Medialibrary.
This is the test:
/** @test */
public function a_user_can_upload_a_photo()
{
$this->withoutExceptionHandling();
Storage::fake('s3');
$user = factory(User::class)->create();
$this->signIn($user);
$this->post( route('users.update.photo', [
$user,
'photo' => UploadedFile::fake()->image('photo.jpeg', 500, 500)->size(1000),
]));
$this->assertEquals(1, Media::all()->count());
Storage::disk('s3')->assertExists('photo.jpeg');
}
and this is the relevant part of the controller method handling the upload:
public function uploadPhoto(User $user, Request $request)
{
// ...
try {
$user->addMediaFromRequest('photo')
->preservingOriginal()
->toMediaCollection('user-photo');
} catch (\Exception $e) {
dd($e);
Log::debug('User photo upload: ' . $e);
}
return redirect(route('users.edit.profile', $user));
}
The error catched there with dd($e)
is
The current request does not have a file in a key named photo
I actually can test out that the error message is true with putting right in front of the try-catch:
dd($request->has('photo'));
=== true
but
dd($request->hasFile('photo'));
=== false
So I do not attach my mock file properly as a file to the request obviously, but I can't figure out how to do that and every example around my online searches suggest doing the test the way I already do.
Any help much appreciated.
The post()
method expects the url as the first argument, and the data as the second argument.
You are using the helper route()
to generate the url, which expects the user you want to edit as a parameter, but you are also passing the file data as a parameter to the helper route()
, instead of passing it as an argument to the post()
method:
$this->post( // just one argument for the post method
route('users.update.photo', [ // and two parameters for the route helper
$user,
'photo' => UploadedFile::fake()->image('photo.jpeg', 500, 500)->size(1000),
])
);
So use this syntax to pass the file as second argument for the post()
method:
$this->post(
route('users.update.photo', ['user' => $user]), // first argument
[ 'photo' => UploadedFile::fake()->image('photo.jpeg', 500, 500)->size(1000) ] // second argument
);