I’m trying to test my update action method in a controller where a fake image needs to be created and uploaded to test if the update action method is working. So, I create fake image using UploadedFile::make()->image(‘imageName.jpeg’) and it is validated before being saved as usual. But my test is failing throwing the validation errors for the image saying the "imageName.jpeg" must be an image and of the specific mime type as set in the rules for validation. I’m new to testing so, can anyone please tell me what I’m doing wrong. Any help much appreciated Below is the code:
The route:
Route::patch('/update/{icon}', [ProductIconController::class,'update'])->name('updateIcon')
->missing(function (Request $request){
return Redirect::back()->with('failed', 'Icon not found!');
});
The controller :
public function update(UpdateIconRequest $request, ProductIcon $icon)
{
$attributes = $request->validated();
if($request->hasFile('iconImage') || $request->hasFile('iconHoverImage')){
if($request->hasFile('iconImage')){
$inputType = 'iconImage';
$file = $request->file('iconImage');
if(Storage::exists('images/product_icons/'.$icon->image)){
$deleted = Storage::delete('images/product_icons/'.$icon->image);
}
$icon->image = $this->saveImage($file, $attributes, $inputType);
}
if($request->hasFile('iconHoverImage')){
$inputType = 'iconHoverImage';
$file = $request->file('iconHoverImage');
if(Storage::exists('images/product_icons/'.$icon->image_hover)){
$deleted = Storage::delete('images/product_icons/'.$icon->image_hover);
}
$icon->image_hover = $this->saveImage($file, $attributes, $inputType);
}
}
$icon->name = $attributes['name']; //make it unique
$icon->ordering = $attributes['order'];
$icon->status = $attributes['status'];
$icon->modified = now();
$icon->trash = null;
$saveSuccess = $icon->save();
if($saveSuccess){
return redirect()->route('icons')->with('success', 'Icon has been Updated');
}
else{
return redirect()->route('icons')->with('failed', 'Some error occured ! </br>Icon was not updated.');
}
}
Inside the UpdateIconRequest class:
public function rules()
{
return [
'name' =>['required', 'string', 'min:3', 'max:80',
Rule::unique('product_icons','name')->ignore($this->route('icon')->id)],
'order' => ['required','numeric','min:1','max:120'],
'status' => ['required', 'numeric'],
'iconImage' => ['image','mimes:png,jpeg,svg','max:2048'],
'iconHoverImage' => ['image','mimes:png,jpeg,svg','max:2048'],
];
}
Inside the update.blade.php file :
<form action="{{route('updateIcon', ['icon'=> $icon->id])}}" method="post" enctype="multipart/form-data" id="iconUpdateForm">
@csrf
@method('PATCH')
---other input fields --
<div class="grid grid-cols-12 px-4 py-6 border-b text-xs">
<div class="col-span-2 font-semibold leading-4 text-gray-700/90">
<div>Image</div>
</div>
<div class="col-span-6 space-x-4 border-2 border-gray-700 p-4">
<label for="thumbImg" class="button-15" role="button">Update Icon Image +</label>
@if (empty($icon->image))
<p class="text-xs inline-block text-red-500">Please select Icon Image (Required)<span class="text-red-500"> *</span></p>
@endif
<input type="file" id="thumbImg" name="iconImage" class="px-2 py-1 text-lg bg-blue-100 text-gray-500 hidden" accept=".jpg, .jpeg, .png .svg" required value="{{ old('iconImage') }}"/>
<div class="fileImgContainer p-2 mt-2 border-2 border-gray-300 bg-gray-200 space-y-2 mb-3">
<p class="head1 text-xs text-red-400">Please select images for Icon</p>
<div class="preview flex flex-wrap gap-3">
@if (!empty($icon->image))
<div class="flex flex-col w-[200px] relative p-2 rounded-xl bg-gray-300">
<div class="h-8 w-8 bg-gray-100/70 text-xl text-gray-600 rounded-full flex justify-center items-center align-middle hover:cursor-pointer"><i class="fa-solid fa-check"></i></div>
<img src="{{asset('storage/images/product_icons/'.$icon->image)}}" alt="" class="object-contain h-[160px] w-[180px] mt-1">
</div>
@endif
</div>
</div>
@foreach ($errors->get('iconImage') as $message)
<p class="text-red-600">{{$message}}</p>
@endforeach
</div>
</div>
<div class="grid grid-cols-12 px-4 py-6 border-b text-xs">
<div class="col-span-2 font-semibold leading-4 text-gray-700/90">
<div>Hover Image</div>
</div>
<div class="col-span-6 space-x-4 border-2 border-gray-700 p-4">
<label for="thumbHoverImg" class="button-15" role="button">Update Icon Image +</label>
@if (empty($icon->image_hover))
<p class="text-xs inline-block text-red-500">Please select Icon Image (Required)<span class="text-red-500"> *</span></p>
@endif
<input type="file" id="thumbHoverImg" name="iconHoverImage" class="px-2 py-1 text-lg bg-blue-100 text-gray-500 hidden" accept=".jpg, .jpeg, .png .svg" required value="{{ old('iconHoverImage')}}"/>
<div class="fileImgContainer p-2 mt-2 border-2 border-gray-300 bg-gray-200 space-y-2 mb-3">
<p class="head1 text-xs text-red-400">Please select hover images for Icon</p>
<div class="preview flex flex-wrap gap-3">
@if (!empty($icon->image_hover))
<div class="flex flex-col w-[200px] relative p-2 rounded-xl bg-gray-300">
<div class="h-8 w-8 bg-gray-100/70 text-xl text-gray-600 rounded-full flex justify-center items-center align-middle hover:cursor-pointer"><i class="fa-solid fa-check"></i></div>
<img src="{{asset('storage/images/product_icons/'.$icon->image_hover)}}" alt="" class="object-contain h-[160px] w-[180px] mt-1">
</div>
@endif
</div>
</div>
</div>
@foreach ($errors->get('iconHoverImage') as $message)
<p class="text-red-600">{{$message}}</p>
@endforeach
</div>
</form>
And finally the test class code:
public function test_user_can_update_ProductIcon(){
$updatedImage1 = UploadedFile::fake()->image('abcde.jpeg');
$updatedHoverImage1 = UploadedFile::fake()->image('abcde1.jpeg');
//test the route with the productIcon id
$response = $this->patch(route('updateIcon', [
'icon'=>2,
'name' =>'Updated Test Name',
'status' => 'yes',
'order' => 112,
'iconImage' => $updatedImage1,
'iconHoverImage' => $updatedHoverImage1
]));
$response->assertStatus(302);
$response->assertRedirectToRoute('icons');
$response->assertSessionHas('success');
}
The errors that is being thrown when the above test fails:
FAIL TestsFeatureProductIconTest
✓ user can access crud pages for product icon
✓ user can create product icon
⨯ user can update product icon
! user can update product icon image → This test did not perform any assertions D:Web DesignWebsitewatergaterestauranttestsFeatureProductIconTest.php:101
---
• TestsFeatureProductIconTest > user can update product icon
Failed asserting that two strings are equal.
The following errors occurred during the last request:
The icon image must be an image.
The icon image must be a file of type: png, jpeg, svg.
The icon hover image must be an image.
The icon hover image must be a file of type: png, jpeg, svg.
at D:Web DesignWebsitewatergaterestauranttestsFeatureProductIconTest.php:97
93▕ 'iconImage' => $updatedImage1,
94▕ 'iconHoverImage' => $updatedHoverImage1
95▕ ]));
96▕ $response->assertStatus(302);
➜ 97▕ $response->assertRedirectToRoute('icons');
So, I tried to test my productIcon update action method but the test fails with errors saying the image fields basically doesn’t have an image.
2
Answers
Well the issue was I was sending the all request parameter of my test in the route method which was only supposed to accept the route parameter ie. the icon Id in this case and all the other request parameter values as the second argument to the path method. Here is the corrected test function:
Hope this helps someone.
In Laravel, when testing file uploads, you need to use the UploadedFile::fake() method to create fake uploaded files. However, it seems like you’re using the UploadedFile::fake()->image() method incorrectly. The image() method is used to generate images with a specific size, while you need to create fake uploaded files.