Question about testing my OrderForm

I have an Order Form which I would like to test. So I have an OrderResource and the url to the form is: admin/orders/create I believe that this corresponds to: 'create' => Pages\CreateOrder::route('/create'), So I wrote a test for this like so:
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
But when I run this I get: Attempt to read property "form" on null.
at vendor/filament/forms/src/Testing/TestsForms.php:125 121▕ public function assertFormExists(): Closure 122▕ { 123▕ return function (string $name = 'form'): static { 124▕ /** @var ComponentContainer $form */ ➜ 125▕ $form = $this->instance()->{$name}; 126▕ 127▕ $livewireClass = $this->instance()::class; 128▕ 129▕ Assert::assertInstanceOf(
MyCreateOrder class doesn't have a form property. I'm wondering where the $form property is set that renders the form when go to the aforementioned url How can I solve this? Thanks
Solution:
you didn't login() ```php it('Can only select suppliers related to the brand', function () { login(); ...
Jump to solution
18 Replies
JJSanders
JJSanders9mo ago
I would appreciate it if someone can have a look at this and let me know what the problem could be. It has to do with testing forms
Bezhan
Bezhan9mo ago
add $this->get(OrderResource::getUrl('create')); before livewire(CreateOrder::class) ...
$this->get(OrderResource::getUrl('create'));

livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
$this->get(OrderResource::getUrl('create'));

livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
JJSanders
JJSanders9mo ago
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
This returns
Unable to find component: [CreateOrder]

at vendor/livewire/livewire/src/Mechanisms/ComponentRegistry.php:25
21▕ }
22▕
23▕ function new($nameOrClass, $id = null)
24▕ {
➜ 25▕ [$class, $name] = $this->getNameAndClass($nameOrClass);
26▕
27▕ $component = new $class;
28▕
29▕ $component->setId($id ?: str()->random(20
Unable to find component: [CreateOrder]

at vendor/livewire/livewire/src/Mechanisms/ComponentRegistry.php:25
21▕ }
22▕
23▕ function new($nameOrClass, $id = null)
24▕ {
➜ 25▕ [$class, $name] = $this->getNameAndClass($nameOrClass);
26▕
27▕ $component = new $class;
28▕
29▕ $component->setId($id ?: str()->random(20
Bezhan
Bezhan9mo ago
can i see your test file?
JJSanders
JJSanders9mo ago
Sure:
<?php

use App\Filament\Resources\OrderResource;
use App\Models\Brand;
use App\Models\Supplier;

use function Pest\Livewire\livewire;

it('Smoketest: it works as it should', function () {
login();
$this->get(OrderResource::getUrl('index'))
->assertSuccessful();
});

it('Can only select suppliers related to the brand', function () {

$brand = Brand::factory()->create();
$suppliers = Supplier::factory()
->count(2)
->hasAttached($brand)
->create();
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
});
<?php

use App\Filament\Resources\OrderResource;
use App\Models\Brand;
use App\Models\Supplier;

use function Pest\Livewire\livewire;

it('Smoketest: it works as it should', function () {
login();
$this->get(OrderResource::getUrl('index'))
->assertSuccessful();
});

it('Can only select suppliers related to the brand', function () {

$brand = Brand::factory()->create();
$suppliers = Supplier::factory()
->count(2)
->hasAttached($brand)
->create();
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
});
Bezhan
Bezhan9mo ago
could you import the CreateOrder page and try?
JJSanders
JJSanders9mo ago
sure: But that gives me.
Attempt to read property "form" on null

at vendor/filament/forms/src/Testing/TestsForms.php:125
121▕ public function assertFormExists(): Closure
122▕ {
123▕ return function (string $name = 'form'): static {
124▕ /** @var ComponentContainer $form */
➜ 125▕ $form = $this->instance()->{$name};
126▕
127▕ $livewireClass = $this->instance()::class;
128▕
129▕ Assert::assertInstanceOf(

+5 vendor frames
6 tests/Feature/OrderTest.php:25
Attempt to read property "form" on null

at vendor/filament/forms/src/Testing/TestsForms.php:125
121▕ public function assertFormExists(): Closure
122▕ {
123▕ return function (string $name = 'form'): static {
124▕ /** @var ComponentContainer $form */
➜ 125▕ $form = $this->instance()->{$name};
126▕
127▕ $livewireClass = $this->instance()::class;
128▕
129▕ Assert::assertInstanceOf(

+5 vendor frames
6 tests/Feature/OrderTest.php:25
This to me sounds logic since my CreateOrder page doesn't have a form:
namespace App\Filament\Resources\OrderResource\Pages;

use App\Filament\Resources\OrderResource;
use Filament\Resources\Pages\CreateRecord;

class CreateOrder extends CreateRecord
{
protected static string $resource = OrderResource::class;

protected function getRedirectUrl(): string
{
return $this->previousUrl ?? $this->getResource()::getUrl('index');
}

protected function mutateFormDataBeforeCreate(array $data): array
{
$data['user_id'] = auth()->id();

return $data;
}
}
namespace App\Filament\Resources\OrderResource\Pages;

use App\Filament\Resources\OrderResource;
use Filament\Resources\Pages\CreateRecord;

class CreateOrder extends CreateRecord
{
protected static string $resource = OrderResource::class;

protected function getRedirectUrl(): string
{
return $this->previousUrl ?? $this->getResource()::getUrl('index');
}

protected function mutateFormDataBeforeCreate(array $data): array
{
$data['user_id'] = auth()->id();

return $data;
}
}
Bezhan
Bezhan9mo ago
no, import the CreateOrder class in your test like use App\Filament\Resources\OrderResource\Pages\CreateOrder;
JJSanders
JJSanders9mo ago
I did so:
<?php

use App\Filament\Resources\OrderResource;
use App\Filament\Resources\OrderResource\Pages\CreateOrder;
use App\Models\Brand;
use App\Models\Supplier;

use function Pest\Livewire\livewire;

it('Smoketest: it works as it should', function () {
login();
$this->get(OrderResource::getUrl('index'))
->assertSuccessful();
});

it('Can only select suppliers related to the brand', function () {

$brand = Brand::factory()->create();
$suppliers = Supplier::factory()
->count(2)
->hasAttached($brand)
->create();
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
});
<?php

use App\Filament\Resources\OrderResource;
use App\Filament\Resources\OrderResource\Pages\CreateOrder;
use App\Models\Brand;
use App\Models\Supplier;

use function Pest\Livewire\livewire;

it('Smoketest: it works as it should', function () {
login();
$this->get(OrderResource::getUrl('index'))
->assertSuccessful();
});

it('Can only select suppliers related to the brand', function () {

$brand = Brand::factory()->create();
$suppliers = Supplier::factory()
->count(2)
->hasAttached($brand)
->create();
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
});
Bezhan
Bezhan9mo ago
and what is the result? it should say something like failed asserting that null matches expected ?? since you are not setting the supplier_id and then asserting that it's set.
JJSanders
JJSanders9mo ago
This is the result:
Attempt to read property "form" on null

at vendor/filament/forms/src/Testing/TestsForms.php:125
121▕ public function assertFormExists(): Closure
122▕ {
123▕ return function (string $name = 'form'): static {
124▕ /** @var ComponentContainer $form */
➜ 125▕ $form = $this->instance()->{$name};
126▕
127▕ $livewireClass = $this->instance()::class;
128▕
129▕ Assert::assertInstanceOf(

+5 vendor frames
6 tests/Feature/OrderTest.php:25
Attempt to read property "form" on null

at vendor/filament/forms/src/Testing/TestsForms.php:125
121▕ public function assertFormExists(): Closure
122▕ {
123▕ return function (string $name = 'form'): static {
124▕ /** @var ComponentContainer $form */
➜ 125▕ $form = $this->instance()->{$name};
126▕
127▕ $livewireClass = $this->instance()::class;
128▕
129▕ Assert::assertInstanceOf(

+5 vendor frames
6 tests/Feature/OrderTest.php:25
Solution
Bezhan
Bezhan9mo ago
you didn't login()
it('Can only select suppliers related to the brand', function () {
login();

$brand = Brand::factory()->create();
$suppliers = Supplier::factory()
->count(2)
->hasAttached($brand)
->create();
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
});
it('Can only select suppliers related to the brand', function () {
login();

$brand = Brand::factory()->create();
$suppliers = Supplier::factory()
->count(2)
->hasAttached($brand)
->create();
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->fillForm([
'brand_id' => $brand->id,
])->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
});
JJSanders
JJSanders9mo ago
L E G E N D ! ! ! 🔥 🔥 🔥 Thanks soo much!
Bezhan
Bezhan9mo ago
np, cheers!
JJSanders
JJSanders9mo ago
Actually I should do a beforeEach(login());
Bezhan
Bezhan9mo ago
or use the setUp() method. for more, test cases and ref, checkout the filament codebase itself.
Bezhan
Bezhan9mo ago
GitHub
filament/tests at 3.x · filamentphp/filament
A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS. - filamentphp/filament
JJSanders
JJSanders9mo ago
Tnx!
Want results from more Discord servers?
Add your server