crscnc wrote a comment+100 XP
5d ago
@Alexandru019 We need a secret badge named 'something whisperer', when someone made a outstanding comment like you!
crscnc liked a comment+100 XP
5d 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!
crscnc liked a comment+100 XP
5d 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'],
crscnc liked a comment+100 XP
5d ago
@radmax I was facing an issue too but the error was
FAILED Tests\Browser\CreatIdeaTest > it creates a new idea
Failed asserting that an array has the key 'title'.
at tests\Browser\CreatIdeaTest.php:27
23▕ ->click('Create')
24▕ ->assertPathIs('/ideas')
25▕ ;
26▕
➜ 27▕ expect($user->ideas()->first())->toMatchArray([
28▕ 'title' => 'Idea Title',
29▕ ...
And I don't know why did the relation $user->ideas()->first() returns null!
But it works after trying what you've said, so, thanks a lot.
crscnc liked a comment+100 XP
2w ago
@kumarayush Did you use the PATCH method in the form? Remember, HTML forms only support GET and POST.
The solution is to use POST and add a hidden input called _method, like this:
<form method="POST" action="{{ route('step.update', $step) }}">
<input type="hidden" name="_method" value="PATCH">
</form>
But in Laravel, you can use the helper directive instead:
<form method="POST" action="{{ route('step.update', $step) }}">
@csrf
@method('PATCH')
<!-- your inputs here -->
<button type="submit">Update</button>
</form>
That way Laravel will correctly handle the PATCH request.
crscnc liked a comment+100 XP
2w ago
@crscnc if you plan increase complexity there are a few great course in here: Laravel API masterclass, Modular Laravel and others. My concern is about time to dedicate to a technology: Blade looks like great but when you plan to do things close to app maybe vue3 is better. But not entirely sure. Maybe you dedicate efforts to vue3 and an experienced developers tell you that now the trend is CanavisReact 4 (fake name) because it handle better some things that vue3 doesn't. As an example: I usually use MariaDB for all kind of projects. It is a bit work to configure MariaDB, maybe a Linux, Apache or nginx, etc. @jeffreyway suggest in a course that SQLite should be enough for most Laravel projects. I tried it and looks like a good advice. So, I expect the opinion who was there in the battle. You know. :-)
Thank you
crscnc liked a comment+100 XP
2w ago
crscnc wrote a comment+100 XP
2w ago
crscnc wrote a reply+100 XP
3w ago
crscnc wrote a comment+100 XP
4w ago
@joellutterodt Intersting point of view. Maybe if results are paginated, it can be a bit worst to do it in front end? Maybe its a trade off of resources. do it in db or frontend runtime... db probably is faster and results can lead to less client memory usage,
crscnc wrote a comment+100 XP
1mo ago
crscnc liked a comment+100 XP
1mo ago
Here are the full CSS component files for those looking to copy:
resources/css/components/btn.css
button {
cursor: pointer;
}
.btn {
background: var(--color-primary);
border-radius: var(--radius-xl);
color: var(--color-primary-foreground);
padding-inline: calc(var(--spacing) * 3);
font-size: var(--text-sm);
font-weight: var(--font-weight-medium);
cursor: pointer;
height: calc(var(--spacing) * 8);
line-height: calc(var(--spacing) * 8);
display: inline-block;
}
.btn.btn-outlined {
background: transparent;
border: 1px solid var(--color-border);
border-color: var(--color-border);
color: var(--color-foreground);
}
.btn.btn-outlined:hover {
background: color-mix(in srgb, black 25%, var(--color-input));
}
.btn.btn-ghost {
background: transparent;
}
.btn:has(> svg) {
display: flex;
align-items: center;
column-gap: calc(var(--spacing) * 2);
}
.btn:hover {
background: color-mix(in srgb, black 10%, var(--color-primary));
text-decoration: none;
}
resources/css/components/form.css
label {
color: var(--color-foreground);
}
.input {
border-radius: var(--radius-md);
height: calc(var(--spacing) * 10);
width: 100%;
border-width: 1px;
border-color: var(--color-border);
padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
background-color: var(--color-card);
color: var(--color-foreground);
outline: 2px solid transparent;
outline-offset: 2px;
}
.input::placeholder {
color: var(--color-muted-foreground);
}
.input:focus-visible {
outline: 0;
box-shadow:
0 0 0 calc(var(--spacing) * .5) var(--color-background)
0 0 0 calc(var(--spacing) * 1) var(--color-primary);
}
@media (min-width: var(--breakpoint-md)) {
.input {
font-size: var(--text-sm);
}
}
.textarea {
border-radius: var(--radius-md);
height: calc(var(--spacing) * 40);
width: 100%;
border-width: 1px;
border-color: var(--color-border);
padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
background-color: var(--color-card);
color: var(--color-foreground);
outline: 2px solid transparent;
outline-offset: 2px;
}
.textarea::placeholder {
color: var(--color-muted-foreground);
}
.textarea:focus-visible {
outline: 0;
box-shadow:
0 0 0 calc(var(--spacing) * .5) var(--color-background)
0 0 0 calc(var(--spacing) * 1) var(--color-primary);
}
.label {
display: block;
font-size: var(--text-sm);
}
input[type=file] {
display: block;
width: 100%;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-foreground);
}
input[type=file]::file-selector-button {
margin-right: calc(var(--spacing) * 4);
padding: calc(var(--spacing) * 2) calc(var(--spacing) * 4);
border-radius: calc(var(--spacing) * 2);
border-width: 0;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
background-color: var(--color-primary);
color: rgb(var(--color-background));
}
input[type=file]::file-selector-button:hover {
opacity: 0.9;
}
.error {
font-size: var(--text-sm);
color: var(--color-red-600);
}
.form-muted-icon {
color: var(--color-muted-foreground);
}
.form-muted-icon:hover {
color: var(--color-foreground);
}
crscnc liked a comment+100 XP
1mo ago
crscnc wrote a comment+100 XP
1mo ago
crscnc wrote a comment+100 XP
1mo ago
crscnc liked a comment+100 XP
2mos ago
crscnc wrote a comment+100 XP
2mos ago
@RogerManich Maybe a course to increasing front-end complexity for same app?
- blade, 2) livewire, 3) Alpine 4) react
crscnc wrote a comment+100 XP
2mos ago
Hey Jeremy, you ate a JavaScript Sage!
I love this course and would love to see an intermediate Vanilla JS, DOM and Client side APIs and a lot of asynchronous techniques, that advance on complex data structures and talk about BigO notations.
Maybe an CRUD that fetch data from REST and get events from SSE/WS. Process data into entities, deal with trade in and offs of data structures!
crscnc wrote a comment+100 XP
2mos ago
Nice. I assume the S3 SDK is a Singleton, right?
At least S3Storage act as Adapter pattern and take advantage of all features it describes on docs, like async requests, persistent connects, etc.
Probably, the LocalStorage can be upgraded to deal with multiple requests (I believe it can block server until it finishes?)
I really enjoy this serias and hope @Jeffrey can do more OOP courses like that for common App Core or Infra patterns.
Maybe: Loggers for external services liek graphana Multiple fetch clients, that can be instantiated with Fetch, Server Side Events, even WebSockets Create Web Workers and manage their lifecycle, etc...
crscnc liked a comment+100 XP
3mos ago