mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
feature: Form component action testing
This commit is contained in:
+22
-22
@@ -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 {}
|
||||
}
|
||||
|
||||
@@ -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 {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
```
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,595 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Forms\Testing;
|
||||
|
||||
use Closure;
|
||||
use Filament\Forms\ComponentContainer;
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Contracts\HasForms;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Testing\Assert;
|
||||
use Livewire\Features\SupportTesting\Testable;
|
||||
|
||||
use function Livewire\store;
|
||||
|
||||
/**
|
||||
* @method HasForms instance()
|
||||
*
|
||||
* @mixin Testable
|
||||
*/
|
||||
class TestsComponentActions
|
||||
{
|
||||
public function mountFormComponentAction(): Closure
|
||||
{
|
||||
return function (string | array $component, string | array $name, array $arguments = [], string $formName = 'form'): static {
|
||||
/** @phpstan-ignore-next-line */
|
||||
[$component, $name] = $this->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)];
|
||||
};
|
||||
}
|
||||
}
|
||||
+21
-21
@@ -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 {}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{{ $this->form }}
|
||||
@@ -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 () {
|
||||
|
||||
@@ -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 () {
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Tests\Forms\Fixtures;
|
||||
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Concerns\InteractsWithForms;
|
||||
use Filament\Forms\Contracts\HasForms;
|
||||
use Filament\Forms\Form;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class Actions extends Component implements HasForms
|
||||
{
|
||||
use InteractsWithForms;
|
||||
|
||||
public $data;
|
||||
|
||||
public static function make(): static
|
||||
{
|
||||
return new static();
|
||||
}
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->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');
|
||||
}
|
||||
}
|
||||
@@ -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']);
|
||||
});
|
||||
|
||||
@@ -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']);
|
||||
});
|
||||
|
||||
@@ -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'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user