测试 Schema
在测试中填写表单
要用数据填写表单,请将数据传给 fillForm():
use function Pest\Livewire\livewire;
livewire(CreatePost::class)
->fillForm([
'title' => fake()->sentence(),
// ...
]);若 Livewire 组件上有多个 schema,可用 `fillForm([...], 'createPostForm')` 指定要填写的表单。
测试表单字段与 infolist 条目状态
要检查表单是否具有某数据,请使用 assertSchemaStateSet():
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 并执行额外断言:
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() 确认表单中的数据得到了正确验证:
use function Pest\Livewire\livewire;
it('can validate input', function () {
livewire(CreatePost::class)
->fillForm([
'title' => null,
])
->call('create')
->assertHasFormErrors(['title' => 'required']);
});使用 assertHasNoFormErrors() 确认没有验证错误:
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'):
use function Pest\Livewire\livewire;
it('has a form', function () {
livewire(CreatePost::class)
->assertSchemaExists('form');
});若 Livewire 组件上有多个 schema,可传入特定表单的名称,例如 `assertSchemaExists('createPostForm')`。
测试表单字段是否存在
要确认表单具有某个字段,请将字段名传给 assertFormFieldExists():
use function Pest\Livewire\livewire;
it('has a title field', function () {
livewire(CreatePost::class)
->assertFormFieldExists('title');
});你可以额外传入一个函数,断言该字段通过给定的「真值测试」。这适用于断言字段具有特定配置:
use function Pest\Livewire\livewire;
it('has a title field', function () {
livewire(CreatePost::class)
->assertFormFieldExists('title', function (TextInput $field): bool {
return $field->isDisabled();
});
});要断言表单没有某个字段,请将字段名传给 assertFormFieldDoesNotExist():
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():
use function Pest\Livewire\livewire;
test('title is visible', function () {
livewire(CreatePost::class)
->assertFormFieldVisible('title');
});要确认某个字段隐藏,可将名称传给 assertFormFieldHidden():
use function Pest\Livewire\livewire;
test('title is hidden', function () {
livewire(CreatePost::class)
->assertFormFieldHidden('title');
});TIP
对于 assertFormFieldHidden() 和 assertFormFieldVisible(),都可将字段所属特定表单的名称作为第二个参数传入,例如 assertFormFieldHidden('title', 'createPostForm')。
测试禁用的表单字段
要确认某个字段已启用,请将名称传给 assertFormFieldEnabled():
use function Pest\Livewire\livewire;
test('title is enabled', function () {
livewire(CreatePost::class)
->assertFormFieldEnabled('title');
});要确认某个字段已禁用,可将名称传给 assertFormFieldDisabled():
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():
use Filament\Schemas\Components\Section;
Section::make('Comments')
->key('comments-section')
->schema([
//
])use function Pest\Livewire\livewire;
test('comments section exists', function () {
livewire(EditPost::class)
->assertSchemaComponentExists('comments-section');
});要断言 schema 没有某个组件,请将组件 key 传给 assertSchemaComponentDoesNotExist():
use function Pest\Livewire\livewire;
it('does not have a conditional component', function () {
livewire(CreatePost::class)
->assertSchemaComponentDoesNotExist('no-such-section');
});要检查组件是否存在并通过给定的真值测试,可将函数传给 assertSchemaComponentExists() 的 checkComponentUsing 参数;若组件通过测试则返回 true,否则返回 false:
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';
},
);
});若希望测试结果更有信息量,可在真值测试回调中嵌入断言:
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():
use function Pest\Livewire\livewire;
test('comments section is visible', function () {
livewire(EditPost::class)
->assertSchemaComponentVisible('comments-section');
});要确认某个 schema 组件隐藏,可将 key 传给 assertSchemaComponentHidden():
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 生成,并用数字键替代:
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 中的条目数量:
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:
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 生成,并用数字键替代:
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 中的条目数量:
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():
use function Pest\Livewire\livewire;
it('moves to next wizard step', function () {
livewire(CreatePost::class)
->goToNextWizardStep()
->assertHasFormErrors(['title']);
});也可以调用 goToPreviousWizardStep() 进入上一步:
use function Pest\Livewire\livewire;
it('moves to next wizard step', function () {
livewire(CreatePost::class)
->goToPreviousWizardStep()
->assertHasFormErrors(['title']);
});若要跳到特定步骤,请使用 goToWizardStep(),然后使用 assertWizardCurrentStep 方法,确认已到达目标步骤且没有来自上一步的验证错误:
use function Pest\Livewire\livewire;
it('moves to the wizards second step', function () {
livewire(CreatePost::class)
->goToWizardStep(2)
->assertWizardCurrentStep(2);
});若单个 Livewire 组件上有多个 schema,任何 wizard 测试辅助方法都可以接受 schema 参数:
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');
});