reakky's avatar

Cannot test livewire file upload

Hey,

I am trying to test a livewire file upload.

This is my test case:


public function test_task_document_can_be_uploaded()
    {
        $this->withExceptionHandling();
        Storage::fake('local');

        $file = UploadedFile::fake()->create('document.pdf', 256);
        
        $category = DocumentCategory::factory()->create();

        #dump('In Test: ' . $file->hashName());

        Livewire::test(DocumentsComponent::class, ['model' => $this->task])
            ->set('file', $file)
            ->set('category', $category->id)
            ->call('store');

        $this->assertDatabaseHas('documents', [
            'tenant_id' => $this->tenant->id,
            'name'      => $file->getClientOriginalName(),
            'path'      => 'files/' . $file->hashName()
        ]);
        Storage::disk('local')->assertExists('files/' . $file->hashname());
    }

The assertExists fails, because the hash name of the file that is created in the component is different from that one in my test case. But how can I get the right name?

Here is my component code:


public function store()
    {
        $this->validate([
            'file'      => 'mimes:pdf|max:1024',
            'category'  => 'required'
        ]);

        $path = $this->file->store('files');

        #dd($this->file->hashName(), $this->file->path(), $path);

        $this->model->documents()->create([
            'name'                  => $this->file->getClientOriginalName(),
            'path'                  => $this->file->path(),
            'document_category_id'  => $this->category
        ]);

        $this->refresh();
    }

0 likes
9 replies
bobbybouwmann's avatar

Mmh, I don't think you should be referencing $this-file->path() in your store method. Instead, you need to store $path in there

reakky's avatar

Yes, you are right. But I also tried this before and it did not work either.

The general problem is, that the generated file path in my component is different from the file path in my test case.

For example: store() generates something like: "files/asd3123sdsad.pdf"

But in my test case it is something different (e.g. "files/ujiojo1221.pdf")

Hope it is clear what I mean :-)

CorvS's avatar

@reakky Since the file name (and path) is created randomly you have to get your document from the database and use assertExists($path) with its path.

1 like
bobbybouwmann's avatar

So you say the $path variables returns a random string? It should actually return the path where the file is stored.

The file path is random because the file is first stored in /tmp, however, the actual filename should still be correct.

1 like
reakky's avatar

@corvs Yes, maybe this is the way I will solve it. I was wondering why I can not get the right path straight from the faked File, especially because it worked before when I had a normal controller function for that.

@bobbybouwmann I was not clear enough. Yes, the path returns the path where the file is stored. What I meant was, that the filename is created randomly. But I still can not get the actual path (including the actual filename) in my test case. So when I dump both path (from the test case and from the component) I get something like files/abc.pdf (in the component) and files/def.pdf (in my test case)

CorvS's avatar

@reakky

I was wondering why I can not get the right path straight from the faked File, especially because it worked before when I had a normal controller function for that.

It wouldn't make sense to get the path from the file on "client side". What do you mean it worked before?

reakky's avatar

Before I had a livewire component, which handles the file upload I have had a controller that did the job. And it worked without any problems.

But as you mentioned, in my component it does not make sense to get the path on client side and I think that is why my test fails.

reakky's avatar

Okay, now things getting really annoying.

As @corvs mentioned, I pull the correct path from the database. But now, when I assertExists with the path, it fails with the message Unable to find a file at path ...

Here is the updated code

public function test_task_document_can_be_uploaded()
    {
        Storage::fake('local');
        $file = UploadedFile::fake()->create('document.pdf', 256);
        $category = DocumentCategory::factory()->create();

        Livewire::test(DocumentsComponent::class, ['model' => $this->task])
            ->set('file', $file)
            ->set('category', $category->id)
            ->call('store');

        $this->assertDatabaseHas('documents', [
            'tenant_id' => $this->tenant->id,
            'name'      => $file->getClientOriginalName()
        ]);

        $document = Document::where('name', $file->getClientOriginalName())->get()->first();

        dump($document->path);

        Storage::disk('local')->assertExists($document->path);
    }

And my store method

    public function store()
    {
        $this->validate([
            'file'      => 'mimes:pdf|max:1024',
            'category'  => 'required'
        ]);

        $path = $this->file->store('files');

        dump($path);

        $this->model->documents()->create([
            'name'                  => $this->file->getClientOriginalName(),
            'path'                  => $path,
            'document_category_id'  => $this->category
        ]);

        $this->refresh();
    }

I also compared both paths, from the test case and from the component. They are both the same. So how can it be, that assertExists fails?

By the way: it works in the browser, so the file really get stored.

reakky's avatar

Okay, got it. Forgot to specify the driver in my component. So:

$path = $this->file->store('files', 'local');

did the trick.

Please or to participate in this conversation.