测试 Action
在测试中调用 action
可通过将 action 的名称或类传给 callAction() 来调用它:
use function Pest\Livewire\livewire;
it('can send invoices', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->callAction('send');
expect($invoice->refresh())
->isSent()->toBeTrue();
});测试表格 action
要测试表格 action,可使用带有 table() 方法的 TestAction 对象。该对象接收你要测试的 action 名称,并在任何测试方法中替代 action 名称。例如:
use Filament\Actions\Testing\TestAction;
use function Pest\Livewire\livewire;
$invoice = Invoice::factory()->create();
livewire(ListInvoices::class)
->callAction(TestAction::make('send')->table($invoice));
livewire(ListInvoices::class)
->assertActionVisible(TestAction::make('send')->table($invoice))
livewire(ListInvoices::class)
->assertActionExists(TestAction::make('send')->table($invoice))测试表格 header action
要测试 header action,可使用不传入具体记录的 table() 方法:
use Filament\Actions\Testing\TestAction;
use function Pest\Livewire\livewire;
livewire(ListInvoices::class)
->callAction(TestAction::make('create')->table());
livewire(ListInvoices::class)
->assertActionVisible(TestAction::make('create')->table())
livewire(ListInvoices::class)
->assertActionExists(TestAction::make('create')->table())测试表格 bulk action
要测试 bulk action,先调用 selectTableRecords() 并传入要选中的记录。然后使用 TestAction 的 bulk() 方法指定要测试的 action。例如:
use Filament\Actions\Testing\TestAction;
use function Pest\Livewire\livewire;
$invoices = Invoice::factory()->count(3)->create();
livewire(ListInvoices::class)
->selectTableRecords($invoices->pluck('id')->toArray())
->callAction(TestAction::make('send')->table()->bulk());
livewire(ListInvoices::class)
->assertActionVisible(TestAction::make('send')->table()->bulk())
livewire(ListInvoices::class)
->assertActionExists(TestAction::make('send')->table()->bulk())测试 schema 中的 action
如果 action 属于资源 infolist 中的某个组件(例如位于 infolist entry 的 belowContent() 方法中),可使用带有 schemaComponent() 方法的 TestAction 对象。该对象接收你要测试的 action 名称,并在任何测试方法中替代 action 名称。例如:
use Filament\Actions\Testing\TestAction;
use function Pest\Livewire\livewire;
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class)
->callAction(TestAction::make('send')->schemaComponent('customer_id'));
livewire(EditInvoice::class)
->assertActionVisible(TestAction::make('send')->schemaComponent('customer_id'))
livewire(EditInvoice::class)
->assertActionExists(TestAction::make('send')->schemaComponent('customer_id'))测试另一 action 的 schema / form 内的 action
如果 action 属于另一 action 的 schema()(或 form())中的组件(例如位于 action 模态框中表单字段的 belowContent() 方法中),可使用带有 schemaComponent() 方法的 TestAction 对象。该对象接收你要测试的 action 名称,并在任何测试方法中替代 action 名称。应按顺序传入 TestAction 对象数组,例如:
use Filament\Actions\Testing\TestAction;
use function Pest\Livewire\livewire;
$invoice = Invoice::factory()->create();
livewire(ManageInvoices::class)
->callAction([
TestAction::make('view')->table($invoice),
TestAction::make('send')->schemaComponent('customer.name'),
]);
livewire(ManageInvoices::class)
->assertActionVisible([
TestAction::make('view')->table($invoice),
TestAction::make('send')->schemaComponent('customer.name'),
]);
livewire(ManageInvoices::class)
->assertActionExists([
TestAction::make('view')->table($invoice),
TestAction::make('send')->schemaComponent('customer.name'),
]);测试资源的 getFormActions()
关于如何测试资源页面 getFormActions() 中的自定义 action,请参阅 测试资源 文档。
测试 action 模态框中的表单
若要向 action 传入数据数组,请使用 data 参数:
use function Pest\Livewire\livewire;
it('can send invoices', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->callAction('send', data: [
'email' => $email = fake()->email(),
])
->assertHasNoFormErrors();
expect($invoice->refresh())
->isSent()->toBeTrue()
->recipient_email->toBe($email);
});若只需设置 action 的数据而不立即调用它,可以使用 fillForm():
use function Pest\Livewire\livewire;
it('can send invoices', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->mountAction('send')
->fillForm([
'email' => $email = fake()->email(),
])
});测试 action 模态框表单中的验证错误
assertHasNoFormErrors() 用于断言提交 action 表单时未发生验证错误。
若要检查数据是否触发验证错误,请使用 assertHasFormErrors(),用法类似 Livewire 中的 assertHasErrors():
use function Pest\Livewire\livewire;
it('can validate invoice recipient email', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->callAction('send', data: [
'email' => Str::random(),
])
->assertHasFormErrors(['email' => ['email']]);
});若要检查 action 是否已预填数据,可使用 assertSchemaStateSet() 方法:
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,
])
->mountAction('send')
->assertSchemaStateSet([
'email' => $recipientEmail,
])
->callMountedAction()
->assertHasNoFormErrors();
expect($invoice->refresh())
->isSent()->toBeTrue()
->recipient_email->toBe($recipientEmail);
});测试 action 模态框内容
要断言模态框内容,应先 mount action(而不是 call,因为 call 会关闭模态框)。随后可使用 assertMountedActionModalSee()、assertMountedActionModalDontSee()、assertMountedActionModalSeeHtml() 或 assertMountedActionModalDontSeeHtml() 断言模态框包含你期望的内容:
use function Pest\Livewire\livewire;
it('confirms the target address before sending', function () {
$invoice = Invoice::factory()->create();
$recipientEmail = $invoice->company->primaryContact->email;
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->mountAction('send')
->assertMountedActionModalSee($recipientEmail);
});测试 action 是否存在
要确认 action 是否存在,可使用 assertActionExists() 或 assertActionDoesNotExist() 方法:
use function Pest\Livewire\livewire;
it('can send but not unsend invoices', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionExists('send')
->assertActionDoesNotExist('unsend');
});你还可以传入一个函数作为额外参数,断言 action 通过给定的「真值测试」。这在断言 action 具有特定配置时很有用:
use Filament\Actions\Action;
use function Pest\Livewire\livewire;
it('has the correct description', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionExists('send', function (Action $action): bool {
return $action->getModalDescription() === 'This will send an email to the customer\'s primary address, with the invoice attached as a PDF';
});
});测试 action 的可见性
要确认某用户下 action 是隐藏还是可见,可使用 assertActionHidden() 或 assertActionVisible() 方法:
use function Pest\Livewire\livewire;
it('can only print invoices', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionHidden('send')
->assertActionVisible('print');
});测试禁用的 action
要确认某用户下 action 是启用还是禁用,可使用 assertActionEnabled() 或 assertActionDisabled() 方法:
use function Pest\Livewire\livewire;
it('can only print a sent invoice', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionDisabled('send')
->assertActionEnabled('print');
});要确认多组 action 按正确顺序存在,可使用 assertActionListInOrder():
use function Pest\Livewire\livewire;
it('can have actions in order', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionListInOrder(['send', 'export']);
});若要检查 action 对某用户是否隐藏,可使用 assertActionHidden() 方法:
use function Pest\Livewire\livewire;
it('can not send invoices', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionHidden('send');
});测试 action 的标签
要确认 action 具有正确的标签,可使用 assertActionHasLabel() 和 assertActionDoesNotHaveLabel():
use function Pest\Livewire\livewire;
it('send action has correct label', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionHasLabel('send', 'Email Invoice')
->assertActionDoesNotHaveLabel('send', 'Send');
});测试 action 的图标
要确认 action 按钮显示正确的图标,可使用 assertActionHasIcon() 或 assertActionDoesNotHaveIcon():
use function Pest\Livewire\livewire;
it('when enabled the send button has correct icon', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionEnabled('send')
->assertActionHasIcon('send', 'envelope-open')
->assertActionDoesNotHaveIcon('send', 'envelope');
});测试 action 的颜色
要确认 action 按钮显示正确的颜色,可使用 assertActionHasColor() 或 assertActionDoesNotHaveColor():
use function Pest\Livewire\livewire;
it('actions display proper colors', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionHasColor('delete', 'danger')
->assertActionDoesNotHaveColor('print', 'danger');
});测试 action 的 URL
要确认 action 具有正确的 URL,可使用 assertActionHasUrl()、assertActionDoesNotHaveUrl()、assertActionShouldOpenUrlInNewTab() 和 assertActionShouldNotOpenUrlInNewTab():
use function Pest\Livewire\livewire;
it('links to the correct Filament sites', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionHasUrl('filament', 'https://filamentphp.com/')
->assertActionDoesNotHaveUrl('filament', 'https://github.com/filamentphp/filament')
->assertActionShouldOpenUrlInNewTab('filament')
->assertActionShouldNotOpenUrlInNewTab('github');
});测试 action 参数
要测试 action 参数,可使用带有 arguments() 方法的 TestAction 对象。该对象接收你要测试的 action 名称,并在任何测试方法中替代 action 名称。例如:
use Filament\Actions\Testing\TestAction;
use function Pest\Livewire\livewire;
$invoice = Invoice::factory()->create();
livewire(ManageInvoices::class)
->callAction(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()]));
livewire(ManageInvoices::class)
->assertActionVisible(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()]))
livewire(ManageInvoices::class)
->assertActionExists(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()]))测试 action 是否已中止
若要检查 action 是否已中止,可使用 assertActionHalted():
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,
])
->callAction('send')
->assertActionHalted('send');
});在测试中使用 action 类名
Filament 内置了大量预构建 action,例如 CreateAction、EditAction 和 DeleteAction,你可以在测试中使用这些类名代替 action 名称,例如:
use Filament\Actions\CreateAction;
use function Pest\Livewire\livewire;
livewire(ManageInvoices::class)
->callAction(CreateAction::class)若应用中有自定义 action 类且带有 make() 方法,Filament 在不运行 make() 的情况下无法发现 action 名称,而运行 make() 并不高效。要在测试中使用自定义 action 类名,可为 action 类添加 #[ActionName] 属性,Filament 可用它发现 action 名称。传给 #[ActionName] 的名称应与你在测试中通常使用的 action 名称相同。例如:
use Filament\Actions\Action;
use Filament\Actions\ActionName;
#[ActionName('send')]
class SendInvoiceAction
{
public static function make(): Action
{
return Action::make('send')
->requiresConfirmation()
->action(function () {
// ...
});
}
}现在你可以在测试中使用该类名:
use App\Filament\Resources\Invoices\Actions\SendInvoiceAction;
use Filament\Actions\Testing\TestAction;
use function Pest\Livewire\livewire;
$invoice = Invoice::factory()->create();
livewire(ManageInvoices::class)
->callAction(TestAction::make(SendInvoiceAction::class)->table($invoice);若 action 类继承自 Action 类,可为该类添加静态方法 getDefaultName(),用于发现 action 名称。它还允许用户在实例化时省略 make() 方法中的 action 名称。例如:
use Filament\Actions\Action;
class SendInvoiceAction extends Action
{
public static function getDefaultName(): string
{
return 'send';
}
protected function setUp(): void
{
parent::setUp();
$this
->requiresConfirmation()
->action(function () {
// ...
});
}
}