Skip to content
全部文档

测试资源

以用户身份认证

请确保在 TestCase 中已认证,以便访问应用:

php
use App\Models\User;

protected function setUp(): void
{
    parent::setUp();

    $this->actingAs(User::factory()->create());
}

或者,若使用 Pest,可在测试文件顶部用 beforeEach() 函数进行认证:

php
use App\Models\User;

beforeEach(function () {
    $user = User::factory()->create();

    actingAs($user);
});

测试资源列表页

要测试列表页能否加载,请将列表页作为 Livewire 组件进行测试,并调用 assertOk() 以确保 HTTP 响应为 200 OK。也可以使用 assertCanSeeTableRecords() 方法检查表格中是否显示了记录:

php
use App\Filament\Resources\Users\Pages\ListUsers;
use App\Models\User;

it('can load the page', function () {
    $users = User::factory()->count(5)->create();

    livewire(ListUsers::class)
        ->assertOk()
        ->assertCanSeeTableRecords($users);
});

要测试列表页上的表格,请参阅 测试表格 一节。要测试页面 header 或表格中的 action,请参阅 测试 Action 一节。以下是可在列表页上运行的其他常见测试示例。

测试表格搜索是否正常,可使用 searchTable() 方法搜索特定记录。也可以使用 assertCanSeeTableRecords()assertCanNotSeeTableRecords() 方法检查表格中是否显示了正确的记录:

php
use App\Filament\Resources\Users\Pages\ListUsers;
use App\Models\User;

it('can search users by `name` or `email`', function () {
    $users = User::factory()->count(5)->create();

    livewire(ListUsers::class)
        ->assertCanSeeTableRecords($users)
        ->searchTable($users->first()->name)
        ->assertCanSeeTableRecords($users->take(1))
        ->assertCanNotSeeTableRecords($users->skip(1))
        ->searchTable($users->last()->email)
        ->assertCanSeeTableRecords($users->take(-1))
        ->assertCanNotSeeTableRecords($users->take($users->count() - 1));
});

测试表格排序是否正常,可使用 sortTable() 方法按特定列排序。也可以使用 assertCanSeeTableRecords() 方法检查记录是否按正确顺序显示:

php
use App\Filament\Resources\Users\Pages\ListUsers;
use App\Models\User;

it('can sort users by `name`', function () {
    $users = User::factory()->count(5)->create();

    livewire(ListUsers::class)
        ->assertCanSeeTableRecords($users)
        ->sortTable('name')
        ->assertCanSeeTableRecords($users->sortBy('name'), inOrder: true)
        ->sortTable('name', 'desc')
        ->assertCanSeeTableRecords($users->sortByDesc('name'), inOrder: true);
});

测试表格筛选是否正常,可使用 filterTable() 方法按特定列筛选表格。也可以使用 assertCanSeeTableRecords()assertCanNotSeeTableRecords() 方法检查表格中是否显示了正确的记录:

php
use App\Filament\Resources\Users\Pages\ListUsers;
use App\Models\User;

it('can filter users by `locale`', function () {
    $users = User::factory()->count(5)->create();

    livewire(ListUsers::class)
        ->assertCanSeeTableRecords($users)
        ->filterTable('locale', $users->first()->locale)
        ->assertCanSeeTableRecords($users->where('locale', $users->first()->locale))
        ->assertCanNotSeeTableRecords($users->where('locale', '!=', $users->first()->locale));
});

测试表格 bulk action 是否正常,可使用 selectTableRecords() 方法在表格中选中多条记录。也可以使用 callAction() 方法对选中的记录调用特定 action:

php
use App\Filament\Resources\Users\Pages\ListUsers;
use App\Models\User;
use Filament\Actions\Testing\TestAction;
use function Pest\Laravel\assertDatabaseMissing;

it('can bulk delete users', function () {
    $users = User::factory()->count(5)->create();

    livewire(ListUsers::class)
        ->assertCanSeeTableRecords($users)
        ->selectTableRecords($users)
        ->callAction(TestAction::make(DeleteBulkAction::class)->table()->bulk())
        ->assertNotified()
        ->assertCanNotSeeTableRecords($users);

    $users->each(fn (User $user) => assertDatabaseMissing($user));
});

测试资源创建页

要测试创建页能否加载,请将创建页作为 Livewire 组件进行测试,并调用 assertOk() 以确保 HTTP 响应为 200 OK:

php
use App\Filament\Resources\Users\Pages\CreateUser;
use App\Models\User;

it('can load the page', function () {
    livewire(CreateUser::class)
        ->assertOk();
});

要测试创建页上的表单,请参阅 测试 Schema 一节。要测试页面 header 或表单中的 action,请参阅 测试 Action 一节。以下是可在创建页上运行的其他常见测试示例。

要测试表单是否正确创建记录,可使用 fillForm() 方法填写表单字段,然后使用 call('create') 方法创建记录。也可以使用 assertNotified() 方法检查是否显示了通知,以及 assertRedirect() 方法检查用户是否被重定向到其他页面:

