Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

TimHaynes's avatar

PEST 4 File upload testing (Inertia)

Hi,

I'm using PEST 4 to test a form submission that includes an image upload as a required field.

$page->attach('input[data-testid="profile_image"]', base_path('tests/Browser/images/avatar.jpg'));

Looking at the produced screenshot ($page->debug()) and using some console logs it's attaching the file to the form as I would expected, but when I submit the form the payload is empty?

I have tested the form without the file (removed it as a required) and the form submitted as expected and the test passes.

I've searched for possible solutions but not found anything that points me in the right direction or seems to replicate what I am experiencing.

Any pointers or solutions would be very much appreciated.

Cheers!

0 likes
1 reply
LaryAI's avatar
Level 58

Certainly! When using PEST (especially with Laravel Dusk or Laravel's browser testing tools) to test file uploads with Inertia, there are a few common pitfalls that can result in the file field not being submitted properly:

  1. Correct Input Selector: Make sure your file input is not hidden or replaced by a custom component. If you're using a custom file input or a JavaScript-based file uploader (common in Inertia/Vue/React), the real <input type="file"> might be hidden or in a different location in the DOM. Ensure your selector targets the actual file input element.

  2. Input Name Attribute: Dusk and similar drivers often work best when you select the name attribute rather than data-testid. For example:

    $page->attach('input[name="profile_image"]', base_path('tests/Browser/images/avatar.jpg'));
    
  3. Form Submission Method: Make sure your form's enctype is set to "multipart/form-data" and that in your Inertia page, you’re handling file uploads correctly. For example, if you use a library like inertia-form, ensure you’re using FormData.

  4. Test File Existence: Double-check that the file exists at the given path:

    base_path('tests/Browser/images/avatar.jpg')
    
  5. Wait for the File to Attach: Sometimes, you need to wait until the file input is fully processed before submitting.

  6. Example: Full Code

    // Assuming $page is an Illuminate\Support\Testing\Browser instance
    
    // 1. Make sure file exists
    assert(file_exists(base_path('tests/Browser/images/avatar.jpg')));
    
    // 2. Attach the file by input name
    $page->attach('input[name="profile_image"]', base_path('tests/Browser/images/avatar.jpg'));
    
    // 3. Optionally wait for any JavaScript (Inertia) processing
    $page->pause(500);
    
    // 4. Submit the form (adjust button selector as per your markup)
    $page->press('@submit-button');
    
    // 5. Assert the upload worked
    $page->assertSee('Successfully uploaded');
    

Troubleshooting:

  • If Using Vue/React File Uploader: If your uploader is purely JavaScript-driven (e.g. with a ref or custom events), Dusk's attach may not trigger your upload code. In that case, you may need to trigger the change event manually after attaching:
    $page->attach('input[name="profile_image"]', base_path('tests/Browser/images/avatar.jpg'))
         ->script('document.querySelector("input[name=\"profile_image\"]").dispatchEvent(new Event("change"))');
    

Summary:

  • Use the actual <input type="file" name="profile_image"> for the selector.
  • Ensure the file exists.
  • Double-check that your Inertia logic transforms the form using FormData.
  • If using a custom uploader, make sure Dusk is operating on the real input.

If you can share your markup or the JS code handling the file, I can give even more direct advice!

Please or to participate in this conversation.