This commit is contained in:
Dan Harrin
2022-08-08 22:23:40 +01:00
parent 7531e4cff5
commit 1dbf5476c8
17 changed files with 727 additions and 411 deletions
+8
View File
@@ -11,8 +11,16 @@ namespace Livewire\Testing {
public function assertHasNoFormErrors(array $keys = []): static {}
public function mountPageAction(string $name): static {}
public function setPageActionData(array $data): static {}
public function assertPageActionDataSet(array $data): static {}
public function callPageAction(string $name, array $data = [], array $arguments = []): static {}
public function callMountedPageAction(array $arguments = []): static {}
public function assertPageActionExists(string $name): static {}
public function assertPageActionVisible(string $name): static {}
+26 -1
View File
@@ -138,6 +138,31 @@ Action::make('updateAuthor')
])
```
#### Filling default data
You may fill the form with default data, using the `mountUsing()` method:
```php
use App\Models\User;
use Filament\Forms;
use Filament\Pages\Actions\Action;
Action::make('updateAuthor')
->mountUsing(fn (Forms\ComponentContainer $form) => $form->fill([
'authorId' => $this->record->author->id,
]))
->action(function (array $data): void {
$this->record->author()->associate($data['authorId']);
$this->record->save();
})
->form([
Forms\Components\Select::make('authorId')
->label('Author')
->options(User::query()->pluck('name', 'id'))
->required(),
])
```
### Setting a modal heading, subheading, and button label
You may customize the heading, subheading and button label of the modal:
@@ -153,7 +178,7 @@ Action::make('delete')
->modalButton('Yes, delete them')
```
## Custom content
### Custom content
You may define custom content to be rendered inside your modal, which you can specify by passing a Blade view into the `modalContent()` method:
+25
View File
@@ -379,6 +379,31 @@ it('can validate invoice recipient email', function () {
});
```
To check if a page action is pre-filled with data, you can use the `assertPageActionDataSet()` 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,
])
->mountPageAction('send')
->assertPageActionDataSet([
'email' => $recipientEmail,
])
->callMountedPageAction()
->assertHasNoPageActionErrors();
expect($invoice->refresh())
->isSent()->toBeTrue()
->recipient_email->toBe($recipientEmail);
});
```
To check if a page action is hidden to a user, you can use the `assertPageActionHidden()` method:
```php
@@ -18,6 +18,7 @@ use Filament\Resources\Resource;
use Filament\Tables\Actions\Action as TableAction;
use Filament\Tables\Actions\ButtonAction;
use Filament\Tables\Actions\IconButtonAction;
use Filament\Testing\TestsPageActions;
use Filament\Testing\TestsPages;
use Filament\Widgets\Widget;
use Illuminate\Filesystem\Filesystem;
@@ -101,6 +102,7 @@ class FilamentServiceProvider extends PluginServiceProvider
$this->bootTableActionConfiguration();
TestableLivewire::mixin(new TestsPageActions());
TestableLivewire::mixin(new TestsPages());
}
@@ -0,0 +1,216 @@
<?php
namespace Filament\Testing;
use Closure;
use Filament\Pages\Actions\Action;
use Filament\Pages\Page;
use Filament\Support\Testing\TestsActions;
use Illuminate\Testing\Assert;
use Livewire\Testing\TestableLivewire;
/**
* @method Page instance()
*
* @mixin TestableLivewire
* @mixin TestsActions
*/
class TestsPageActions
{
public function mountPageAction(): Closure
{
return function (string $name): static {
$name = $this->parseActionName($name);
/** @phpstan-ignore-next-line */
$this->assertPageActionVisible($name);
$this->call('mountAction', $name);
$action = $this->instance()->getCachedAction($name);
if (! $action->shouldOpenModal()) {
$this->assertNotDispatchedBrowserEvent('open-modal');
$this->assertNotSet('mountedAction', $action->getName());
return $this;
}
$this->assertSet('mountedAction', $name);
$this->assertDispatchedBrowserEvent('open-modal', [
'id' => 'page-action',
]);
return $this;
};
}
public function setPageActionData(): Closure
{
return function (array $data): static {
$this->set('mountedActionData', $data);
return $this;
};
}
public function assertPageActionDataSet(): Closure
{
return function (array $data): static {
foreach ($data as $key => $value) {
$this->assertSet("mountedActionData.{$key}", $value);
}
return $this;
};
}
public function callPageAction(): Closure
{
return function (string $name, array $data = [], array $arguments = []): static {
/** @phpstan-ignore-next-line */
$this->mountPageAction($name);
/** @phpstan-ignore-next-line */
$this->setPageActionData($data);
/** @phpstan-ignore-next-line */
$this->callMountedPageAction($arguments);
return $this;
};
}
public function callMountedPageAction(): Closure
{
return function (array $arguments = []): static {
$action = $this->instance()->getMountedAction();
if (! $action) {
return $this;
}
$this->call('callMountedAction', json_encode($arguments));
if ($this->get('mountedAction') !== $action->getName()) {
$this->assertDispatchedBrowserEvent('close-modal', [
'id' => 'page-action',
]);
}
return $this;
};
}
public function assertPageActionExists(): Closure
{
return function (string $name): static {
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedAction($name);
Assert::assertInstanceOf(
Action::class,
$action,
message: "Failed asserting that an action with name [{$name}] exists on the [{$livewireClass}] page.",
);
return $this;
};
}
public function assertPageActionVisible(): Closure
{
return function (string $name): static {
/** @phpstan-ignore-next-line */
$this->assertPageActionExists($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedAction($name);
Assert::assertFalse(
$action->isHidden(),
message: "Failed asserting that an action with name [{$name}] is visible on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertPageActionHidden(): Closure
{
return function (string $name): static {
/** @phpstan-ignore-next-line */
$this->assertPageActionExists($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedAction($name);
Assert::assertTrue(
$action->isHidden(),
message: "Failed asserting that an action with name [{$name}] is hidden on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertPageActionHeld(): Closure
{
return function (string $name): static {
$name = $this->parseActionName($name);
/** @phpstan-ignore-next-line */
$this->assertPageActionExists($name);
$this->assertSet('mountedAction', $name);
return $this;
};
}
public function assertHasPageActionErrors(): Closure
{
return function (array $keys = []): static {
$this->assertHasErrors(
collect($keys)
->mapWithKeys(function ($value, $key): array {
if (is_int($key)) {
return [$key => "mountedActionData.{$value}"];
}
return ["mountedActionData.{$key}" => $value];
})
->all(),
);
return $this;
};
}
public function assertHasNoPageActionErrors(): Closure
{
return function (array $keys = []): static {
$this->assertHasNoErrors(
collect($keys)
->mapWithKeys(function ($value, $key): array {
if (is_int($key)) {
return [$key => "mountedActionData.{$value}"];
}
return ["mountedActionData.{$key}" => $value];
})
->all(),
);
return $this;
};
}
}
-150
View File
@@ -74,154 +74,4 @@ class TestsPages
return $this;
};
}
public function callPageAction(): Closure
{
return function (string $name, array $data = [], array $arguments = []): static {
$name = $this->parseActionName($name);
/** @phpstan-ignore-next-line */
$this->assertPageActionVisible($name);
$this->call('mountAction', $name);
$action = $this->instance()->getCachedAction($name);
if (! $action->shouldOpenModal()) {
$this->assertNotDispatchedBrowserEvent('open-modal');
$this->assertNotSet('mountedAction', $name);
return $this;
}
$this->assertSet('mountedAction', $name);
$this->assertDispatchedBrowserEvent('open-modal', [
'id' => 'page-action',
]);
$this->set('mountedActionData', $data);
$this->call('callMountedAction', json_encode($arguments));
if ($this->get('mountedAction') !== $name) {
$this->assertDispatchedBrowserEvent('close-modal', [
'id' => 'page-action',
]);
}
return $this;
};
}
public function assertPageActionExists(): Closure
{
return function (string $name): static {
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedAction($name);
Assert::assertInstanceOf(
Action::class,
$action,
message: "Failed asserting that an action with name [{$name}] exists on the [{$livewireClass}] page.",
);
return $this;
};
}
public function assertPageActionVisible(): Closure
{
return function (string $name): static {
/** @phpstan-ignore-next-line */
$this->assertPageActionExists($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedAction($name);
Assert::assertFalse(
$action->isHidden(),
message: "Failed asserting that an action with name [{$name}] is visible on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertPageActionHidden(): Closure
{
return function (string $name): static {
/** @phpstan-ignore-next-line */
$this->assertPageActionExists($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedAction($name);
Assert::assertTrue(
$action->isHidden(),
message: "Failed asserting that an action with name [{$name}] is hidden on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertPageActionHeld(): Closure
{
return function (string $name): static {
$name = $this->parseActionName($name);
/** @phpstan-ignore-next-line */
$this->assertPageActionExists($name);
$this->assertSet('mountedAction', $name);
return $this;
};
}
public function assertHasPageActionErrors(): Closure
{
return function (array $keys = []): static {
$this->assertHasErrors(
collect($keys)
->mapWithKeys(function ($value, $key): array {
if (is_int($key)) {
return [$key => "mountedActionData.{$value}"];
}
return ["mountedActionData.{$key}" => $value];
})
->all(),
);
return $this;
};
}
public function assertHasNoPageActionErrors(): Closure
{
return function (array $keys = []): static {
$this->assertHasNoErrors(
collect($keys)
->mapWithKeys(function ($value, $key): array {
if (is_int($key)) {
return [$key => "mountedActionData.{$value}"];
}
return ["mountedActionData.{$key}" => $value];
})
->all(),
);
return $this;
};
}
}
+16
View File
@@ -5,8 +5,16 @@ namespace Livewire\Testing {
use Illuminate\Support\Collection;
class TestableLivewire {
public function mountTableAction(string $name, $record = null): static {}
public function setTableActionData(array $data): static {}
public function assertTableActionDataSet(array $data): static {}
public function callTableAction(string $name, $record = null, array $data = [], array $arguments = []): static {}
public function callMountedTableAction(array $arguments = []): static {}
public function assertTableActionExists(string $name): static {}
public function assertTableActionVisible(string $name, $record = null): static {}
@@ -19,8 +27,16 @@ namespace Livewire\Testing {
public function assertHasNoTableActionErrors(array $keys = []): static {}
public function mountTableBulkAction(string $name, array | Collection $records): static {}
public function setTableBulkActionData(array $data): static {}
public function assertTableBulkActionDataSet(array $data): static {}
public function callTableBulkAction(string $name, array | Collection $records, array $data = [], array $arguments = []): static {}
public function callMountedTableBulkAction(array $arguments = []): static {}
public function assertTableBulkActionExists(string $name): static {}
public function assertTableBulkActionVisible(string $name): static {}
+27 -1
View File
@@ -188,6 +188,32 @@ BulkAction::make('updateAuthor')
])
```
#### Filling default data
You may fill the form with default data, using the `mountUsing()` method:
```php
use App\Models\User;
use Filament\Forms;
use Filament\Tables\Actions\Action;
use Illuminate\Database\Eloquent\Collection;
Action::make('updateAuthor')
->mountUsing(fn (Forms\ComponentContainer $form, User $record) => $form->fill([
'authorId' => $record->author->id,
]))
->action(function (User $record, array $data): void {
$record->author()->associate($data['authorId']);
$record->save();
})
->form([
Forms\Components\Select::make('authorId')
->label('Author')
->options(User::query()->pluck('name', 'id'))
->required(),
])
```
#### Wizards
You may easily transform action forms into multistep wizards.
@@ -248,7 +274,7 @@ BulkAction::make('delete')
->modalButton('Yes, delete them')
```
## Custom content
### Custom content
You may define custom content to be rendered inside your modal, which you can specify by passing a Blade view into the `modalContent()` method:
+24
View File
@@ -232,6 +232,30 @@ it('can validate edited post data', function () {
For bulk actions, this method is called `assertHasTableBulkActionErrors()`.
To check if an action or bulk action is pre-filled with data, you can use the `assertTableActionDataSet()` or `assertTableBulkActionDataSet()` method:
```php
use function Pest\Livewire\livewire;
it('can load existing post data for editing', function () {
$post = Post::factory()->create();
livewire(PostResource\Pages\ListPosts::class)
->mountTableAction(EditAction::class, $post)
->assertTableActionDataSet([[
'title' => $post->title,
])
->setTableActionData([[
'title' => $title = fake()->words(asText: true),
])
->callMountedTableAction()
->assertHasNoTableActionErrors();
expect($post->refresh())
->title->toBe($title);
});
```
To ensure that an action or bulk action is hidden for a user, you can use the `assertTableActionHidden()` or `assertTableBulkActionHidden()` method:
```php
@@ -3,6 +3,7 @@
namespace Filament\Tables;
use Filament\Tables\Testing\TestsActions;
use Filament\Tables\Testing\TestsBulkActions;
use Filament\Tables\Testing\TestsColumns;
use Filament\Tables\Testing\TestsFilters;
use Filament\Tables\Testing\TestsRecords;
@@ -47,6 +48,7 @@ class TablesServiceProvider extends PackageServiceProvider
public function packageBooted(): void
{
TestableLivewire::mixin(new TestsActions());
TestableLivewire::mixin(new TestsBulkActions());
TestableLivewire::mixin(new TestsColumns());
TestableLivewire::mixin(new TestsFilters());
TestableLivewire::mixin(new TestsRecords());
+9 -225
View File
@@ -5,10 +5,8 @@ namespace Filament\Tables\Testing;
use Closure;
use Filament\Support\Testing\TestsActions as BaseTestsActions;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\BulkAction;
use Filament\Tables\Contracts\HasTable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Testing\Assert;
use Livewire\Testing\TestableLivewire;
@@ -42,6 +40,8 @@ class TestsActions
if (! $action->shouldOpenModal()) {
$this->assertNotDispatchedBrowserEvent('open-modal');
$this->assertNotSet('mountedTableAction', $action->getName());
return $this;
}
@@ -64,7 +64,7 @@ class TestsActions
};
}
public function assertTableActionData(): Closure
public function assertTableActionDataSet(): Closure
{
return function (array $data): static {
foreach ($data as $key => $value) {
@@ -82,7 +82,10 @@ class TestsActions
$this->mountTableAction($name, $record);
/** @phpstan-ignore-next-line */
$this->callMountedTableAction($data, $arguments);
$this->setTableActionData($data);
/** @phpstan-ignore-next-line */
$this->callMountedTableAction($arguments);
return $this;
};
@@ -90,21 +93,16 @@ class TestsActions
public function callMountedTableAction(): Closure
{
return function (array $data = [], array $arguments = []): static {
return function (array $arguments = []): static {
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getMountedTableAction();
if (! $action->shouldOpenModal()) {
$this->assertNotSet('mountedTableAction', $action->getName());
if (! $action) {
return $this;
}
/** @phpstan-ignore-next-line */
$this->setTableActionData($data);
$this->call('callMountedTableAction', json_encode($arguments));
if ($this->get('mountedTableAction') !== $action->getName()) {
@@ -240,218 +238,4 @@ class TestsActions
return $this;
};
}
public function mountTableBulkAction(): Closure
{
return function (string $name, array | Collection $records): static {
$name = $this->parseActionName($name);
/** @phpstan-ignore-next-line */
$this->assertTableBulkActionVisible($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$records = array_map(
function ($record) use ($livewire) {
if ($record instanceof Model) {
return $livewire->getTableRecordKey($record);
}
return $record;
},
$records instanceof Collection ? $records->all() : $records,
);
$this->call('mountTableBulkAction', $name, $records);
$action = $livewire->getCachedTableBulkAction($name);
if (! $action->shouldOpenModal()) {
$this->assertNotDispatchedBrowserEvent('open-modal');
return $this;
}
$this->assertSet('mountedTableBulkAction', $name);
$this->assertDispatchedBrowserEvent('open-modal', [
'id' => "{$livewireClass}-table-bulk-action",
]);
return $this;
};
}
public function setTableBulkActionData(): Closure
{
return function (array $data): static {
$this->set('mountedTableBulkActionData', $data);
return $this;
};
}
public function assertTableBulkActionData(): Closure
{
return function (array $data): static {
foreach ($data as $key => $value) {
$this->assertSet("mountedTableBulkActionData.{$key}", $value);
}
return $this;
};
}
public function callTableBulkAction(): Closure
{
return function (string $name, array | Collection $records, array $data = [], array $arguments = []): static {
/** @phpstan-ignore-next-line */
$this->mountTableBulkAction($name, $records);
/** @phpstan-ignore-next-line */
$this->callMountedTableBulkAction($data);
return $this;
};
}
public function callMountedTableBulkAction(): Closure
{
return function (array $data = [], array $arguments = []): static {
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getMountedTableBulkAction();
if (! $action->shouldOpenModal()) {
$this->assertNotSet('mountedTableBulkAction', $action->getName());
return $this;
}
/** @phpstan-ignore-next-line */
$this->setTableBulkActionData($data);
$this->call('callMountedTableBulkAction', json_encode($arguments));
if ($this->get('mountedTableBulkAction') !== $action->getName()) {
$this->assertDispatchedBrowserEvent('close-modal', [
'id' => "{$livewireClass}-table-bulk-action",
]);
}
return $this;
};
}
public function assertTableBulkActionExists(): Closure
{
return function (string $name): static {
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedTableBulkAction($name);
Assert::assertInstanceOf(
BulkAction::class,
$action,
message: "Failed asserting that a table bulk action with name [{$name}] exists on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertTableBulkActionVisible(): Closure
{
return function (string $name): static {
/** @phpstan-ignore-next-line */
$this->assertTableBulkActionExists($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedTableBulkAction($name);
Assert::assertFalse(
$action->isHidden(),
message: "Failed asserting that a table bulk action with name [{$name}] is visible on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertTableBulkActionHidden(): Closure
{
return function (string $name): static {
/** @phpstan-ignore-next-line */
$this->assertTableBulkActionExists($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedTableBulkAction($name);
Assert::assertTrue(
$action->isHidden(),
message: "Failed asserting that a table bulk action with name [{$name}] is hidden on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertTableBulkActionHeld(): Closure
{
return function (string $name): static {
$name = $this->parseActionName($name);
/** @phpstan-ignore-next-line */
$this->assertTableBulkActionExists($name);
$this->assertSet('mountedTableBulkAction', $name);
return $this;
};
}
public function assertHasTableBulkActionErrors(): Closure
{
return function (array $keys = []): static {
$this->assertHasErrors(
collect($keys)
->mapWithKeys(function ($value, $key): array {
if (is_int($key)) {
return [$key => "mountedTableBulkActionData.{$value}"];
}
return ["mountedTableBulkActionData.{$key}" => $value];
})
->all(),
);
return $this;
};
}
public function assertHasNoTableBulkActionErrors(): Closure
{
return function (array $keys = []): static {
$this->assertHasNoErrors(
collect($keys)
->mapWithKeys(function ($value, $key): array {
if (is_int($key)) {
return [$key => "mountedTableBulkActionData.{$value}"];
}
return ["mountedTableBulkActionData.{$key}" => $value];
})
->all(),
);
return $this;
};
}
}
@@ -0,0 +1,236 @@
<?php
namespace Filament\Tables\Testing;
use Closure;
use Filament\Support\Testing\TestsActions as BaseTestsActions;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\BulkAction;
use Filament\Tables\Contracts\HasTable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Testing\Assert;
use Livewire\Testing\TestableLivewire;
/**
* @method HasTable instance()
*
* @mixin TestableLivewire
* @mixin BaseTestsActions
*/
class TestsBulkActions
{
public function mountTableBulkAction(): Closure
{
return function (string $name, array | Collection $records): static {
$name = $this->parseActionName($name);
/** @phpstan-ignore-next-line */
$this->assertTableBulkActionVisible($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$records = array_map(
function ($record) use ($livewire) {
if ($record instanceof Model) {
return $livewire->getTableRecordKey($record);
}
return $record;
},
$records instanceof Collection ? $records->all() : $records,
);
$this->call('mountTableBulkAction', $name, $records);
$action = $livewire->getCachedTableBulkAction($name);
if (! $action->shouldOpenModal()) {
$this->assertNotDispatchedBrowserEvent('open-modal');
$this->assertNotSet('mountedTableBulkAction', $action->getName());
return $this;
}
$this->assertSet('mountedTableBulkAction', $name);
$this->assertDispatchedBrowserEvent('open-modal', [
'id' => "{$livewireClass}-table-bulk-action",
]);
return $this;
};
}
public function setTableBulkActionData(): Closure
{
return function (array $data): static {
$this->set('mountedTableBulkActionData', $data);
return $this;
};
}
public function assertTableBulkActionDataSet(): Closure
{
return function (array $data): static {
foreach ($data as $key => $value) {
$this->assertSet("mountedTableBulkActionData.{$key}", $value);
}
return $this;
};
}
public function callTableBulkAction(): Closure
{
return function (string $name, array | Collection $records, array $data = [], array $arguments = []): static {
/** @phpstan-ignore-next-line */
$this->mountTableBulkAction($name, $records);
/** @phpstan-ignore-next-line */
$this->setTableBulkActionData($data);
/** @phpstan-ignore-next-line */
$this->callMountedTableBulkAction($arguments);
return $this;
};
}
public function callMountedTableBulkAction(): Closure
{
return function (array $arguments = []): static {
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getMountedTableBulkAction();
if (! $action) {
return $this;
}
$this->call('callMountedTableBulkAction', json_encode($arguments));
if ($this->get('mountedTableBulkAction') !== $action->getName()) {
$this->assertDispatchedBrowserEvent('close-modal', [
'id' => "{$livewireClass}-table-bulk-action",
]);
}
return $this;
};
}
public function assertTableBulkActionExists(): Closure
{
return function (string $name): static {
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedTableBulkAction($name);
Assert::assertInstanceOf(
BulkAction::class,
$action,
message: "Failed asserting that a table bulk action with name [{$name}] exists on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertTableBulkActionVisible(): Closure
{
return function (string $name): static {
/** @phpstan-ignore-next-line */
$this->assertTableBulkActionExists($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedTableBulkAction($name);
Assert::assertFalse(
$action->isHidden(),
message: "Failed asserting that a table bulk action with name [{$name}] is visible on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertTableBulkActionHidden(): Closure
{
return function (string $name): static {
/** @phpstan-ignore-next-line */
$this->assertTableBulkActionExists($name);
$livewire = $this->instance();
$livewireClass = $livewire::class;
$action = $livewire->getCachedTableBulkAction($name);
Assert::assertTrue(
$action->isHidden(),
message: "Failed asserting that a table bulk action with name [{$name}] is hidden on the [{$livewireClass}] component.",
);
return $this;
};
}
public function assertTableBulkActionHeld(): Closure
{
return function (string $name): static {
$name = $this->parseActionName($name);
/** @phpstan-ignore-next-line */
$this->assertTableBulkActionExists($name);
$this->assertSet('mountedTableBulkAction', $name);
return $this;
};
}
public function assertHasTableBulkActionErrors(): Closure
{
return function (array $keys = []): static {
$this->assertHasErrors(
collect($keys)
->mapWithKeys(function ($value, $key): array {
if (is_int($key)) {
return [$key => "mountedTableBulkActionData.{$value}"];
}
return ["mountedTableBulkActionData.{$key}" => $value];
})
->all(),
);
return $this;
};
}
public function assertHasNoTableBulkActionErrors(): Closure
{
return function (array $keys = []): static {
$this->assertHasNoErrors(
collect($keys)
->mapWithKeys(function ($value, $key): array {
if (is_int($key)) {
return [$key => "mountedTableBulkActionData.{$value}"];
}
return ["mountedTableBulkActionData.{$key}" => $value];
})
->all(),
);
return $this;
};
}
}
@@ -2,6 +2,7 @@
namespace Filament\Tests\Admin\Fixtures\Pages;
use Filament\Forms\ComponentContainer;
use Filament\Forms\Components\TextInput;
use Filament\Pages\Actions\Action;
use Filament\Pages\Page;
@@ -17,12 +18,13 @@ class PageActions extends Page
->action(function () {
$this->emit('simple-called');
}),
Action::make('form')
Action::make('data')
->mountUsing(fn (ComponentContainer $form) => $form->fill(['foo' => 'bar']))
->form([
TextInput::make('payload')->required(),
])
->action(function (array $data) {
$this->emit('form-called', $data);
$this->emit('data-called', $data);
}),
Action::make('arguments')
->requiresConfirmation()
+13 -4
View File
@@ -2,6 +2,7 @@
use Filament\Tests\Admin\Fixtures\Pages\PageActions;
use Filament\Tests\Admin\Pages\TestCase;
use Filament\Tests\Tables\Fixtures\PostsTable;
use Illuminate\Support\Str;
use function Pest\Livewire\livewire;
@@ -15,22 +16,30 @@ it('can call an action', function () {
it('can call an action with data', function () {
livewire(PageActions::class)
->callPageAction('form', data: [
->callPageAction('data', data: [
'payload' => $payload = Str::random(),
])
->assertHasNoPageActionErrors()
->assertEmitted('form-called', [
->assertEmitted('data-called', [
'payload' => $payload,
]);
});
it('can validate an action\'s data', function () {
livewire(PageActions::class)
->callPageAction('form', data: [
->callPageAction('data', data: [
'payload' => null,
])
->assertHasPageActionErrors(['payload' => ['required']])
->assertNotEmitted('form-called');
->assertNotEmitted('data-called');
});
it('can set default action data when mounted', function () {
livewire(PageActions::class)
->mountPageAction('data')
->assertPageActionDataSet([
'foo' => 'bar',
]);
});
it('can call an action with arguments', function () {
+12 -22
View File
@@ -1,7 +1,6 @@
<?php
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\DeleteBulkAction;
use Filament\Tests\Models\Post;
use Filament\Tests\Tables\Fixtures\PostsTable;
use Filament\Tests\Tables\TestCase;
@@ -19,35 +18,32 @@ it('can call action', function () {
$this->assertModelMissing($post);
});
it('can call bulk action', function () {
$posts = Post::factory()->count(10)->create();
livewire(PostsTable::class)
->callTableBulkAction(DeleteBulkAction::class, $posts);
foreach ($posts as $post) {
$this->assertModelMissing($post);
}
});
it('can call an action with data', function () {
livewire(PostsTable::class)
->callTableAction('form', data: [
->callTableAction('data', data: [
'payload' => $payload = Str::random(),
])
->assertHasNoTableActionErrors()
->assertEmitted('form-called', [
->assertEmitted('data-called', [
'payload' => $payload,
]);
});
it('can validate an action\'s data', function () {
livewire(PostsTable::class)
->callTableAction('form', data: [
->callTableAction('data', data: [
'payload' => null,
])
->assertHasTableActionErrors(['payload' => ['required']])
->assertNotEmitted('form-called');
->assertNotEmitted('data-called');
});
it('can set default action data when mounted', function () {
livewire(PostsTable::class)
->mountTableAction('data')
->assertTableActionDataSet([
'foo' => 'bar',
]);
});
it('can call an action with arguments', function () {
@@ -72,9 +68,3 @@ it('can hide an action', function () {
->assertTableActionVisible('visible')
->assertTableActionHidden('hidden');
});
it('can hide a bulk action', function () {
livewire(PostsTable::class)
->assertTableBulkActionVisible('visible')
->assertTableBulkActionHidden('hidden');
});
+83
View File
@@ -0,0 +1,83 @@
<?php
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\DeleteBulkAction;
use Filament\Tests\Models\Post;
use Filament\Tests\Tables\Fixtures\PostsTable;
use Filament\Tests\Tables\TestCase;
use Illuminate\Support\Str;
use function Pest\Livewire\livewire;
uses(TestCase::class);
it('can call bulk action', function () {
$posts = Post::factory()->count(10)->create();
livewire(PostsTable::class)
->callTableBulkAction(DeleteBulkAction::class, $posts);
foreach ($posts as $post) {
$this->assertModelMissing($post);
}
});
it('can call a bulk action with data', function () {
$posts = Post::factory()->count(10)->create();
livewire(PostsTable::class)
->callTableBulkAction('data', records: $posts, data: [
'payload' => $payload = Str::random(),
])
->assertHasNoTableBulkActionErrors()
->assertEmitted('data-called', [
'payload' => $payload,
]);
});
it('can validate a bulk action\'s data', function () {
$posts = Post::factory()->count(10)->create();
livewire(PostsTable::class)
->callTableBulkAction('data', records: $posts, data: [
'payload' => null,
])
->assertHasTableBulkActionErrors(['payload' => ['required']])
->assertNotEmitted('data-called');
});
it('can set default bulk action data when mounted', function () {
$posts = Post::factory()->count(10)->create();
livewire(PostsTable::class)
->mountTableBulkAction('data', records: $posts)
->assertTableBulkActionDataSet([
'foo' => 'bar',
]);
});
it('can call a bulk action with arguments', function () {
$posts = Post::factory()->count(10)->create();
livewire(PostsTable::class)
->callTableBulkAction('arguments', records: $posts, arguments: [
'payload' => $payload = Str::random(),
])
->assertEmitted('arguments-called', [
'payload' => $payload,
]);
});
it('can call a bulk action and hold', function () {
$posts = Post::factory()->count(10)->create();
livewire(PostsTable::class)
->callTableBulkAction('hold', records: $posts)
->assertEmitted('hold-called')
->assertTableBulkActionHeld('hold');
});
it('can hide a bulk action', function () {
livewire(PostsTable::class)
->assertTableBulkActionVisible('visible')
->assertTableBulkActionHidden('hidden');
});
+24 -6
View File
@@ -2,6 +2,7 @@
namespace Filament\Tests\Tables\Fixtures;
use Filament\Forms\ComponentContainer;
use Filament\Forms\Components\TextInput;
use Filament\Tables;
use Filament\Tests\Models\Post;
@@ -42,16 +43,13 @@ class PostsTable extends Component implements Tables\Contracts\HasTable
protected function getTableHeaderActions(): array
{
return [
Tables\Actions\Action::make('simple')
->action(function () {
$this->emit('simple-called');
}),
Tables\Actions\Action::make('form')
Tables\Actions\Action::make('data')
->mountUsing(fn (ComponentContainer $form) => $form->fill(['foo' => 'bar']))
->form([
TextInput::make('payload')->required(),
])
->action(function (array $data) {
$this->emit('form-called', $data);
$this->emit('data-called', $data);
}),
Tables\Actions\Action::make('arguments')
->requiresConfirmation()
@@ -83,6 +81,26 @@ class PostsTable extends Component implements Tables\Contracts\HasTable
{
return [
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\BulkAction::make('data')
->mountUsing(fn (ComponentContainer $form) => $form->fill(['foo' => 'bar']))
->form([
TextInput::make('payload')->required(),
])
->action(function (array $data) {
$this->emit('data-called', $data);
}),
Tables\Actions\BulkAction::make('arguments')
->requiresConfirmation()
->action(function (array $arguments) {
$this->emit('arguments-called', $arguments);
}),
Tables\Actions\BulkAction::make('hold')
->requiresConfirmation()
->action(function (Tables\Actions\BulkAction $action) {
$this->emit('hold-called');
$action->hold();
}),
Tables\Actions\BulkAction::make('visible'),
Tables\Actions\BulkAction::make('hidden')
->hidden(),