php
use App\Filament\Resources\Users\Pages\CreateUser;
use App\Models\User;
use function Pest\Laravel\assertDatabaseHas;

it('can create a user', function () {
    $newUserData = User::factory()->make();

    livewire(CreateUser::class)
        ->fillForm([
            'name' => $newUserData->name,
            'email' => $newUserData->email,
        ])
        ->call('create')
        ->assertNotified()
        ->assertRedirect();

    assertDatabaseHas(User::class, [
        'name' => $newUserData->name,
        'email' => $newUserData->email,
    ]);
});

要测试表单验证是否正常,可使用 fillForm() 方法填写表单字段,然后使用 call('create') 方法创建记录。也可以使用 assertHasFormErrors() 方法检查表单是否有错误,以及 assertNotNotified() 方法检查是否未显示通知。还可以使用 assertNoRedirect() 方法检查用户是否未被重定向到其他页面。本例使用 Pest dataset 测试多条规则,而无需重复测试代码:

php
use App\Filament\Resources\Users\Pages\CreateUser;
use App\Models\User;
use Illuminate\Support\Str;

it('validates the form data', function (array $data, array $errors) {
    $newUserData = User::factory()->make();

    livewire(CreateUser::class)
        ->fillForm([
            'name' => $newUserData->name,
            'email' => $newUserData->email,
            ...$data,
        ])
        ->call('create')
        ->assertHasFormErrors($errors)
        ->assertNotNotified()
        ->assertNoRedirect();
})->with([
    '`name` is required' => [['name' => null], ['name' => 'required']],
    '`name` is max 255 characters' => [['name' => Str::random(256)], ['name' => 'max']],
    '`email` is a valid email address' => [['email' => Str::random()], ['email' => 'email']],
    '`email` is required' => [['email' => null], ['email' => 'required']],
    '`email` is max 255 characters' => [['email' => Str::random(256)], ['email' => 'max']],
]);

测试资源编辑页

要测试编辑页能否加载,请将编辑页作为 Livewire 组件进行测试,并调用 assertOk() 以确保 HTTP 响应为 200 OK。也可以使用 assertSchemaStateSet() 方法检查表单字段是否被设置为正确的值:

php
use App\Filament\Resources\Users\Pages\EditUser;
use App\Models\User;

it('can load the page', function () {
    $user = User::factory()->create();

    livewire(EditUser::class, [
        'record' => $user->id,
    ])
        ->assertOk()
        ->assertSchemaStateSet([
            'name' => $user->name,
            'email' => $user->email,
        ]);
});

要测试编辑页上的表单,请参阅 测试 Schema 一节。要测试页面 header 或表单中的 action,请参阅 测试 Action 一节。以下是可在编辑页上运行的其他常见测试示例。

php
use App\Filament\Resources\Users\Pages\EditUser;
use App\Models\User;
use function Pest\Laravel\assertDatabaseHas;

it('can update a user', function () {
    $user = User::factory()->create();

    $newUserData = User::factory()->make();

    livewire(EditUser::class, [
        'record' => $user->id,
    ])
        ->fillForm([
            'name' => $newUserData->name,
            'email' => $newUserData->email,
        ])
        ->call('save')
        ->assertNotified();

    assertDatabaseHas(User::class, [
        'id' => $user->id,
        'name' => $newUserData->name,
        'email' => $newUserData->email,
    ]);
});

要测试表单验证是否正常,可使用 fillForm() 方法填写表单字段,然后使用 call('save') 方法保存记录。也可以使用 assertHasFormErrors() 方法检查表单是否有错误,以及 assertNotNotified() 方法检查是否未显示通知。本例使用 Pest dataset 测试多条规则,而无需重复测试代码:

php
use App\Filament\Resources\Users\Pages\EditUser;
use App\Models\User;
use Illuminate\Support\Str;

it('validates the form data', function (array $data, array $errors) {
    $user = User::factory()->create();

    $newUserData = User::factory()->make();

    livewire(EditUser::class, [
        'record' => $user->id,
    ])
        ->fillForm([
            'name' => $newUserData->name,
            'email' => $newUserData->email,
            ...$data,
        ])
        ->call('save')
        ->assertHasFormErrors($errors)
        ->assertNotNotified();
})->with([
    '`name` is required' => [['name' => null], ['name' => 'required']],
    '`name` is max 255 characters' => [['name' => Str::random(256)], ['name' => 'max']],
    '`email` is a valid email address' => [['email' => Str::random()], ['email' => 'email']],
    '`email` is required' => [['email' => null], ['email' => 'required']],
    '`email` is max 255 characters' => [['email' => Str::random(256)], ['email' => 'max']],
]);

测试 action 是否正常,例如 DeleteAction,可使用 callAction() 方法调用删除 action。也可以使用 assertNotified() 方法检查是否显示了通知,以及 assertRedirect() 方法检查用户是否被重定向到其他页面:

php
use App\Filament\Resources\Users\Pages\EditUser;
use App\Models\User;
use Filament\Actions\DeleteAction;
use function Pest\Laravel\assertDatabaseMissing;

