Summer Sale! All accounts are 50% off this week.

deshiloh's avatar

File asserting always false because hashName's file

Hi,

I would like to write a test of my upload method using Livewire :

public function saveImage()
    {
        $this->validate();

        try {
            Carousel::create([
                'file_name' => $this->photo->hashName(),
                'position' => $this->position
            ]);

            $this->photo->store('photos');
            $this->photo = null;
        } catch (\Exception $exception) {
            ray()->exception($exception);
        }
    }

here my test :

public function testAddCarouselSuccess()
    {
        \Storage::fake('local');

        $file = UploadedFile::fake()->image('test.png');
        $name = $file->hashName();

        Livewire::test(CarouselDataTable::class)
            ->set('photo', $file)
            ->set('position', 1)
            ->call('saveImage')
            ->assertHasNoErrors()
        ;

        \Storage::disk('local')->assertExists('photos/'.$file->hashName());

        $this->assertDatabaseHas('carousels', [
            'file_name' => $name
        ]);
    }

It gives me :

Unable to find a file or directory at path [photos/WLCFuzQe0IA5imQO2uSGNR5uU0mRGFiu5iVTbUM8.png].

I noticed that the assertDatabaseHas, gives me :

Failed asserting that a row in the table [carousels] matches the attributes {
    "file_name": "bPAAByU7Mm4qPxK6hlXPNfLNrRvLPZqmtlgnf1JN.png"
}.

Found: [
    {
        "file_name": "LXS5HQOTleyeoXI1MWJOoUaJvohRdoK6mlNzaO5R.png"
    }
].

How is it possible, that the name of $file and the name registered in the database are not the same ?

0 likes
3 replies
tisuchi's avatar

@deshiloh It looks like the issue is that the file name stored in the database and the file name that you are asserting against in your test are not the same. This is likely because the file name generated by the hashName() method is different each time the test is run.

One way to fix this issue is to store the file name generated by the hashName() method in a variable, and then use that variable in both the database assertion and the storage assertion.

Here's an example of how you could do that:

public function testAddCarouselSuccess()
{
    \Storage::fake('local');

    $file = UploadedFile::fake()->image('test.png');
    $name = $file->hashName();

    Livewire::test(CarouselDataTable::class)
        ->set('photo', $file)
        ->set('position', 1)
        ->call('saveImage')
        ->assertHasNoErrors()
    ;

    \Storage::disk('local')->assertExists('photos/'.$name);

    $this->assertDatabaseHas('carousels', [
        'file_name' => $name
    ]);
}

Another way is to use storeAs() instead of store(), this way you can specify the name of the file, it's helpful when you want to test certain file name and you want to assert if it's stored correctly or not.

$this->photo->storeAs('photos', $name);

You can also use Storage::assertExists('photos/'.$name) instead of \Storage::disk('local')->assertExists('photos/'.$name);

It should resolve your problem and the test should pass.

deshiloh's avatar
deshiloh
OP
Best Answer
Level 1

My actually solution has to deport the store work in the method.

public function upload(string $name)
    {
        $this->photo->storeAs('/', $name, $disk = 'photos');
    }

And the test :

public function testUploadFile()
    {
        \Storage::fake('photos');

        $file = UploadedFile::fake()->image('test.png');
        $name = $file->hashName();

        Livewire::test(CarouselDataTable::class)
            ->set('photo', $file)
            ->call('upload', $name)
        ;

        \Storage::disk('photos')->assertExists($name);
    }

Please or to participate in this conversation.