From 558cc1cc317d461622af7c91e0ea0f945b1495a5 Mon Sep 17 00:00:00 2001 From: Craig Date: Fri, 26 Aug 2022 15:19:44 -0400 Subject: [PATCH] Add form testing helpers --- packages/forms/src/FormsServiceProvider.php | 8 + packages/forms/src/Testing/TestsForms.php | 160 ++++++++++++++++++ .../views/forms/fixtures/form.blade.php | 0 tests/src/Forms/FormsTest.php | 138 +++++++++++++++ 4 files changed, 306 insertions(+) create mode 100644 packages/forms/src/Testing/TestsForms.php create mode 100644 tests/resources/views/forms/fixtures/form.blade.php create mode 100644 tests/src/Forms/FormsTest.php diff --git a/packages/forms/src/FormsServiceProvider.php b/packages/forms/src/FormsServiceProvider.php index 1a51a03559..32b3c08b39 100644 --- a/packages/forms/src/FormsServiceProvider.php +++ b/packages/forms/src/FormsServiceProvider.php @@ -2,8 +2,11 @@ namespace Filament\Forms; +use Filament\Forms\Testing\TestsForms; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; +use Livewire\Testing\TestableLivewire; + class FormsServiceProvider extends PackageServiceProvider { @@ -39,4 +42,9 @@ class FormsServiceProvider extends PackageServiceProvider return array_merge($commands, $aliases); } + + public function packageBooted(): void + { + TestableLivewire::mixin(new TestsForms()); + } } diff --git a/packages/forms/src/Testing/TestsForms.php b/packages/forms/src/Testing/TestsForms.php new file mode 100644 index 0000000000..684f4a114d --- /dev/null +++ b/packages/forms/src/Testing/TestsForms.php @@ -0,0 +1,160 @@ +instance(); + $livewireClass = $livewire::class; + + /** @var ComponentContainer $form */ + $form = $livewire->$name; + + Assert::assertInstanceOf( + ComponentContainer::class, + $form, + "Failed asserting that a form with the name [{$name}] exists on the [{$livewireClass}] component." + ); + + return $this; + }; + } + + public function assertFormFieldExists(): Closure + { + return function (string $fieldName, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormExists($formName); + + $livewire = $this->instance(); + $livewireClass = $livewire::class; + + /** @var ComponentContainer $form */ + $form = $livewire->$formName; + + /** @var ?Field $field */ + $field = data_get($form->getFlatFields(true), $fieldName, null); + + Assert::assertInstanceOf( + Field::class, + $field, + "Failed asserting that a field with the name [{$fieldName}] exists on the form with the name [${formName}] on the [{$livewireClass}] component." + ); + + return $this; + }; + } + + public function assertFormFieldIsDisabled(): Closure + { + return function (string $fieldName, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormFieldExists($fieldName, $formName); + + $livewire = $this->instance(); + $livewireClass = $livewire::class; + + /** @var ComponentContainer $form */ + $form = $livewire->$formName; + + /** @var Field $field */ + $field = $form->getFlatFields(true)[$fieldName]; + + Assert::assertTrue( + $field->isDisabled(), + "Failed asserting that a field with the name [{$fieldName}] is disabled on the form named [{$formName}] on the [{$livewireClass}] component." + ); + + return $this; + }; + } + + public function assertFormFieldIsEnabled(): Closure + { + return function (string $fieldName, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormFieldExists($fieldName, $formName); + + $livewire = $this->instance(); + $livewireClass = $livewire::class; + + /** @var ComponentContainer $form */ + $form = $livewire->$formName; + + /** @var Field $field */ + $field = $form->getFlatFields(true)[$fieldName]; + + Assert::assertFalse( + $field->isDisabled(), + "Failed asserting that a field with the name [{$fieldName}] is enabled on the form named [{$formName}] on the [{$livewireClass}] component." + ); + + return $this; + }; + } + + public function assertFormFieldIsHidden(): Closure + { + return function (string $fieldName, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormFieldExists($fieldName, $formName); + + $livewire = $this->instance(); + $livewireClass = $livewire::class; + + /** @var ComponentContainer $form */ + $form = $livewire->$formName; + + $fields = $form->getFlatFields(); + + Assert::assertArrayNotHasKey( + $fieldName, + $fields, + "Failed asserting that a field with the name [{$fieldName}] is hidden on the form named [{$formName}] on the [{$livewireClass}] component." + ); + + return $this; + }; + } + + public function assertFormFieldIsVisible(): Closure + { + return function (string $fieldName, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormFieldExists($fieldName, $formName); + + $livewire = $this->instance(); + $livewireClass = $livewire::class; + + /** @var ComponentContainer $form */ + $form = $livewire->$formName; + + $fields = $form->getFlatFields(true); + + $fields = $form->getFlatFields(); + + Assert::assertArrayHasKey( + $fieldName, + $fields, + "Failed asserting that a field with the name [{$fieldName}] is hidden on the form named [{$formName}] on the [{$livewireClass}] component." + ); + + return $this; + }; + } +} diff --git a/tests/resources/views/forms/fixtures/form.blade.php b/tests/resources/views/forms/fixtures/form.blade.php new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/src/Forms/FormsTest.php b/tests/src/Forms/FormsTest.php new file mode 100644 index 0000000000..0053597f15 --- /dev/null +++ b/tests/src/Forms/FormsTest.php @@ -0,0 +1,138 @@ +assertFormExists(); +})->only(); + +it('can have forms with non-default names', function() { + livewire(TestComponentWithMultipleForms::class) + ->assertFormExists('fooForm') + ->assertFormExists('barForm'); +})->only(); + +it('has fields', function() { + livewire(TestComponentWithForm::class) + ->assertFormFieldExists('title'); +})->only(); + +it('has fields on multiple forms', function() { + livewire(TestComponentWithMultipleForms::class) + ->assertFormFieldExists('title', 'fooForm') + ->assertFormFieldExists('title', 'barForm'); +})->only(); + +it('can have disabled fields', function() { + livewire(TestComponentWithForm::class) + ->assertFormFieldIsDisabled('disabled'); +})->only(); + +it('can have disabled fields on multiple forms', function() { + livewire(TestComponentWithMultipleForms::class) + ->assertFormFieldIsDisabled('disabled', 'fooForm') + ->assertFormFieldIsDisabled('disabled', 'barForm'); +})->only(); + +it('can have enabled fields', function() { + livewire(TestComponentWithForm::class) + ->assertFormFieldIsEnabled('enabled'); +})->only(); + +it('can have enabled fields on multiple forms', function() { + livewire(TestComponentWithMultipleForms::class) + ->assertFormFieldIsEnabled('enabled', 'fooForm') + ->assertFormFieldIsEnabled('enabled', 'barForm'); +})->only(); + +it('can have hidden fields', function() { + livewire(TestComponentWithForm::class) + ->assertFormFieldIsHidden('hidden'); +})->only(); + +it('can have hidden fields on multiple forms', function() { + livewire(TestComponentWithMultipleForms::class) + ->assertFormFieldIsHidden('hidden', 'fooForm') + ->assertFormFieldIsHidden('hidden', 'barForm'); +})->only(); + +it('can have visible fields', function() { + livewire(TestComponentWithForm::class) + ->assertFormFieldIsVisible('visible'); +})->only(); + +it('can have visible fields on multiple forms', function() { + livewire(TestComponentWithMultipleForms::class) + ->assertFormFieldIsVisible('visible', 'fooForm') + ->assertFormFieldIsVisible('visible', 'barForm'); +})->only(); + +class TestComponentWithForm extends Livewire +{ + public function getFormSchema(): array + { + return [ + TextInput::make('title'), + + TextInput::make('disabled') + ->disabled(), + + TextInput::make('enabled'), + + TextInput::make('hidden') + ->hidden(), + + TextInput::make('visible'), + ]; + } + + public function render(): View + { + return view('forms.fixtures.form'); + } +} + +class TestComponentWithMultipleForms extends Livewire +{ + protected function getForms(): array + { + return [ + 'fooForm' => $this->makeForm() + ->schema($this->getSchemaForForms()), + + 'barForm' => $this->makeForm() + ->schema($this->getSchemaForForms()), + ]; + } + + private function getSchemaForForms(): array + { + return [ + TextInput::make('title'), + + TextInput::make('disabled') + ->disabled(), + + TextInput::make('enabled'), + + TextInput::make('hidden') + ->hidden(), + + TextInput::make('visible'), + ]; + } + + public function render(): View + { + return view('forms.fixtures.form'); + } +}