I'm trying to test a form that when I select a brand it should prefill the related suppliers in the next select. In my form I user the ->live() method to make the fields dependent on each other. In my test i have:
$brand = Brand::factory()->create();
$suppliers = Supplier::factory()
->count(2)
->hasAttached($brand)
->create();
$this->get(OrderResource::getUrl('create'));
livewire(CreateOrder::class)
->assertFormFieldExists('brand_id')
->fillForm([
'brand_id' => $brand->id,
])
->assertFormSet(['supplier_id' => $suppliers->pluck('id')->toArray()]);
However this doesn't work, I get the error:
Failed asserting that null matches expected 1.
at vendor/livewire/livewire/src/Features/SupportTesting/MakesAssertions.php:93
89▕
90▕ if (! is_string($value) && is_callable($value)) {
91▕ PHPUnit::assertTrue($value($actual));
92▕ } else {
➜ 93▕ $strict ? PHPUnit::assertSame($value, $actual) : PHPUnit::assertEquals($value, $actual);
94▕ }
95▕
96▕ return $this;
97▕ }
I have tried to log what the value is of the suppliers. And I have confirmed that the options are empty. How Can I solve this, or where can I read about testing these dependent fields. Thanks.
You didn t show the form but it must be similar to the one below (the example form below is the one shown here:
class CreateOrder extends Component implements HasForms
{
use InteractsWithForms;
public $brandId;
public $supplierId;
public function getFormSchema(): array
{
return [
Select::make('brandId')
->label('Brands')
->options(Brand::all()->pluck('name','id')->toArray())
->reactive(),
Select::make('supplierId')
->label('Suppliers')
->options(function(callable $get){
$brand = Brand::find($get('brandId'));
if(!$brand){
return Supplier::all()->pluck('title','id');
}
return $brand->suppliers->pluck('title','id');
})
];
}
public function render():View
{
return view('livewire.createorder');
}
}
The form has 2 dependant selects, the second one lists all suppliers in the database if no brand is chosen in the first select, but if a brand is chosen it re-renders to list only the suppliers that belongs to the chosen brand.
Below is the test:
it('has dependant fields with logic ok', function () {
$brand = Brand::factory()->create();
$brand2 = Brand::factory()->create();
$suppliersVisible = Supplier::factory()
->count(2)->create(['user_id' => $brand->id, 'title'=>fake()->sentence()]);
$suppliersHidden = Supplier::factory()
->count(2)->create(['user_id' => $brand2->id,'title'=>fake()->sentence()]);
livewire(CreateOrder::class)
->fillForm([
'brandId' => $brand->id,
])
->assertSee($suppliersVisible[0]->title)
->assertSee($suppliersVisible[1]->title)
->assertDontSee($suppliersHidden[0]->title)
->assertDontSee($suppliersHidden[1]->title);
});
The test populate the db with 2 brands and each brand has 2 suppliers.
The test passes if only the suppliers for the selected brand are shown after the re-render.
The assertFormSet method is to test state of the form, but in this case there is no state, we have to test what the page shows.