From 8ab36adac902a1d5ba1c1f0fd0ce5bf308ed31b9 Mon Sep 17 00:00:00 2001 From: Alan Ostaszewski Date: Fri, 6 Jun 2025 21:07:32 +0200 Subject: [PATCH 1/6] test: add test for hidden section fields in dehydrated state --- tests/src/Forms/StateTest.php | 59 ++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/tests/src/Forms/StateTest.php b/tests/src/Forms/StateTest.php index 35b1003085..04c533c38b 100644 --- a/tests/src/Forms/StateTest.php +++ b/tests/src/Forms/StateTest.php @@ -1,12 +1,15 @@ getContent()->toBe($state); }); + +test( + 'fields in hidden section should not be included in dehydrated state', + function () { + $container = ComponentContainer::make(Livewire::make()) + ->components([ + Section::make("User Information") + ->statePath('data') + ->schema([ + Radio::make('show_input') + ->label('Control Input Visibility') + ->options([ + 'show' => 'Show', + 'hide' => 'Hide', + ]) + ->live(), + + Section::make("Name") + ->schema([ + TextInput::make('name') + ->label('Conditional Name') + ]) + ->hidden(fn (Get $get): bool => $get('show_input') === 'hide' || $get('show_input') === null) + ->dehydrated(fn (Get $get): bool => $get('show_input') === 'show'), + ]), + ]) + ->fill([ + 'data' => [ + 'show_input' => 'hide', + 'name' => 'lorem ipsum', + ] + ]); + + $dehydratedState = $container->dehydrateState(); + + // Assert: Expect 'name' field NOT to be present in dehydrated state when 'show_input' is 'hide' + // This assertion is designed to FAIL due to the bug, thus documenting it. + expect($dehydratedState) + ->toBe([ + 'data' => [ + 'show_input' => 'hide', + // 'name' field with 'lorem ipsum' should NOT be here if the bug was fixed. + ], + ]); + } +); \ No newline at end of file From 0955707182c8c805d2dea2178f7c4eb919a150d8 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Tue, 10 Jun 2025 16:27:40 +0100 Subject: [PATCH 2/6] clean up and fix test --- .../src/Components/Concerns/HasState.php | 3 +- tests/src/Forms/StateTest.php | 68 ++++++------------- 2 files changed, 24 insertions(+), 47 deletions(-) diff --git a/packages/forms/src/Components/Concerns/HasState.php b/packages/forms/src/Components/Concerns/HasState.php index 04358a6b59..aae40267ae 100644 --- a/packages/forms/src/Components/Concerns/HasState.php +++ b/packages/forms/src/Components/Concerns/HasState.php @@ -4,6 +4,7 @@ namespace Filament\Forms\Components\Concerns; use Closure; use Filament\Forms\Components\Component; +use Filament\Forms\Components\Section; use Filament\Forms\Get; use Filament\Forms\Set; use Illuminate\Contracts\Support\Arrayable; @@ -189,7 +190,7 @@ trait HasState // we need to dehydrate the child component containers while // informing them that they are not dehydrated, so that their // child components get removed from the state. - foreach ($this->getChildComponentContainers() as $container) { + foreach ($this->getChildComponentContainers(withHidden: true) as $container) { $container->dehydrateState($state, isDehydrated: false); } diff --git a/tests/src/Forms/StateTest.php b/tests/src/Forms/StateTest.php index 04c533c38b..986537a9ea 100644 --- a/tests/src/Forms/StateTest.php +++ b/tests/src/Forms/StateTest.php @@ -602,6 +602,28 @@ test('hidden components are not excluded from state dehydration if there is anot ->dehydrateState()->data->not()->toBe([]); }); +test('components in a hidden parent component with a grandparent component with a state path are excluded from state dehydration', function () { + $container = ComponentContainer::make(Livewire::make()) + ->statePath('data') + ->components([ + (new Component) + ->statePath(Str::random()) + ->schema([ + (new Component) + ->schema([ + (new Component) + ->statePath(Str::random()) + ->default(Str::random()), + ]) + ->hidden(), + ]), + ]) + ->fill(); + + expect($container) + ->dehydrateState()->toBe([]); +}); + test('disabled components are excluded from state dehydration', function () { $container = ComponentContainer::make(Livewire::make()) ->statePath('data') @@ -800,49 +822,3 @@ test('parent sibling state can be retrieved absolutely from another component', expect($placeholder) ->getContent()->toBe($state); }); - -test( - 'fields in hidden section should not be included in dehydrated state', - function () { - $container = ComponentContainer::make(Livewire::make()) - ->components([ - Section::make("User Information") - ->statePath('data') - ->schema([ - Radio::make('show_input') - ->label('Control Input Visibility') - ->options([ - 'show' => 'Show', - 'hide' => 'Hide', - ]) - ->live(), - - Section::make("Name") - ->schema([ - TextInput::make('name') - ->label('Conditional Name') - ]) - ->hidden(fn (Get $get): bool => $get('show_input') === 'hide' || $get('show_input') === null) - ->dehydrated(fn (Get $get): bool => $get('show_input') === 'show'), - ]), - ]) - ->fill([ - 'data' => [ - 'show_input' => 'hide', - 'name' => 'lorem ipsum', - ] - ]); - - $dehydratedState = $container->dehydrateState(); - - // Assert: Expect 'name' field NOT to be present in dehydrated state when 'show_input' is 'hide' - // This assertion is designed to FAIL due to the bug, thus documenting it. - expect($dehydratedState) - ->toBe([ - 'data' => [ - 'show_input' => 'hide', - // 'name' field with 'lorem ipsum' should NOT be here if the bug was fixed. - ], - ]); - } -); \ No newline at end of file From a3b0f0f8aa9747d56e631281887e63efef2c2749 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Tue, 10 Jun 2025 16:29:05 +0100 Subject: [PATCH 3/6] Update StateTest.php --- tests/src/Forms/StateTest.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/src/Forms/StateTest.php b/tests/src/Forms/StateTest.php index 986537a9ea..26c001d434 100644 --- a/tests/src/Forms/StateTest.php +++ b/tests/src/Forms/StateTest.php @@ -1,15 +1,12 @@ Date: Tue, 10 Jun 2025 16:29:20 +0100 Subject: [PATCH 4/6] Update HasState.php --- packages/forms/src/Components/Concerns/HasState.php | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/forms/src/Components/Concerns/HasState.php b/packages/forms/src/Components/Concerns/HasState.php index aae40267ae..218549eba2 100644 --- a/packages/forms/src/Components/Concerns/HasState.php +++ b/packages/forms/src/Components/Concerns/HasState.php @@ -4,7 +4,6 @@ namespace Filament\Forms\Components\Concerns; use Closure; use Filament\Forms\Components\Component; -use Filament\Forms\Components\Section; use Filament\Forms\Get; use Filament\Forms\Set; use Illuminate\Contracts\Support\Arrayable; From 2fa5f19f322bd1391884572c7701bf8d39674bff Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Tue, 10 Jun 2025 16:31:51 +0100 Subject: [PATCH 5/6] Update StateTest.php --- tests/src/Forms/StateTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/Forms/StateTest.php b/tests/src/Forms/StateTest.php index 26c001d434..a0763fb271 100644 --- a/tests/src/Forms/StateTest.php +++ b/tests/src/Forms/StateTest.php @@ -604,7 +604,7 @@ test('components in a hidden parent component with a grandparent component with ->statePath('data') ->components([ (new Component) - ->statePath(Str::random()) + ->statePath('data') ->schema([ (new Component) ->schema([ @@ -618,7 +618,7 @@ test('components in a hidden parent component with a grandparent component with ->fill(); expect($container) - ->dehydrateState()->toBe([]); + ->dehydrateState()->toBe(['data' => []]); }); test('disabled components are excluded from state dehydration', function () { From e51bceb60a017b0394f319d1c542a2c5de9cfc24 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Tue, 10 Jun 2025 16:34:34 +0100 Subject: [PATCH 6/6] Update StateTest.php --- tests/src/Forms/StateTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Forms/StateTest.php b/tests/src/Forms/StateTest.php index a0763fb271..484cc4ea64 100644 --- a/tests/src/Forms/StateTest.php +++ b/tests/src/Forms/StateTest.php @@ -618,7 +618,7 @@ test('components in a hidden parent component with a grandparent component with ->fill(); expect($container) - ->dehydrateState()->toBe(['data' => []]); + ->dehydrateState()->toBe(['data' => ['data' => []]]); }); test('disabled components are excluded from state dehydration', function () {