skeith22's avatar

skeith22 wrote a comment+100 XP

1w ago

@SarwarAhmed i follow the whole series hands on, my repo for this series is available if you need it

skeith22's avatar

skeith22 wrote a comment+100 XP

2w ago

what you can recommend other services that offer free deployment?

skeith22's avatar

skeith22 liked a comment+100 XP

3w ago

@radmax @andrewdv8 @halvarado77

Solution for Browser Test Issues with File Upload Forms

I experienced the same issue and found a solution based on a comment from the next video. The problem occurs when using enctype="multipart/form-data" on forms with Playwright browser tests.

The Fix

The solution is to dynamically set the enctype attribute using Alpine.js, only when a file is actually selected.

Step 1: Update the form's x-data

In resources/views/idea/index.blade.php, add a new hasImage property to track when a file is selected:

<form
    x-data="{
        status : 'pending',
        newLink: '',
        links: [],
        newStep: '',
        steps: [],
        hasImage: false
    }"
    action="{{ route('idea.store') }}"
    method="POST"
    class="space-y-4"
    x-bind:enctype="hasImage ? 'multipart/form-data' : false"
>

Step 2: Replace static enctype with dynamic binding

Replace the static enctype="multipart/form-data" attribute with:

x-bind:enctype="hasImage ? 'multipart/form-data' : false"

Step 3: Update the file input

Add an @change event to the file input to toggle hasImage when a file is selected:

<input 
    type="file" 
    name="image" 
    accept="image/*" 
    @change="hasImage = $event.target.files.length > 0" 
/>

Why This Works

This approach prevents the form from using multipart/form-data encoding when no image is uploaded, which resolves conflicts with Playwright browser tests. The enctype is only set when an actual file is selected by the user.

Benefits

  • ✅ Browser tests pass successfully without modifications to Composer packages
  • ✅ File uploads still work correctly for end users
  • ✅ No impact on form functionality
  • ✅ Clean, maintainable solution using Alpine.js

Test Results

After implementing these changes:

PASS  Tests\Browser\CreateIdeaTest
✓ it creates a new idea (1.95s)

Tests:    1 passed (9 assertions)
Duration: 2.42s

Hope this helps!

skeith22's avatar

skeith22 liked a comment+100 XP

3w ago

the CreateIdea constructor must be like this

public function __construct(#[CurrentUser()] protected User $user)
{
}

with parentheses after the attribute, without it wont work ( at least in my case)

skeith22's avatar

skeith22 wrote a comment+100 XP

4w ago

@Go3shom we are facing the same issue : FAILED Tests\Browser\CreateIdeaTest > it creates a new idea Failed asserting that an array has the key 'title'.

at tests\Browser\CreateIdeaTest.php:21 17▕ ->press('Create') 18▕ ->assertPathIs('/ideas'); 19▕ 20▕ ➜ 21▕ expect($user->ideas()->first())->toMatchArray([ 22▕ 'title' => 'Idea Title Test', 23▕ 'status' => 'completed', 24▕ 'desription' => 'I want to test my modal if can create a new idea.', 25▕ 'links' => ['https://google.com', 'https://laracasts.com'],

skeith22's avatar

skeith22 liked a comment+100 XP

1mo ago

arrow-back.blade.php

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
    stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
    class="lucide lucide-arrow-left-icon lucide-arrow-left">
    <path d="m12 19-7-7 7-7" />
    <path d="M19 12H5" />
</svg>

skeith22's avatar

skeith22 liked a comment+100 XP

1mo ago

external.blade.php

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
    stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
    class="lucide lucide-external-link-icon lucide-external-link">
    <path d="M15 3h6v6" />
    <path d="M10 14 21 3" />
    <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
</svg>

skeith22's avatar

skeith22 wrote a comment+100 XP

1mo ago

@Go3shom when fetching ideas in when() condition make sure the first argument point on the $status var, instead of $request->status:

$ideas = $user ->ideas() ->when($status, fn($query, $status) => $query->where('status', $status)) ->get();

skeith22's avatar

skeith22 wrote a comment+100 XP

1mo ago

@Go3shom i think you should meant directly like this when rendering: {{ $statusCount['all'] }}, because if you do : {{ $statusCounts->count()}} it count all the rows status in your db which means count all the rows in db even the current user is not owned that idea or not the current auth.

skeith22's avatar

skeith22 wrote a comment+100 XP

2mos ago

@jeffey - i think you can also use the Request object to extract authenticated user instance there like this one: public function store(IdeaRequest $request) {

    $request->user()->ideas()->create([
        'description' => $request->description,
    ]);

    return redirect('/ideas');
} 

this would be cleaner and clearer

skeith22's avatar

skeith22 liked a comment+100 XP

2mos ago

And in the controller if we are using authorize method with one parameter, we are using gate:

Gate::authorize(parameter1);

// ex.
Gate::authorize(gateName);

If we are using authorize method with 2 parameters, we are using policies:

Gate::authorize(parameter1, parameter2);

// ex.
Gate::authorize(methodName, modelOrClassInstance);