MohamedAbdalla started a new conversation+100 XP
1d ago
Hi everyone,
I'm running into an issue with a PEST browser test that I can't figure out.
The feature works perfectly when I test it manually in the browser, but the browser test fails because the record is never created.
Test
it('create idea', function () {
$this->actingAs($user = User::factory()->create());
$title = 'some test title';
$description = 'some test description';
$status = 'in_progress';
visit('/ideas')
->click('@create-idea-button')
->fill('title', $title)
->click('@status-button-'.$status)
->fill('description', $description)
->fill('@new-step-input', 'some step description')
->click('@add-step-button')
->fill('@new-link-input', 'https://example.com')
->click('@add-link-button')
->fill('@new-link-input', 'https://example2.com')
->click('@add-link-button')
->click('Create')
->assertPathIs('/ideas');
expect($user->ideas()->count())->toBe(1);
});
The assertion fails:
Expected: 1 Actual: 0
So it looks like the form submission never creates the Idea.
Controller
public function store(StoreIdeaRequest $request, CreateIdea $action)
{
$action->handle($request->safe()->all());
return to_route('idea.index')
->with('success', 'Idea created successfully.');
}
Action
class CreateIdea
{
public function __construct(
#[CurrentUser] protected User $user
) {}
public function handle(array $attributes): void
{
$data = collect($attributes)->only([
'title',
'description',
'status',
'links',
])->toArray();
if ($attributes['image'] ?? false) {
$data['image_path'] = $attributes['image']->store('ideasImages', 'public');
}
$steps = collect($attributes['steps'] ?? [])
->map(fn ($step) => ['description' => $step]);
DB::transaction(function () use ($steps, $data) {
$idea = $this->user->ideas()->create($data);
$idea->steps()->createMany($steps);
});
}
}
Form
The form is a normal POST form, but it uses Alpine.js to manage the dynamic steps[] and links[] inputs.
The submit button is:
<button type="submit" class="btn btn-primary">
Create
</button>
What I've verified
- The feature works correctly when used manually in the browser.
- The browser test reaches
assertPathIs('/ideas'). - No Idea record is
created ($user->ideas()->count() returns 0). - Earlier I also saw the exception:
No query results for model [App\Models\Idea]
it('create idea', function () {
$this->actingAs($user = User::factory()->create());
$title = 'some test title';
$description = 'some test description';
$status = 'in_progress';
visit('/ideas')
->click('@create-idea-button')
->fill('title', $title)
->click('@status-button-'.$status)
->fill('description', $description)
->fill('@new-step-input', 'some step description')
->click('@add-step-button')
->fill('@new-link-input', 'https://example.com')
->click('@add-link-button')
->fill('@new-link-input', 'https://example2.com')
->click('@add-link-button')
->click('Create')
->assertPathIs('/ideas');
$idea = $user->ideas()->sole();
expect($idea->title)->toBe($title)
->and($idea->description)->toBe($description)
->and($idea->status->value)->toBe($status)
->and($idea->links->getArrayCopy())->toBe([
'https://example.com',
'https://example2.com',
]);
expect($idea->steps)->toHaveCount(1);
});
which I now suspect is just a consequence of the record never being created.
Has anyone experienced this with PEST Browser Testing? Is there something about authentication, Alpine.js updates, form submission, or browser sessions that I might be missing?
Any suggestions would be greatly appreciated.
MohamedAbdalla wrote a comment+100 XP
2d ago
Route::patch('/steps/{step}',[StepController::class,'update'])->name('step.update')->middleware('auth');
<form method="POST" action="{{ route('step.update',$step) }}" >
@csrf
@method('PATCH')
....
</form>
still the browser rendering as GET request ?!
uri
/steps/2
method
GET
format
html
content_type
text/html; charset=utf-8
status_text
Method Not Allowed
status_code
405
request_query
array:2 [▼
"_token" => "h3***Br"
"_method" => "patch"
]
MohamedAbdalla wrote a comment+100 XP
6d ago
#resources>css>components>form.css
.form-muted-icon { color: var(--color-muted-foreground); }
.form-muted-icon:hover { color: var(--color-foreground); }
MohamedAbdalla liked a comment+100 XP
2mos ago
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\TypeDeclaration\Rector\ArrowFunction\AddArrowFunctionReturnTypeRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictTypedCallRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnUnionTypeRector;
use Rector\TypeDeclaration\Rector\Closure\AddClosureVoidReturnTypeWhereNoReturnRector;
use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector;
use RectorLaravel\Set\LaravelSetProvider;
return RectorConfig::configure()
->withPaths([
__DIR__.'/app',
__DIR__.'/bootstrap',
__DIR__.'/config',
__DIR__.'/public',
__DIR__.'/resources',
__DIR__.'/routes',
__DIR__.'/tests',
])
->withSkip([
__DIR__.'/bootstrap/cache',
__DIR__.'/storage',
__DIR__.'/vendor',
AddClosureVoidReturnTypeWhereNoReturnRector::class,
ReturnTypeFromStrictTypedCallRector::class,
ReturnUnionTypeRector::class,
DeclareStrictTypesRector::class => [
__DIR__.'/resources/views',
],
AddArrowFunctionReturnTypeRector::class,
])
->withPhpSets()
->withSetProviders(LaravelSetProvider::class)
->withImportNames()
->withComposerBased(laravel: true)
->withPreparedSets(
deadCode: true,
codeQuality: true,
typeDeclarations: true,
privatization: true,
earlyReturn: true,
)
->withRules([
DeclareStrictTypesRector::class,
]);