it('can delete a user', function () {
    $user = User::factory()->create();

    livewire(EditUser::class, [
        'record' => $user->id,
    ])
        ->callAction(DeleteAction::class)
        ->assertNotified()
        ->assertRedirect();

    assertDatabaseMissing($user);
});

测试资源查看页

要测试查看页能否加载,请将查看页作为 Livewire 组件进行测试,并调用 assertOk() 以确保 HTTP 响应为 200 OK。也可以使用 assertSchemaStateSet() 方法检查 infolist 条目是否被设置为正确的值:

php
use App\Filament\Resources\Users\Pages\ViewUser;
use App\Models\User;

it('can load the page', function () {
    $user = User::factory()->create();

    livewire(ViewUser::class, [
        'record' => $user->id,
    ])
        ->assertOk()
        ->assertSchemaStateSet([
            'name' => $user->name,
            'email' => $user->email,
        ]);
});

要测试查看页上的 infolist,请参阅 测试 Schema 一节。要测试页面 header 或 infolist 中的 action,请参阅 测试 Action 一节。

测试 relation manager

要测试页面(例如资源的编辑页)上是否渲染了 relation manager,可使用 assertSeeLivewire() 方法检查 relation manager 是否正在渲染:

php
use App\Filament\Resources\Users\Pages\EditUser;
use App\Filament\Resources\Users\RelationManagers\PostsRelationManager;
use App\Models\User;

it('can load the relation manager', function () {
    $user = User::factory()->create();

    livewire(EditUser::class, [
        'record' => $user->id,
    ])
        ->assertSeeLivewire(PostsRelationManager::class);
});

由于 relation manager 是 Livewire 组件,也可以测试 relation manager 自身的功能,例如能否以 200 OK 响应成功加载,以及表格中是否有正确的记录。测试 relation manager 时,需要传入 ownerRecord(你所在资源中的记录)和 pageClass(当前页面的类):

php
use App\Filament\Resources\Users\Pages\EditUser;
use App\Filament\Resources\Users\RelationManagers\PostsRelationManager;
use App\Models\Post;
use App\Models\User;

it('can load the relation manager', function () {
    $user = User::factory()
        ->has(Post::factory()->count(5))
        ->create();

    livewire(PostsRelationManager::class, [
        'ownerRecord' => $user,
        'pageClass' => EditUser::class,
    ])
        ->assertOk()
        ->assertCanSeeTableRecords($user->posts);
});

可以像在资源列表页上一样测试搜索排序筛选

也可以测试 action,例如表格 header 中的 CreateAction

php
use App\Filament\Resources\Users\Pages\EditUser;
use App\Filament\Resources\Users\RelationManagers\PostsRelationManager;
use App\Models\Post;
use App\Models\User;
use Filament\Actions\Testing\TestAction;
use function Pest\Laravel\assertDatabaseHas;

it('can create a post', function () {
    $user = User::factory()->create();

    $newPostData = Post::factory()->make();

    livewire(PostsRelationManager::class, [
        'ownerRecord' => $user,
        'pageClass' => EditUser::class,
    ])
        ->callAction(TestAction::make(CreateAction::class)->table(), [
            'title' => $newPostData->title,
            'content' => $newPostData->content,
        ])
        ->assertNotified();

    assertDatabaseHas(Post::class, [
        'title' => $newPostData->title,
        'content' => $newPostData->content,
        'user_id' => $user->id,
    ]);
});

测试创建 / 编辑页的 getFormActions()

在资源页面上测试 getFormActions() 中的 action 时,请使用 schemaComponent() 方法,并以 content schema 中的 form-actions 键为目标。例如,若在 CreateUser 页面的 getFormActions() 方法中有自定义的 Action::make('createAndVerifyEmail') action,可以这样测试:

php
use App\Filament\Resources\Users\Pages\CreateUser;
use App\Models\User;
use Filament\Actions\Testing\TestAction;

it('can create a user and verify their email address', function () {
    livewire(CreateUser::class)
        ->fillForm([
            'name' => 'Test User',
            'email' => 'test@example.com',
        ])
        ->callAction(TestAction::make('createAndVerifyEmail')->schemaComponent('form-actions', schema: 'content'));

    expect(User::query()->where('email', 'test@example.com')->first())
        ->hasVerifiedEmail()->toBeTrue();
});

测试多个面板

若有多个面板且想测试非默认面板,需要告知 Filament 正在测试哪个面板。可在测试用例的 setUp() 方法中完成,也可以在某个测试的开头进行。通过请求访问面板时,Filament 通常在中间件中完成此事;因此若测试中没有发起请求(例如测试 Livewire 组件时),需要手动设置当前面板:

php
use Filament\Facades\Filament;

Filament::setCurrentPanel('app'); // Where `app` is the ID of the panel you want to test.

测试多租户面板

在多租户面板中测试资源时,设置租户后可能需要调用 Filament::bootCurrentPanel(),以便应用租户作用域和模型事件监听器:

php
use Filament\Facades\Filament;

$team = Team::factory()->create();

Filament::setTenant($this->team);
Filament::setCurrentPanel('admin');
Filament::bootCurrentPanel();