I am trying to add a profile image feature in my app. I am using the TDD approach to do this. The test for uploading profile picture shows green. But when I run the test to update the profile picture, it gives an error. Below is the code:
Controller:
public function store(StoreAvatarRequest $request)
{
$path = $request->file('avatar')->store('avatars');
BasicInformation::updateOrCreate([
'user_id' => auth()->id(),
], [
'user_id' => auth()->id(),
'avatar' => $path,
]);
$this->showAlerts('alert-success', 'Profile Image uploaded successfully');
return redirect()->route('avatar.index');
}
public function update(StoreAvatarRequest $request, $id)
{
$basicProfile = BasicInformation::find($id)->first();
$oldAvatarPath = $basicProfile->avatar;
if ($basicProfile->user_id == auth()->id()) {
$path = $request->file('avatar')->store('avatars');
$basicProfile->avatar = $path;
$basicProfile->update();
Storage::delete($oldAvatarPath);
$this->showAlerts('alert-success', 'Profile Image Updated Successfully');
return redirect()->route('avatar.index');
} else {
// TODO :: Need to add logic here
}
}
Test Case:
public function can_update_profile_picture()
{
$this->actingAs($this->lawyer)->post(route('avatar.store'), [
'avatar' => UploadedFile::fake()->image('avatar.jpg', 600, 600)
]);
$oldImagePath = $this->lawyer->information->avatar;
$this->actingAs($this->lawyer)->put(route('avatar.update', ['id' => $this->lawyer->information->id]), [
'avatar' => UploadedFile::fake()->image('avatar1.jpg', 600, 600)
])
->assertRedirect(route('avatar.index'))
->assertSessionHas('status', 'Profile Image Updated Successfully');
Storage::disk('local')->assertExists($this->lawyer->information->avatar);
Storage::disk('local')->assertMissing($oldImagePath);
}
I am getting the following error when I run the test:
PHPUnit 5.7.19 by Sebastian Bergmann and contributors.
F 1 /
1 (100%)
Time: 298 ms, Memory: 20.00MB
There was 1 failure:
1) Tests\Feature\Dashboard\Lawyer\Account\ProfileImageTest::can_update_profile_picture
Unable to find a file at path [local/c5tjUUQDzU4iKHauJK68Z801I5iaYJ7e3cVQ5iA1.jpeg].
Failed asserting that false is true.
This is a matter of configuration and then preference for using store() or storeAs() methods.
First off you have to configure filesystems.phpto recognize your tests Storage disk as the fake() disk:
'testing' => [
'driver' => 'local',
'root' => storage_path('framework/testing/disks/'),
'visibility' => 'public',
Using that setup allows you to use your APP_ENV value in phpunit.xmlfor defaulting this disk for your tests.
Also, I use the use the storeAs()in my controller so that I can test against the filename I stored in the assertExists() method in my test.
$request->file('avatar')->storeAs('avatar', $request->file('avatar')->getClientOriginalName())
Storage::disk('avatar')->assertExists('avatar.jpg');
This is what works for me and the files are deleted before running each test and clean up is not an issue. You can also do a test for the hashName and use the store() method by getting the responsed and using baseName() to get the name of the new file.
I have added to phpunit.xml next line:
<env name="FILESYSTEM_DRIVER" value="uploads"/>
and while checking
$image = $response->original['logo']; // as the image name get changed in Controller
Storage::disk('uploads')->assertExists("public/uploads/$image");
Others codes are similar as Laravel Doc. You may Like to check the discussion at Laracast.