你可以通过传递其名称或类给 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();
});要测试表操作,你可以使用一个 TestAction 对象配合 table() 方法。该对象接收你想要测试的操作名称,并替换你想要使用的任何测试方法中的此操作名称。例如:
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))要测试标头操作,您可以使用 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())要测试批量操作,首先调用 selectTableRecords() 并传入任何你想要选择的记录。然后,使用 TestAction 的 bulk() 方法来指定你想要测试的操作。例如:
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())如果某个操作属于资源信息列表中的一个组件,例如,如果它在信息列表条目的 belowContent() 方法中,你可以使用 TestAction 对象配合 schemaComponent() 方法。该对象接收你想要测试的操作名称,并替换掉你想要使用的任何测试方法中的操作名称。例如:
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'))如果一个操作属于另一个操作的 schema() (或 form())中的一个组件,例如,如果它在一个操作模态框中的表单字段的 belowContent() 方法中,你可以使用 TestAction 对象结合 schemaComponent() 方法。这个对象接收你想要测试的操作的名称,并替换你在任何想要使用的测试方法中的操作名称。你应该按顺序传递 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() 中测试自定义操作的详细信息,请参阅 测试资源 文档。
要将数据数组传递给操作,请使用 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);
});如果你需要只设置一个操作的数据而不立即调用它,你可以使用 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(),
])
});assertHasNoFormErrors() 用于断言在提交操作表单时没有发生验证错误。
要检查数据是否发生了验证错误,使用 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']]);
});要检查某个操作是否已预填充数据,你可以使用 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);
});为了断言模态框的内容, 你应该首先挂载该动作 (而不是调用它, 那样会关闭模态框). 然后你可以使用 assertMountedActionModalSee(), assertMountedActionModalDontSee(), assertMountedActionModalSeeHtml() or 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);
});为确保某个动作存在或不存在,你可以使用 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');
});你可以传递一个函数作为额外参数,以断言一个操作通过了给定的“真值测试”。这对于断言一个操作具有特定配置很有用:
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';
});
});为确保某个操作对用户隐藏或可见,您可以使用 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');
});为确保某个操作对用户是启用或禁用的,您可以使用 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');
});为了确保操作集按正确顺序存在, 您可以使用 assertActionsExistInOrder():
use function Pest\Livewire\livewire;
it('can have actions in order', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionsExistInOrder(['send', 'export']);
});要检查某个操作是否对用户隐藏,您可以使用 assertActionHidden() 方法:
use function Pest\Livewire\livewire;
it('can not send invoices', function () {
$invoice = Invoice::factory()->create();
livewire(EditInvoice::class, [
'invoice' => $invoice,
])
->assertActionHidden('send');
});为确保某个操作具有正确的标签,您可以使用 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');
});为确保某个操作的按钮显示正确的图标,你可以使用 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');
});为确保某个操作按钮显示正确的颜色,您可以使用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');
});为确保操作具有正确的 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');
});要测试动作参数,你可以使用一个 TestAction 对象,配合 arguments() 方法。该对象接收你想要测试的动作名称,并替换该动作的名称在你想要使用的任何测试方法中。例如:
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()]))要检查某个操作是否已停止,您可以使用 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');
});Filament 包含许多预设操作,例如 CreateAction, EditAction 和 DeleteAction,你可以在测试中使用这些类名而非操作名称,例如:
use Filament\Actions\CreateAction;
use function Pest\Livewire\livewire;
livewire(ManageInvoices::class)
->callAction(CreateAction::class)如果你的应用中存在带有 make() 方法的自定义动作类,Filament 无法发现你的动作名称,除非它运行 make() 方法,但这并不高效。要在测试中使用你的自定义动作类名称,你可以在动作类中添加 #[ActionName] 属性,Filament 可以利用它来发现你的动作名称。传递给 #[ActionName] 属性的名称应该与你通常在测试中使用的动作名称一致。例如:
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 类的动作类,你可以向该类添加一个 getDefaultName() 静态方法,该方法将用于发现动作的名称。它还允许用户在实例化时,从 make() 方法中省略动作的名称。例如:
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 () {
// ...
});
}
}