Skip to content
全部文档

测试 Schema

在测试中填写表单

要用数据填写表单,请将数据传给 fillForm()

php
use function Pest\Livewire\livewire;

livewire(CreatePost::class)
    ->fillForm([
        'title' => fake()->sentence(),
        // ...
    ]);
若 Livewire 组件上有多个 schema,可用 `fillForm([...], 'createPostForm')` 指定要填写的表单。

测试表单字段与 infolist 条目状态

要检查表单是否具有某数据,请使用 assertSchemaStateSet()

php
use Illuminate\Support\Str;
use function Pest\Livewire\livewire;

it('can automatically generate a slug from the title', function () {
    $title = fake()->sentence();

    livewire(CreatePost::class)
        ->fillForm([
            'title' => $title,
        ])
        ->assertSchemaStateSet([
            'slug' => Str::slug($title),
        ]);
});
若 Livewire 组件上有多个 schema,可用 `assertSchemaStateSet([...], 'createPostForm')` 指定要检查的 schema。

你也可以向 assertSchemaStateSet() 方法传入一个函数,以便访问表单 $state 并执行额外断言:

php
use Illuminate\Support\Str;
use function Pest\Livewire\livewire;

it('can automatically generate a slug from the title without any spaces', function () {
    $title = fake()->sentence();

    livewire(CreatePost::class)
        ->fillForm([
            'title' => $title,
        ])
        ->assertSchemaStateSet(function (array $state): array {
            expect($state['slug'])
                ->not->toContain(' ');
                
            return [
                'slug' => Str::slug($title),
            ];
        });
});

若希望 Filament 在函数运行后继续断言 schema 状态,可以从该函数返回一个数组。

测试表单验证

使用 assertHasFormErrors() 确认表单中的数据得到了正确验证:

php
use function Pest\Livewire\livewire;

it('can validate input', function () {
    livewire(CreatePost::class)
        ->fillForm([
            'title' => null,
        ])
        ->call('create')
        ->assertHasFormErrors(['title' => 'required']);
});

使用 assertHasNoFormErrors() 确认没有验证错误:

php
use function Pest\Livewire\livewire;

livewire(CreatePost::class)
    ->fillForm([
        'title' => fake()->sentence(),
        // ...
    ])
    ->call('create')
    ->assertHasNoFormErrors();
若 Livewire 组件上有多个 schema,可将特定表单的名称作为第二个参数传入,例如 `assertHasFormErrors(['title' => 'required'], 'createPostForm')` 或 `assertHasNoFormErrors([], 'createPostForm')`。

测试表单是否存在

要检查 Livewire 组件是否有表单,请使用 assertSchemaExists('form')

php
use function Pest\Livewire\livewire;

it('has a form', function () {
    livewire(CreatePost::class)
        ->assertSchemaExists('form');
});
若 Livewire 组件上有多个 schema,可传入特定表单的名称,例如 `assertSchemaExists('createPostForm')`。

测试表单字段是否存在

要确认表单具有某个字段,请将字段名传给 assertFormFieldExists()

php
use function Pest\Livewire\livewire;

it('has a title field', function () {
    livewire(CreatePost::class)
        ->assertFormFieldExists('title');
});

你可以额外传入一个函数,断言该字段通过给定的「真值测试」。这适用于断言字段具有特定配置:

php
use function Pest\Livewire\livewire;

it('has a title field', function () {
    livewire(CreatePost::class)
        ->assertFormFieldExists('title', function (TextInput $field): bool {
            return $field->isDisabled();
        });
});

要断言表单没有某个字段,请将字段名传给 assertFormFieldDoesNotExist()

php
use function Pest\Livewire\livewire;

it('does not have a conditional field', function () {
    livewire(CreatePost::class)
        ->assertFormFieldDoesNotExist('no-such-field');
});
若 Livewire 组件上有多个 schema,可指定要检查字段是否存在的表单,例如 `assertFormFieldExists('title', 'createPostForm')`。

测试表单字段的可见性

要确认某个字段可见,请将名称传给 assertFormFieldVisible()

php
use function Pest\Livewire\livewire;

test('title is visible', function () {
    livewire(CreatePost::class)
        ->assertFormFieldVisible('title');
});

要确认某个字段隐藏,可将名称传给 assertFormFieldHidden()

php
use function Pest\Livewire\livewire;

