diff --git a/packages/actions/.stubs.php b/packages/actions/.stubs.php index 14566b445c..734901431c 100644 --- a/packages/actions/.stubs.php +++ b/packages/actions/.stubs.php @@ -3,7 +3,7 @@ namespace Livewire\Features\SupportTesting { class Testable { - public function mountAction(string $name, array $arguments = []): static {} + public function mountAction(string | array $name, array $arguments = []): static {} public function unmountAction(): static {} @@ -11,53 +11,53 @@ namespace Livewire\Features\SupportTesting { public function assertActionDataSet(array $data): static {} - public function callAction(string $name, array $data = [], array $arguments = []): static {} + public function callAction(string | array $name, array $data = [], array $arguments = []): static {} public function callMountedAction(array $arguments = []): static {} - public function assertActionExists(string $name): static {} + public function assertActionExists(string | array $name): static {} - public function assertActionDoesNotExist(string $name): static {} + public function assertActionDoesNotExist(string | array $name): static {} - public function assertActionVisible(string $name): static {} + public function assertActionVisible(string | array $name): static {} - public function assertActionHidden(string $name): static {} + public function assertActionHidden(string | array $name): static {} - public function assertActionEnabled(string $name): static {} + public function assertActionEnabled(string | array $name): static {} - public function assertActionDisabled(string $name): static {} + public function assertActionDisabled(string | array $name): static {} - public function assertActionHasIcon(string $name, string $icon): static {} + public function assertActionHasIcon(string | array $name, string $icon): static {} - public function assertActionDoesNotHaveIcon(string $name, string $icon): static {} + public function assertActionDoesNotHaveIcon(string | array $name, string $icon): static {} - public function assertActionHasLabel(string $name, string $label): static {} + public function assertActionHasLabel(string | array $name, string $label): static {} - public function assertActionHasColor(string $name, string $color): static {} + public function assertActionHasColor(string | array $name, string $color): static {} - public function assertActionDoesNotHaveColor(string $name, string $color): static {} + public function assertActionDoesNotHaveColor(string | array $name, string $color): static {} - public function assertActionHasUrl(string $name, string $url): static {} + public function assertActionHasUrl(string | array $name, string $url): static {} - public function assertActionDoesNotHaveUrl(string $name, string $url): static {} + public function assertActionDoesNotHaveUrl(string | array $name, string $url): static {} - public function assertActionShouldOpenUrlInNewTab(string $name): static {} + public function assertActionShouldOpenUrlInNewTab(string | array $name): static {} - public function assertActionShouldNotOpenUrlInNewTab(string $name): static {} + public function assertActionShouldNotOpenUrlInNewTab(string | array $name): static {} - public function assertActionDoesNotHaveLabel(string $name, string $label): static {} + public function assertActionDoesNotHaveLabel(string | array $name, string $label): static {} - public function assertActionMounted(string $name): static {} + public function assertActionMounted(string | array $name): static {} - public function assertActionNotMounted(string $name): static {} + public function assertActionNotMounted(string | array $name): static {} - public function assertActionHalted(string $name): static {} + public function assertActionHalted(string | array $name): static {} public function assertHasActionErrors(array $keys = []): static {} public function assertHasNoActionErrors(array $keys = []): static {} - public function parseActionName(string $name): string {} + public function parseActionName(string | array $name): string {} public function parseNestedActionName(string | array $name): array {} } diff --git a/packages/forms/.stubs.php b/packages/forms/.stubs.php index 194a215f89..6b5032dee5 100644 --- a/packages/forms/.stubs.php +++ b/packages/forms/.stubs.php @@ -4,6 +4,8 @@ use Closure; namespace Livewire\Features\SupportTesting { + use Illuminate\Support\Collection; + class Testable { public function fillForm(array $state = [], string $formName = 'form'): static {} @@ -13,7 +15,7 @@ namespace Livewire\Features\SupportTesting { public function assertHasNoFormErrors(array $keys = [], string $formName = 'form'): static {} - public function assertFormExists(string $name = 'form'): static {} + public function assertFormExists(string | array $name = 'form'): static {} public function assertFormFieldExists(string $fieldName, string | Closure $formName = 'form', ?Closure $checkFieldUsing = null): static {} @@ -24,6 +26,64 @@ namespace Livewire\Features\SupportTesting { public function assertFormFieldIsHidden(string $fieldName, string $formName = 'form'): static {} public function assertFormFieldIsVisible(string $fieldName, string $formName = 'form'): static {} + + public function mountFormComponentAction(string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static {} + + public function unmountFormComponentAction(): static {} + + public function setFormComponentActionData(array $data): static {} + + public function assertFormComponentActionDataSet(array $data): static {} + + public function callFormComponentAction(string | array $component, string | array $name, array $data = [], array $arguments = [], string $formName = 'form'): static {} + + public function callMountedFormComponentAction(array $arguments = []): static {} + + public function assertFormComponentActionExists(string | array $component, string | array $name, string $formName = 'form'): static {} + + public function assertFormComponentActionDoesNotExist(string | array $component, string | array $name, string $formName = 'form'): static {} + + public function assertFormComponentActionVisible(string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionHidden(string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionEnabled(string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionDisabled(string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionMounted(string | array $component, string | array $name, string $formName = 'form'): static {} + + public function assertFormComponentActionNotMounted(string | array $component, string | array $name, string $formName = 'form'): static {} + + public function assertFormComponentActionHalted(string | array $component, string | array $name, string $formName = 'form'): static {} + + public function assertHasFormComponentActionErrors(array $keys = []): static {} + + public function assertHasNoFormComponentActionErrors(array $keys = []): static {} + + public function assertFormComponentActionHasIcon(string | array $component, string | array $name, string $icon, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionDoesNotHaveIcon(string | array $component, string | array $name, string $icon, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionHasLabel(string | array $component, string | array $name, string $label, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionDoesNotHaveLabel(string | array $component, string | array $name, string $label, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionHasColor(string | array $component, string | array $name, string | array $color, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionDoesNotHaveColor(string | array $component, string | array $name, string | array $color, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionHasUrl(string | array $component, string | array $name, string $url, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionDoesNotHaveUrl(string | array $component, string | array $name, string $url, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionShouldOpenUrlInNewTab(string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static {} + + public function assertFormComponentActionShouldNotOpenUrlInNewTab(string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static {} + + public function getNestedFormComponentActionComponentAndName(string | array $component, string | array $name, string $formName = 'form'): static {} + + public function parseNestedFormComponentActionComponentAndName(string | array $component, string | array $name, string $formName = 'form'): static {} } } diff --git a/packages/forms/docs/09-testing.md b/packages/forms/docs/09-testing.md index 262f12ae69..ee1c0dee99 100644 --- a/packages/forms/docs/09-testing.md +++ b/packages/forms/docs/09-testing.md @@ -172,3 +172,264 @@ test('title is disabled', function () { ``` > For both `assertFormFieldIsEnabled()` and `assertFormFieldIsDisabled()` you can pass the name of a specific form the field belongs to as the second argument like `assertFormFieldIsEnabled('title', 'createPostForm')`. + +## Actions + +You can call an action by passing its form component name, and then the name of the action to `callFormComponentAction()`: + +```php +use function Pest\Livewire\livewire; + +it('can send invoices', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->callFormComponentAction('customer_id', 'send'); + + expect($invoice->refresh()) + ->isSent()->toBeTrue(); +}); +``` + +To pass an array of data into an action, use the `data` parameter: + +```php +use function Pest\Livewire\livewire; + +it('can send invoices', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->callAction('customer_id', 'send', data: [ + 'email' => $email = fake()->email(), + ]) + ->assertHasNoFormComponentActionErrors(); + + expect($invoice->refresh()) + ->isSent()->toBeTrue() + ->recipient_email->toBe($email); +}); +``` + +If you ever need to only set an action's data without immediately calling it, you can use `setFormComponentActionData()`: + +```php +use function Pest\Livewire\livewire; + +it('can send invoices', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->mountFormComponentAction('customer_id', 'send') + ->setFormComponentActionData('customer_id', 'send', data: [ + 'email' => $email = fake()->email(), + ]) +}); +``` + +### Execution + +To check if an action has been halted, you can use `assertFormComponentActionHalted()`: + +```php +use function Pest\Livewire\livewire; + +it('stops sending if invoice has no email address', function () { + $invoice = Invoice::factory(['email' => null])->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->callFormComponentAction('customer_id', 'send') + ->assertFormComponentActionHalted('customer_id', 'send'); +}); +``` + +### Errors + +`assertHasNoFormComponentActionErrors()` is used to assert that no validation errors occurred when submitting the action form. + +To check if a validation error has occurred with the data, use `assertHasFormComponentActionErrors()`, similar to `assertHasErrors()` in Livewire: + +```php +use function Pest\Livewire\livewire; + +it('can validate invoice recipient email', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->callFormComponentAction('customer_id', 'send', data: [ + 'email' => Str::random(), + ]) + ->assertHasFormComponentActionErrors(['email' => ['email']]); +}); +``` + +To check if an action is pre-filled with data, you can use the `assertFormComponentActionDataSet()` method: + +```php +use function Pest\Livewire\livewire; + +it('can send invoices to the primary contact by default', function () { + $invoice = Invoice::factory()->create(); + $recipientEmail = $invoice->company->primaryContact->email; + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->mountFormComponentAction('customer_id', 'send') + ->assertFormComponentActionDataSet([ + 'email' => $recipientEmail, + ]) + ->callMountedFormComponentAction() + ->assertHasNoFormComponentActionErrors(); + + expect($invoice->refresh()) + ->isSent()->toBeTrue() + ->recipient_email->toBe($recipientEmail); +}); +``` + +### Action state + +To ensure that an action exists or doesn't in a table, you can use the `assertFormComponentActionExists()` or `assertFormComponentActionDoesNotExist()` method: + +```php +use function Pest\Livewire\livewire; + +it('can send but not unsend invoices', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertFormComponentActionExists('customer_id', 'send') + ->assertFormComponentActionDoesNotExist('customer_id', 'unsend'); +}); +``` + +To ensure an action is hidden or visible for a user, you can use the `assertFormComponentActionHidden()` or `assertFormComponentActionVisible()` methods: + +```php +use function Pest\Livewire\livewire; + +it('can only print customers', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertFormComponentActionHidden('customer_id', 'send') + ->assertFormComponentActionVisible('customer_id', 'print'); +}); +``` + +To ensure an action is enabled or disabled for a user, you can use the `assertFormComponentActionEnabled()` or `assertFormComponentActionDisabled()` methods: + +```php +use function Pest\Livewire\livewire; + +it('can only print a customer for a sent invoice', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertFormComponentActionDisabled('customer_id', 'send') + ->assertFormComponentActionEnabled('customer_id', 'print'); +}); +``` + +To check if an action is hidden to a user, you can use the `assertFormComponentActionHidden()` method: + +```php +use function Pest\Livewire\livewire; + +it('can not send invoices', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertFormComponentActionHidden('customer_id', 'send'); +}); +``` + +### Button appearance + +To ensure an action has the correct label, you can use `assertFormComponentActionHasLabel()` and `assertFormComponentActionDoesNotHaveLabel()`: + +```php +use function Pest\Livewire\livewire; + +it('send action has correct label', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertFormComponentActionHasLabel('customer_id', 'send', 'Email Invoice') + ->assertFormComponentActionDoesNotHaveLabel('customer_id', 'send', 'Send'); +}); +``` + +To ensure an action's button is showing the correct icon, you can use `assertFormComponentActionHasIcon()` or `assertFormComponentActionDoesNotHaveIcon()`: + +```php +use function Pest\Livewire\livewire; + +it('when enabled the send button has correct icon', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertFormComponentActionEnabled('customer_id', 'send') + ->assertFormComponentActionHasIcon('customer_id', 'send', 'envelope-open') + ->assertFormComponentActionDoesNotHaveIcon('customer_id', 'send', 'envelope'); +}); +``` + +To ensure that an action's button is displaying the right color, you can use `assertFormComponentActionHasColor()` or `assertFormComponentActionDoesNotHaveColor()`: + +```php +use function Pest\Livewire\livewire; + +it('actions display proper colors', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertFormComponentActionHasColor('customer_id', 'delete', 'danger') + ->assertFormComponentActionDoesNotHaveColor('customer_id', 'print', 'danger'); +}); +``` + +### URL + +To ensure an action has the correct URL, you can use `assertFormComponentActionHasUrl()`, `assertFormComponentActionDoesNotHaveUrl()`, `assertFormComponentActionShouldOpenUrlInNewTab()`, and `assertFormComponentActionShouldNotOpenUrlInNewTab()`: + +```php +use function Pest\Livewire\livewire; + +it('links to the correct Filament sites', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertFormComponentActionHasUrl('customer_id', 'filament', 'https://filamentphp.com/') + ->assertFormComponentActionDoesNotHaveUrl('customer_id', 'filament', 'https://github.com/filamentphp/filament') + ->assertFormComponentActionShouldOpenUrlInNewTab('customer_id', 'filament') + ->assertFormComponentActionShouldNotOpenUrlInNewTab('customer_id', 'github'); +}); +``` diff --git a/packages/forms/src/FormsServiceProvider.php b/packages/forms/src/FormsServiceProvider.php index f3cf4927f8..c5ffa94b43 100644 --- a/packages/forms/src/FormsServiceProvider.php +++ b/packages/forms/src/FormsServiceProvider.php @@ -2,6 +2,7 @@ namespace Filament\Forms; +use Filament\Forms\Testing\TestsComponentActions; use Filament\Forms\Testing\TestsForms; use Filament\Support\Assets\AlpineComponent; use Filament\Support\Assets\Css; @@ -46,6 +47,7 @@ class FormsServiceProvider extends PackageServiceProvider } Testable::mixin(new TestsForms()); + Testable::mixin(new TestsComponentActions()); } /** diff --git a/packages/forms/src/Testing/TestsComponentActions.php b/packages/forms/src/Testing/TestsComponentActions.php new file mode 100644 index 0000000000..d144803c4f --- /dev/null +++ b/packages/forms/src/Testing/TestsComponentActions.php @@ -0,0 +1,595 @@ +parseNestedFormComponentActionComponentAndName($component, $name, $formName); + + foreach ($name as $actionNestingIndex => $actionName) { + $this->call( + 'mountFormComponentAction', + $component[$actionNestingIndex], + $actionName, + $arguments, + ); + } + + if (store($this->instance())->has('redirect')) { + return $this; + } + + if (! count($this->instance()->mountedFormComponentActions)) { + $this->assertNotDispatched('open-modal'); + + return $this; + } + + $this->assertSet('mountedFormComponentActionsComponents', $component); + $this->assertSet('mountedFormComponentActions', $name); + + $this->assertDispatched('open-modal', id: "{$this->instance()->getId()}-form-component-action"); + + return $this; + }; + } + + public function unmountFormComponentAction(): Closure + { + return function (): static { + $this->call('unmountFormComponentAction'); + + return $this; + }; + } + + public function setFormComponentActionData(): Closure + { + return function (array $data): static { + foreach (Arr::dot($data, prepend: 'mountedFormComponentActionsData.' . array_key_last($this->instance()->mountedFormComponentActionsData) . '.') as $key => $value) { + $this->set($key, $value); + } + + return $this; + }; + } + + public function assertFormComponentActionDataSet(): Closure + { + return function (array $data): static { + foreach (Arr::dot($data, prepend: 'mountedFormComponentActionsData.' . array_key_last($this->instance()->mountedFormComponentActionsData) . '.') as $key => $value) { + $this->assertSet($key, $value); + } + + return $this; + }; + } + + public function callFormComponentAction(): Closure + { + return function (string | array $component, string | array $name, array $data = [], array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionVisible($component, $name, $arguments, $formName); + + /** @phpstan-ignore-next-line */ + $this->mountFormComponentAction($component, $name, $arguments, $formName); + + if (! $this->instance()->getMountedFormComponentAction()) { + return $this; + } + + /** @phpstan-ignore-next-line */ + $this->setFormComponentActionData($data); + + /** @phpstan-ignore-next-line */ + $this->callMountedFormComponentAction($arguments); + + return $this; + }; + } + + public function callMountedFormComponentAction(): Closure + { + return function (array $arguments = []): static { + $action = $this->instance()->getMountedFormComponentAction(); + + if (! $action) { + return $this; + } + + $this->call('callMountedFormComponentAction', $arguments); + + if (store($this->instance())->has('redirect')) { + return $this; + } + + if (! count($this->instance()->mountedFormComponentActions)) { + $this->assertDispatched('close-modal', id: "{$this->instance()->getId()}-form-component-action"); + } + + return $this; + }; + } + + public function assertFormComponentActionExists(): Closure + { + return function (string | array $component, string | array $name, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertInstanceOf( + Action::class, + $action, + message: "Failed asserting that a form component action with name [{$prettyName}] is registered to [{$component->getKey()}] on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionDoesNotExist(): Closure + { + return function (string | array $component, string | array $name, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertNull( + $action, + message: "Failed asserting that a form component action with name [{$prettyName}] is not registered to [{$component->getKey()}] on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionVisible(): Closure + { + return function (string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertFalse( + $action->isHidden(), + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], is visible on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionHidden(): Closure + { + return function (string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertTrue( + $action->isHidden(), + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], is hidden on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionEnabled(): Closure + { + return function (string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertFalse( + $action->isDisabled(), + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], is enabled on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionDisabled(): Closure + { + return function (string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertFalse( + $action->isEnabled(), + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], is disabled on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionHasIcon(): Closure + { + return function (string | array $component, string | array $name, string $icon, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertTrue( + $action->getIcon() === $icon, + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], has icon [{$icon}] on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionDoesNotHaveIcon(): Closure + { + return function (string | array $component, string | array $name, string $icon, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertFalse( + $action->getIcon() === $icon, + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], does not have icon [{$icon}] on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionHasLabel(): Closure + { + return function (string | array $component, string | array $name, string $label, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertTrue( + $action->getLabel() === $label, + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], has label [{$label}] on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionDoesNotHaveLabel(): Closure + { + return function (string | array $component, string | array $name, string $label, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertFalse( + $action->getLabel() === $label, + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], does not have label [{$label}] on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionHasColor(): Closure + { + return function (string | array $component, string | array $name, string | array $color, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + $colorName = is_string($color) ? $color : 'custom'; + + Assert::assertTrue( + $action->getColor() === $color, + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], has [{$colorName}] color on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionDoesNotHaveColor(): Closure + { + return function (string | array $component, string | array $name, string | array $color, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + $colorName = is_string($color) ? $color : 'custom'; + + Assert::assertFalse( + $action->getColor() === $color, + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], does not have [{$colorName}] color on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionHasUrl(): Closure + { + return function (string | array $component, string | array $name, string $url, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertTrue( + $action->getUrl() === $url, + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], has URL [{$url}] on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionDoesNotHaveUrl(): Closure + { + return function (string | array $component, string | array $name, string $url, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertFalse( + $action->getUrl() === $url, + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], does not have URL [{$url}] on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionShouldOpenUrlInNewTab(): Closure + { + return function (string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertTrue( + $action->shouldOpenUrlInNewTab(), + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], should open url in new tab on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionShouldNotOpenUrlInNewTab(): Closure + { + return function (string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $action] = $this->getNestedFormComponentActionComponentAndName($component, $name, $formName, $arguments); + + $livewireClass = $this->instance()::class; + $prettyName = implode(' > ', Arr::wrap($name)); + + Assert::assertFalse( + $action->shouldOpenUrlInNewTab(), + message: "Failed asserting that a form component action with name [{$prettyName}], registered to [{$component->getKey()}], should not open url in new tab on the [{$livewireClass}] component.", + ); + + return $this; + }; + } + + public function assertFormComponentActionMounted(): Closure + { + return function (string | array $component, string | array $name, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $name] = $this->parseNestedFormComponentActionComponentAndName($component, $name, $formName); + + $this->assertSet('mountedFormComponentActions', $name); + + return $this; + }; + } + + public function assertFormComponentActionNotMounted(): Closure + { + return function (string | array $component, string | array $name, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormComponentActionExists($component, $name, $formName); + + /** @phpstan-ignore-next-line */ + [$component, $name] = $this->parseNestedFormComponentActionComponentAndName($component, $name, $formName); + + $this->assertNotSet('mountedFormComponentActions', $name); + + return $this; + }; + } + + public function assertFormComponentActionHalted(): Closure + { + return $this->assertFormComponentActionMounted(); + } + + public function assertHasFormComponentActionErrors(): Closure + { + return function (array $keys = []): static { + $this->assertHasErrors( + collect($keys) + ->mapWithKeys(function ($value, $key): array { + if (is_int($key)) { + return [$key => 'mountedFormComponentActionsData.' . array_key_last($this->instance()->mountedFormComponentActionsData) . '.' . $value]; + } + + return ['mountedFormComponentActionsData.' . array_key_last($this->instance()->mountedFormComponentActionsData) . '.' . $key => $value]; + }) + ->all(), + ); + + return $this; + }; + } + + public function assertHasNoFormComponentActionErrors(): Closure + { + return function (array $keys = []): static { + $this->assertHasNoErrors( + collect($keys) + ->mapWithKeys(function ($value, $key): array { + if (is_int($key)) { + return [$key => 'mountedFormComponentActionsData.' . array_key_last($this->instance()->mountedFormComponentActionsData) . '.' . $value]; + } + + return ['mountedFormComponentActionsData.' . array_key_last($this->instance()->mountedFormComponentActionsData) . '.' . $key => $value]; + }) + ->all(), + ); + + return $this; + }; + } + + public function getNestedFormComponentActionComponentAndName(): Closure + { + return function (string | array $component, string | array $name, string $formName = 'form', array $arguments = []): array { + $isSingular = ! is_array($component); + + /** @phpstan-ignore-next-line */ + [$component, $name] = $this->parseNestedFormComponentActionComponentAndName($component, $name, $formName); + + foreach ($component as $componentNestingIndex => $componentKey) { + foreach ($this->instance()->getCachedForms() as $form) { + $formComponent = $form->getComponent($componentKey); + + if (! $formComponent) { + continue; + } + + break; + } + + $action = ($formComponent ?? null)?->getAction($name[$componentNestingIndex]); + $action?->arguments($isSingular ? $arguments : $arguments[$componentNestingIndex] ?? []); + } + + return [$formComponent ?? null, $action ?? null]; + }; + } + + public function parseNestedFormComponentActionComponentAndName(): Closure + { + return function (string | array $component, string | array $name, string $formName = 'form'): array { + $this->assertFormExists($formName); + + $component = Arr::wrap($component); + + $livewire = $this->instance(); + + /** @var ComponentContainer $form */ + $form = $livewire->{$formName}; + + $components = []; + + foreach ($component as $componentIndex => $componentKey) { + if ($componentIndex) { + $components[] = 'mountedFormComponentActionData.' . ($componentIndex - 1) . ".{$componentKey}"; + + continue; + } + + $components[] = "{$form->getStatePath()}.{$componentKey}"; + } + + return [$components, $this->parseNestedActionName($name)]; + }; + } +} diff --git a/packages/tables/.stubs.php b/packages/tables/.stubs.php index f818baeccd..39962f0ea9 100644 --- a/packages/tables/.stubs.php +++ b/packages/tables/.stubs.php @@ -6,7 +6,7 @@ namespace Livewire\Features\SupportTesting { use Closure; class Testable { - public function mountTableAction(string $name, $record = null): static {} + public function mountTableAction(string | array $name, $record = null): static {} public function unmountTableAction(): static {} @@ -14,15 +14,15 @@ namespace Livewire\Features\SupportTesting { public function assertTableActionDataSet(array $data): static {} - public function callTableAction(string $name, $record = null, array $data = [], array $arguments = []): static {} + public function callTableAction(string | array $name, $record = null, array $data = [], array $arguments = []): static {} public function callTableColumnAction(string $name, $record = null): static {} public function callMountedTableAction(array $arguments = []): static {} - public function assertTableActionExists(string $name): static {} + public function assertTableActionExists(string | array $name): static {} - public function assertTableActionDoesNotExist(string $name): static {} + public function assertTableActionDoesNotExist(string | array $name): static {} public function assertTableActionsExistInOrder(array $names): static {} @@ -30,19 +30,19 @@ namespace Livewire\Features\SupportTesting { public function assertTableEmptyStateActionsExistInOrder(array $names): static {} - public function assertTableActionVisible(string $name, $record = null): static {} + public function assertTableActionVisible(string | array $name, $record = null): static {} - public function assertTableActionHidden(string $name, $record = null): static {} + public function assertTableActionHidden(string | array $name, $record = null): static {} - public function assertTableActionEnabled(string $name, $record = null): static {} + public function assertTableActionEnabled(string | array $name, $record = null): static {} - public function assertTableActionDisabled(string $name, $record = null): static {} + public function assertTableActionDisabled(string | array $name, $record = null): static {} - public function assertTableActionMounted(string $name): static {} + public function assertTableActionMounted(string | array $name): static {} - public function assertTableActionNotMounted(string $name): static {} + public function assertTableActionNotMounted(string | array $name): static {} - public function assertTableActionHalted(string $name): static {} + public function assertTableActionHalted(string | array $name): static {} public function assertHasTableActionErrors(array $keys = []): static {} @@ -72,17 +72,17 @@ namespace Livewire\Features\SupportTesting { public function assertTableBulkActionDisabled(string $name): static {} - public function assertTableActionHasIcon(string $name, string $icon): static {} + public function assertTableActionHasIcon(string | array $name, string $icon): static {} - public function assertTableActionDoesNotHaveIcon(string $name, string $icon): static {} + public function assertTableActionDoesNotHaveIcon(string | array $name, string $icon): static {} - public function assertTableActionHasLabel(string $name, string $label): static {} + public function assertTableActionHasLabel(string | array $name, string $label): static {} - public function assertTableActionDoesNotHaveLabel(string $name, string $label): static {} + public function assertTableActionDoesNotHaveLabel(string | array $name, string $label): static {} - public function assertTableActionHasColor(string $name, string | array $color): static {} + public function assertTableActionHasColor(string | array $name, string | array $color): static {} - public function assertTableActionDoesNotHaveColor(string $name, string | array $color): static {} + public function assertTableActionDoesNotHaveColor(string | array $name, string | array $color): static {} public function assertTableBulkActionHasIcon(string $name, string $icon): static {} @@ -96,13 +96,13 @@ namespace Livewire\Features\SupportTesting { public function assertTableBulkActionDoesNotHaveColor(string $name, string | array $color): static {} - public function assertTableActionHasUrl(string $name, string $url): static {} + public function assertTableActionHasUrl(string | array $name, string $url): static {} - public function assertTableActionDoesNotHaveUrl(string $name, string $url): static {} + public function assertTableActionDoesNotHaveUrl(string | array $name, string $url): static {} - public function assertTableActionShouldOpenUrlInNewTab(string $name): static {} + public function assertTableActionShouldOpenUrlInNewTab(string | array $name): static {} - public function assertTableActionShouldNotOpenUrlInNewTab(string $name): static {} + public function assertTableActionShouldNotOpenUrlInNewTab(string | array $name): static {} public function assertTableBulkActionMounted(string $name): static {} diff --git a/tests/resources/views/forms/fixtures/actions.blade.php b/tests/resources/views/forms/fixtures/actions.blade.php new file mode 100644 index 0000000000..823a5cf3f4 --- /dev/null +++ b/tests/resources/views/forms/fixtures/actions.blade.php @@ -0,0 +1 @@ +{{ $this->form }} diff --git a/tests/src/Actions/ActionTest.php b/tests/src/Actions/ActionTest.php index 7a643667b2..20ed05c249 100644 --- a/tests/src/Actions/ActionTest.php +++ b/tests/src/Actions/ActionTest.php @@ -105,20 +105,20 @@ it('can disable an action', function () { it('can have an icon', function () { livewire(Actions::class) - ->assertActionHasIcon('has-icon', 'heroicon-m-pencil-square') - ->assertActionDoesNotHaveIcon('has-icon', 'heroicon-m-trash'); + ->assertActionHasIcon('hasIcon', 'heroicon-m-pencil-square') + ->assertActionDoesNotHaveIcon('hasIcon', 'heroicon-m-trash'); }); it('can have a label', function () { livewire(Actions::class) - ->assertActionHasLabel('has-label', 'My Action') - ->assertActionDoesNotHaveLabel('has-label', 'My Other Action'); + ->assertActionHasLabel('hasLabel', 'My Action') + ->assertActionDoesNotHaveLabel('hasLabel', 'My Other Action'); }); it('can have a color', function () { livewire(Actions::class) - ->assertActionHasColor('has-color', 'primary') - ->assertActionDoesNotHaveColor('has-color', 'gray'); + ->assertActionHasColor('hasColor', 'primary') + ->assertActionDoesNotHaveColor('hasColor', 'gray'); }); it('can have a URL', function () { @@ -129,14 +129,14 @@ it('can have a URL', function () { it('can open a URL in a new tab', function () { livewire(Actions::class) - ->assertActionShouldOpenUrlInNewTab('url-in-new-tab') - ->assertActionShouldNotOpenUrlInNewTab('url-not-in-new-tab'); + ->assertActionShouldOpenUrlInNewTab('urlInNewTab') + ->assertActionShouldNotOpenUrlInNewTab('urlNotInNewTab'); }); it('can state whether a page action exists', function () { livewire(Actions::class) ->assertActionExists('exists') - ->assertActionDoesNotExist('does-not-exist'); + ->assertActionDoesNotExist('doesNotExist'); }); it('can show a notification', function () { diff --git a/tests/src/Actions/Fixtures/Pages/Actions.php b/tests/src/Actions/Fixtures/Pages/Actions.php index cad581a012..a8a8b3a24d 100644 --- a/tests/src/Actions/Fixtures/Pages/Actions.php +++ b/tests/src/Actions/Fixtures/Pages/Actions.php @@ -52,18 +52,18 @@ class Actions extends Page Action::make('enabled'), Action::make('disabled') ->disabled(), - Action::make('has-icon') + Action::make('hasIcon') ->icon('heroicon-m-pencil-square'), - Action::make('has-label') + Action::make('hasLabel') ->label('My Action'), - Action::make('has-color') + Action::make('hasColor') ->color('primary'), Action::make('exists'), Action::make('url') ->url('https://filamentphp.com'), - Action::make('url-in-new-tab') + Action::make('urlInNewTab') ->url('https://filamentphp.com', true), - Action::make('url-not-in-new-tab') + Action::make('urlNotInNewTab') ->url('https://filamentphp.com', false), Action::make('shows-notification') ->action(function () { diff --git a/tests/src/Forms/ActionTest.php b/tests/src/Forms/ActionTest.php index bbfc91bbad..230ba49880 100644 --- a/tests/src/Forms/ActionTest.php +++ b/tests/src/Forms/ActionTest.php @@ -2,9 +2,12 @@ use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\TextInput; +use Filament\Tests\Forms\Fixtures\Actions; use Filament\Tests\TestCase; use Illuminate\Support\Str; +use function Filament\Tests\livewire; + uses(TestCase::class); it('can register actions', function () { @@ -30,3 +33,90 @@ it('can auto-register actions from affixes', function () { ->getAction($prefixActionName)->toBe($prefixAction) ->getAction($suffixActionName)->toBe($suffixAction); }); + +it('can call an action with data', function () { + livewire(Actions::class) + ->callFormComponentAction('textInput', 'setValue', data: [ + 'value' => $value = Str::random(), + ]) + ->assertFormSet(['textInput' => $value]); +}); + +it('can validate an action\'s data', function () { + livewire(Actions::class) + ->callFormComponentAction('textInput', 'setValue', data: [ + 'value' => null, + ]) + ->assertHasFormComponentActionErrors(['value' => ['required']]) + ->assertFormSet(['textInput' => null]); +}); + +it('can set default action data when mounted', function () { + livewire(Actions::class) + ->mountFormComponentAction('textInput', 'setValue') + ->assertFormComponentActionDataSet([ + 'value' => 'foo', + ]); +}); + +it('can call an action with arguments', function () { + livewire(Actions::class) + ->callFormComponentAction('textInput', 'setValueFromArguments', arguments: [ + 'value' => $value = Str::random(), + ]) + ->assertFormSet(['textInput' => $value]); +}); + +it('can call an action and halt', function () { + livewire(Actions::class) + ->callFormComponentAction('textInput', 'halt') + ->assertFormComponentActionHalted('textInput', 'halt'); +}); + +it('can hide an action', function () { + livewire(Actions::class) + ->assertFormComponentActionVisible('textInput', 'visible') + ->assertFormComponentActionHidden('textInput', 'hidden'); +}); + +it('can disable an action', function () { + livewire(Actions::class) + ->assertFormComponentActionEnabled('textInput', 'enabled') + ->assertFormComponentActionDisabled('textInput', 'disabled'); +}); + +it('can have an icon', function () { + livewire(Actions::class) + ->assertFormComponentActionHasIcon('textInput', 'hasIcon', 'heroicon-m-pencil-square') + ->assertFormComponentActionDoesNotHaveIcon('textInput', 'hasIcon', 'heroicon-m-trash'); +}); + +it('can have a label', function () { + livewire(Actions::class) + ->assertFormComponentActionHasLabel('textInput', 'hasLabel', 'My Action') + ->assertFormComponentActionDoesNotHaveLabel('textInput', 'hasLabel', 'My Other Action'); +}); + +it('can have a color', function () { + livewire(Actions::class) + ->assertFormComponentActionHasColor('textInput', 'hasColor', 'primary') + ->assertFormComponentActionDoesNotHaveColor('textInput', 'hasColor', 'gray'); +}); + +it('can have a URL', function () { + livewire(Actions::class) + ->assertFormComponentActionHasUrl('textInput', 'url', 'https://filamentphp.com') + ->assertFormComponentActionDoesNotHaveUrl('textInput', 'url', 'https://google.com'); +}); + +it('can open a URL in a new tab', function () { + livewire(Actions::class) + ->assertFormComponentActionShouldOpenUrlInNewTab('textInput', 'urlInNewTab') + ->assertFormComponentActionShouldNotOpenUrlInNewTab('textInput', 'urlNotInNewTab'); +}); + +it('can state whether a form component action exists', function () { + livewire(Actions::class) + ->assertFormComponentActionExists('textInput', 'exists') + ->assertFormComponentActionDoesNotExist('textInput', 'doesNotExist'); +}); diff --git a/tests/src/Forms/Fixtures/Actions.php b/tests/src/Forms/Fixtures/Actions.php new file mode 100644 index 0000000000..81fc8bb547 --- /dev/null +++ b/tests/src/Forms/Fixtures/Actions.php @@ -0,0 +1,93 @@ +form->fill(); + } + + public function form(Form $form): Form + { + return $form + ->schema([ + TextInput::make('textInput') + ->registerActions([ + Action::make('setValue') + ->form([ + TextInput::make('value') + ->default('foo') + ->required(), + ]) + ->action(function (TextInput $component, array $data) { + $component->state($data['value']); + }), + Action::make('setValueFromArguments') + ->action(function (TextInput $component, array $arguments) { + $component->state($arguments['value']); + }), + Action::make('halt') + ->requiresConfirmation() + ->action(function (Action $action) { + $action->halt(); + }), + Action::make('hidden') + ->hidden(), + Action::make('visible'), + Action::make('disabled') + ->disabled(), + Action::make('enabled'), + Action::make('hasIcon') + ->icon('heroicon-m-pencil-square'), + Action::make('hasLabel') + ->label('My Action'), + Action::make('hasColor') + ->color('primary'), + Action::make('url') + ->url('https://filamentphp.com'), + Action::make('urlInNewTab') + ->url('https://filamentphp.com', true), + Action::make('urlNotInNewTab') + ->url('https://filamentphp.com'), + Action::make('exists'), + ]), + ]) + ->statePath('data'); + } + + public function data($data): static + { + $this->data = $data; + + return $this; + } + + public function getData() + { + return $this->data; + } + + public function render(): View + { + return view('forms.fixtures.actions'); + } +} diff --git a/tests/src/Tables/ActionTest.php b/tests/src/Tables/ActionTest.php index 59659c9785..5e4b859640 100644 --- a/tests/src/Tables/ActionTest.php +++ b/tests/src/Tables/ActionTest.php @@ -79,20 +79,20 @@ it('can disable an action', function () { it('can have an icon', function () { livewire(PostsTable::class) - ->assertTableActionHasIcon('has-icon', 'heroicon-m-pencil-square') - ->assertTableActionDoesNotHaveIcon('has-icon', 'heroicon-m-trash'); + ->assertTableActionHasIcon('hasIcon', 'heroicon-m-pencil-square') + ->assertTableActionDoesNotHaveIcon('hasIcon', 'heroicon-m-trash'); }); it('can have a label', function () { livewire(PostsTable::class) - ->assertTableActionHasLabel('has-label', 'My Action') - ->assertTableActionDoesNotHaveLabel('has-label', 'My Other Action'); + ->assertTableActionHasLabel('hasLabel', 'My Action') + ->assertTableActionDoesNotHaveLabel('hasLabel', 'My Other Action'); }); it('can have a color', function () { livewire(PostsTable::class) - ->assertTableActionHasColor('has-color', 'primary') - ->assertTableActionDoesNotHaveColor('has-color', 'gray'); + ->assertTableActionHasColor('hasColor', 'primary') + ->assertTableActionDoesNotHaveColor('hasColor', 'gray'); }); it('can have a URL', function () { @@ -103,19 +103,19 @@ it('can have a URL', function () { it('can open a URL in a new tab', function () { livewire(PostsTable::class) - ->assertTableActionShouldOpenUrlInNewTab('url-in-new-tab') - ->assertTableActionShouldNotOpenUrlInNewTab('url-not-in-new-tab'); + ->assertTableActionShouldOpenUrlInNewTab('urlInNewTab') + ->assertTableActionShouldNotOpenUrlInNewTab('urlNotInNewTab'); }); it('can state whether a table action exists', function () { livewire(PostsTable::class) ->assertTableActionExists('exists') - ->assertTableActionDoesNotExist('does-not-exist'); + ->assertTableActionDoesNotExist('doesNotExist'); }); it('can state whether table actions exist in order', function () { livewire(PostsTable::class) ->assertTableActionsExistInOrder(['edit', 'delete']) - ->assertTableHeaderActionsExistInOrder(['exists', 'exists-in-order']) - ->assertTableEmptyStateActionsExistInOrder(['empty-exists', 'empty-exists-in-order']); + ->assertTableHeaderActionsExistInOrder(['exists', 'existsInOrder']) + ->assertTableEmptyStateActionsExistInOrder(['emptyExists', 'emptyExistsInOrder']); }); diff --git a/tests/src/Tables/BulkActionTest.php b/tests/src/Tables/BulkActionTest.php index 42f60078fe..155407ea8a 100644 --- a/tests/src/Tables/BulkActionTest.php +++ b/tests/src/Tables/BulkActionTest.php @@ -91,20 +91,20 @@ it('can disable a bulk action', function () { it('can have an icon', function () { livewire(PostsTable::class) - ->assertTableBulkActionHasIcon('has-icon', 'heroicon-m-pencil-square') - ->assertTableBulkActionDoesNotHaveIcon('has-icon', 'heroicon-m-trash'); + ->assertTableBulkActionHasIcon('hasIcon', 'heroicon-m-pencil-square') + ->assertTableBulkActionDoesNotHaveIcon('hasIcon', 'heroicon-m-trash'); }); it('can have a label', function () { livewire(PostsTable::class) - ->assertTableBulkActionHasLabel('has-label', 'My Action') - ->assertTableBulkActionDoesNotHaveLabel('has-label', 'My Other Action'); + ->assertTableBulkActionHasLabel('hasLabel', 'My Action') + ->assertTableBulkActionDoesNotHaveLabel('hasLabel', 'My Other Action'); }); it('can have a color', function () { livewire(PostsTable::class) - ->assertTableBulkActionHasColor('has-color', 'primary') - ->assertTableBulkActionDoesNotHaveColor('has-color', 'gray'); + ->assertTableBulkActionHasColor('hasColor', 'primary') + ->assertTableBulkActionDoesNotHaveColor('hasColor', 'gray'); }); it('can state whether a bulk action exists', function () { @@ -115,5 +115,5 @@ it('can state whether a bulk action exists', function () { it('can state whether bulk actions exist in order', function () { livewire(PostsTable::class) - ->assertTableBulkActionsExistInOrder(['exists', 'exists-in-order']); + ->assertTableBulkActionsExistInOrder(['exists', 'existsInOrder']); }); diff --git a/tests/src/Tables/Fixtures/PostsTable.php b/tests/src/Tables/Fixtures/PostsTable.php index 5a081f0f9e..8ae687d533 100644 --- a/tests/src/Tables/Fixtures/PostsTable.php +++ b/tests/src/Tables/Fixtures/PostsTable.php @@ -129,19 +129,19 @@ class PostsTable extends Component implements HasForms, Tables\Contracts\HasTabl Tables\Actions\Action::make('enabled'), Tables\Actions\Action::make('disabled') ->disabled(), - Tables\Actions\Action::make('has-icon') + Tables\Actions\Action::make('hasIcon') ->icon('heroicon-m-pencil-square'), - Tables\Actions\Action::make('has-label') + Tables\Actions\Action::make('hasLabel') ->label('My Action'), - Tables\Actions\Action::make('has-color') + Tables\Actions\Action::make('hasColor') ->color('primary'), Tables\Actions\Action::make('exists'), - Tables\Actions\Action::make('exists-in-order'), + Tables\Actions\Action::make('existsInOrder'), Tables\Actions\Action::make('url') ->url('https://filamentphp.com'), - Tables\Actions\Action::make('url-in-new-tab') + Tables\Actions\Action::make('urlInNewTab') ->url('https://filamentphp.com', true), - Tables\Actions\Action::make('url-not-in-new-tab') + Tables\Actions\Action::make('urlNotInNewTab') ->url('https://filamentphp.com'), ]) ->actions([ @@ -178,18 +178,18 @@ class PostsTable extends Component implements HasForms, Tables\Contracts\HasTabl Tables\Actions\BulkAction::make('enabled'), Tables\Actions\BulkAction::make('disabled') ->disabled(), - Tables\Actions\BulkAction::make('has-icon') + Tables\Actions\BulkAction::make('hasIcon') ->icon('heroicon-m-pencil-square'), - Tables\Actions\BulkAction::make('has-label') + Tables\Actions\BulkAction::make('hasLabel') ->label('My Action'), - Tables\Actions\BulkAction::make('has-color') + Tables\Actions\BulkAction::make('hasColor') ->color('primary'), Tables\Actions\BulkAction::make('exists'), - Tables\Actions\BulkAction::make('exists-in-order'), + Tables\Actions\BulkAction::make('existsInOrder'), ]) ->emptyStateActions([ - Tables\Actions\Action::make('empty-exists'), - Tables\Actions\Action::make('empty-exists-in-order'), + Tables\Actions\Action::make('emptyExists'), + Tables\Actions\Action::make('emptyExistsInOrder'), ]); }