test('title is hidden', function () {
    livewire(CreatePost::class)
        ->assertFormFieldHidden('title');
});

TIP

对于 assertFormFieldHidden()assertFormFieldVisible(),都可将字段所属特定表单的名称作为第二个参数传入,例如 assertFormFieldHidden('title', 'createPostForm')

测试禁用的表单字段

要确认某个字段已启用,请将名称传给 assertFormFieldEnabled()

php
use function Pest\Livewire\livewire;

test('title is enabled', function () {
    livewire(CreatePost::class)
        ->assertFormFieldEnabled('title');
});

要确认某个字段已禁用,可将名称传给 assertFormFieldDisabled()

php
use function Pest\Livewire\livewire;

test('title is disabled', function () {
    livewire(CreatePost::class)
        ->assertFormFieldDisabled('title');
});

TIP

对于 assertFormFieldEnabled()assertFormFieldDisabled(),都可将字段所属特定表单的名称作为第二个参数传入,例如 assertFormFieldEnabled('title', 'createPostForm')

测试其他 schema 组件

若需要检查某个 schema 组件(而非字段)是否存在,可使用 assertSchemaComponentExists()。由于组件没有名称,该方法使用开发者提供的 key()

php
use Filament\Schemas\Components\Section;

Section::make('Comments')
    ->key('comments-section')
    ->schema([
        //
    ])
php
use function Pest\Livewire\livewire;

test('comments section exists', function () {
    livewire(EditPost::class)
        ->assertSchemaComponentExists('comments-section');
});

要断言 schema 没有某个组件,请将组件 key 传给 assertSchemaComponentDoesNotExist()

php
use function Pest\Livewire\livewire;

it('does not have a conditional component', function () {
    livewire(CreatePost::class)
        ->assertSchemaComponentDoesNotExist('no-such-section');
});

要检查组件是否存在并通过给定的真值测试,可将函数传给 assertSchemaComponentExists()checkComponentUsing 参数;若组件通过测试则返回 true,否则返回 false:

php
use Filament\Schemas\Components\Section;

use function Pest\Livewire\livewire;

test('comments section has heading', function () {
    livewire(EditPost::class)
        ->assertSchemaComponentExists(
            'comments-section',
            checkComponentUsing: function (Section $component): bool {
                return $component->getHeading() === 'Comments';
            },
        );
});

若希望测试结果更有信息量,可在真值测试回调中嵌入断言:

php
use Filament\Schemas\Components\Section;
use Illuminate\Testing\Assert;

use function Pest\Livewire\livewire;

test('comments section is enabled', function () {
    livewire(EditPost::class)
        ->assertSchemaComponentExists(
            'comments-section',
            checkComponentUsing: function (Section $component): bool {
                Assert::assertTrue(
                    $component->isEnabled(),
                    'Failed asserting that comments-section is enabled.',
                );

                return true;
            },
        );
});

测试 schema 组件的可见性

要确认某个 schema 组件可见,请将 key 传给 assertSchemaComponentVisible()

php
use function Pest\Livewire\livewire;

test('comments section is visible', function () {
    livewire(EditPost::class)
        ->assertSchemaComponentVisible('comments-section');
});

要确认某个 schema 组件隐藏,可将 key 传给 assertSchemaComponentHidden()

php
use function Pest\Livewire\livewire;

test('comments section is hidden', function () {
    livewire(EditPost::class)
        ->assertSchemaComponentHidden('comments-section');
});

TIP

对于 assertSchemaComponentHidden()assertSchemaComponentVisible(),都可将组件所属特定 schema 的名称作为第二个参数传入,例如 assertSchemaComponentHidden('comments-section', 'createPostForm')

测试 repeater

内部实现中,repeater 会为条目生成 UUID,以便在 Livewire HTML 中更容易跟踪它们。因此,在测试带有 repeater 的表单时,需要确保表单与测试之间的 UUID 一致。这可能比较棘手;若处理不当,测试会失败,因为测试期望的是 UUID 而非数字键。

不过,由于 Livewire 在测试中不需要跟踪 UUID,可在测试开头使用 Repeater::fake() 方法禁用 UUID 生成,并用数字键替代:

php
use Filament\Forms\Components\Repeater;
use function Pest\Livewire\livewire;

$undoRepeaterFake = Repeater::fake();

livewire(EditPost::class, ['record' => $post])
    ->assertSchemaStateSet([
        'quotes' => [
            [
                'content' => 'First quote',
            ],
            [
                'content' => 'Second quote',
            ],
        ],
        // ...
    ]);

$undoRepeaterFake();

你也可以向 assertSchemaStateSet() 方法传入一个函数,以测试 repeater 中的条目数量:

php
use Filament\Forms\Components\Repeater;
use function Pest\Livewire\livewire;

$undoRepeaterFake = Repeater::fake();

livewire(EditPost::class, ['record' => $post])
    ->assertSchemaStateSet(function (array $state) {
        expect($state['quotes'])
            ->toHaveCount(2);
    });

$undoRepeaterFake();

测试 repeater action

要测试 repeater action 是否按预期工作,可使用 callFormComponentAction() 方法调用 repeater action,然后执行额外断言

要与某个 repeater 条目上的 action 交互,需要传入 item 参数,其值为该 repeater 条目的 key。若 repeater 读取的是关系,应将关联记录的 ID(key)加上 record- 前缀,以构成 repeater 条目的 key:

php
use App\Models\Quote;
use Filament\Forms\Components\Repeater;
use function Pest\Livewire\livewire;

$quote = Quote::first();

livewire(EditPost::class, ['record' => $post])
    ->callAction(TestAction::make('sendQuote')->schemaComponent('quotes')->arguments([
        'item' => "record-{$quote->getKey()}",
    ]))
    ->assertNotified('Quote sent!');

测试 builder

内部实现中,builder 会为条目生成 UUID,以便在 Livewire HTML 中更容易跟踪它们。因此,在测试带有 builder 的表单时,需要确保表单与测试之间的 UUID 一致。这可能比较棘手;若处理不当,测试会失败,因为测试期望的是 UUID 而非数字键。

不过,由于 Livewire 在测试中不需要跟踪 UUID,可在测试开头使用 Builder::fake() 方法禁用 UUID 生成,并用数字键替代:

php
use Filament\Forms\Components\Builder;
use function Pest\Livewire\livewire;

$undoBuilderFake = Builder::fake();

livewire(EditPost::class, ['record' => $post])
    ->assertSchemaStateSet([
        'content' => [
            [
                'type' => 'heading',
                'data' => [
                    'content' => 'Hello, world!',
                    'level' => 'h1',
                ],
            ],
            [
                'type' => 'paragraph',
                'data' => [
                    'content' => 'This is a test post.',
                ],
            ],
        ],
        // ...
    ]);

$undoBuilderFake();

你也可以向 assertSchemaStateSet() 方法传入一个函数,以测试 repeater 中的条目数量:

php
use Filament\Forms\Components\Builder;
use function Pest\Livewire\livewire;

$undoBuilderFake = Builder::fake();

livewire(EditPost::class, ['record' => $post])
    ->assertSchemaStateSet(function (array $state) {
        expect($state['content'])
            ->toHaveCount(2);
    });

$undoBuilderFake();

测试 wizard

要进入 wizard 的下一步,请使用 goToNextWizardStep()

php
use function Pest\Livewire\livewire;

it('moves to next wizard step', function () {
    livewire(CreatePost::class)
        ->goToNextWizardStep()
        ->assertHasFormErrors(['title']);
});

也可以调用 goToPreviousWizardStep() 进入上一步:

php
use function Pest\Livewire\livewire;

it('moves to next wizard step', function () {
    livewire(CreatePost::class)
        ->goToPreviousWizardStep()
        ->assertHasFormErrors(['title']);
});

若要跳到特定步骤,请使用 goToWizardStep(),然后使用 assertWizardCurrentStep 方法,确认已到达目标步骤且没有来自上一步的验证错误:

php
use function Pest\Livewire\livewire;

it('moves to the wizards second step', function () {
    livewire(CreatePost::class)
        ->goToWizardStep(2)
        ->assertWizardCurrentStep(2);
});

若单个 Livewire 组件上有多个 schema,任何 wizard 测试辅助方法都可以接受 schema 参数:

php
use function Pest\Livewire\livewire;

it('moves to next wizard step only for fooForm', function () {
    livewire(CreatePost::class)
        ->goToNextWizardStep(schema: 'fooForm')
        ->assertHasFormErrors(['title'], schema: 'fooForm');
});