[Laravel/Livewire]コンポーネントをテストする
はじめに
Livewireの勉強で作成したフォームコンポーネントをテストしてみました。
環境
PHP 8.x
Laravel 10.x
Tailwind
tl;dr
1. コンポーネントを作成する
2. ビューを作成する
3. バリデーションロジックを追加する
4. テストケースを作成する
5. まとめ
コンポーネントを作成する
フォームコンポーネントを作成します。
➜ php artisan livewire:make Form
COMPONENT CREATED 🤙
CLASS: app/Livewire/Form.php
VIEW: resources/views/livewire/form.blade.php
_._
/ /o\ \ || () () __
|_\ /_| || || \\// /_\ \\ // || |~~ /_\
|`|`| || || \/ \\_ \^/ || || \\_
Congratulations, you've created your first Livewire component! 🎉🎉🎉
作成したコンポーネントをビューに読み込みます。
<livewire:form />
ビューを作成する
Livewireコンポーネントのプロパティに同期されるようwire:model
を追加します。
wire:model.live
またはwire:model.blur
を使用すると、フィールドが入力されたときにネットワークリクエストをトリガーするように入力に対してユーザーにリアルタイムのバリデーションを提供することができます。
<form wire:submit.prevent="submitForm" action="/form" method="POST">
@csrf
// フラッシュメッセージ
@if(session()->has('success_message'))
<div>
{{ session('success_message') }}
</div>
@endif
// フォーム
<div>
<input wire:model="name" id="name" name="name" value="{{ old('name') }}" placeholder="名前">
</div>
// バリデーション
@error('name')
<p>{{ $message }}</p>
@enderror
<div>
<input wire:model="email" id="email" type="text" name="email" value="{{ old('email') }}" placeholder="メールアドレス">
</div>
@error('email')
<p>{{ $message }}</p>
@enderror
<div>
<textarea wire:model="message" id="message" rows="4" name="message" placeholder="お問い合わせ">{{ old('message') }}</textarea>
</div>
@error('message')
<p>{{ $message }}</p>
@enderror
<button type="submit">
送信
</button>
</form>
wire:submit.prevent
ディレクティブは、通常のフォームの submit
イベントを Livewire コンポーネントのメソッドにバインドする役割を果たします。
通常のフォーム送信が行われた場合、ブラウザはページを再読み込みします。.prevent
はイベントのデフォルトの挙動をキャンセルし、通常のフォームの送信が防がれ、Livewire コンポーネントのメソッドに制御が渡されます。
これによりページ全体を再読み込みせずに、動的にフォームの送信と応答を処理できます。
バリデーションロジックを追加する
フォームの各プロパティを定義します。
<?php
namespace App\Livewire;
use Livewire\Component;
class Form extends Component
{
// プロパティを定義する
public $name;
public $email;
public $message;
// バリデーションルールを定義する
protected $rules = [
'name' => 'required|min:3',
'email' => 'required|email',
'message' => 'required|min:5',
];
// エラーメッセージを定義する
protected $messages = [
'name.required' => '名前は必須です。',
'name.min' => '名前は少なくとも:min文字以上でなければなりません。',
'email.required' => 'メールアドレスは必須です。',
'email.email' => '有効なメールアドレスを入力してください。',
'message.required' => 'メッセージは必須です。',
'message.min' => 'メッセージは少なくとも:min文字以上でなければなりません。',
];
// リアルタイムに検証する
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
// フォームの送信
public function submitForm()
{
// フォームの内容をバリデートする
$this->validate();
// 送信されたらフォームがリセットされる
$this->reset();
session()->flash('success_message', 'お問い合わせありがとうございました。');
}
public function render()
{
return view('livewire.form');
}
}
これで非同期でフォームの送信とエラーメッセージ、フラッシュメッセージの表示ができました。
テストケースを作成する
フォームが正しく機能しているかどうかを確認するためにテストを作成します。
➜ php artisan make:livewire form --test
INFO Test [tests/Feature/Livewire/FormTest.php] created successfully.
テストメソッドは /** @test */
アノテーションを使用して定義されます。
<?php
namespace Tests\Feature\Livewire;
use App\Livewire\Form;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Livewire\Livewire;
use Tests\TestCase;
class FormTest extends TestCase
{
// Livewireコンポーネントが存在している
/** @test */
public function livewire_form()
{
$this->get('/')
->assertSeeLivewire('form');
}
// フォームを送信できる
/** @test */
public function form_submits()
{
Livewire::test(Form::class)
->set('name', 'Test User')
->set('email', 'test@example.com')
->set('message', 'hello')
->call('submitForm')
->assertSee('お問い合わせありがとうございました。');
}
// 名前を入力しないと送信できない
/** @test */
public function form_name_required()
{
Livewire::test(Form::class)
->set('name', '')
->set('email', 'test@example.com')
->set('message', 'hello')
->call('submitForm')
->assertHasErrors(['name' => 'required']);
}
// メッセージを5文字入力しないと送信できない
/** @test */
public function form_message_has_min_characters()
{
Livewire::test(Form::class)
->set('name', 'Test User')
->set('email', 'test@example.com')
->set('message', 'hi')
->call('submitForm')
->assertHasErrors(['message' => 'min']);
}
}
get
メソッド: get('/')
を使用して、特定のURL(この場合はルートURL)にGETリクエストを送信し、そのページにLivewireコンポーネントが表示されるかどうかを確認しています。
Livewire::test
メソッド: Livewireコンポーネントをテストするためのメソッドです。Livewire::test(Form::class)
は、Form
コンポーネントをテストモードで起動します。
set
メソッド: フォームフィールドの値を設定するためのメソッドです。例えば、->set('name', 'Test User')
は、フォームの名前フィールドに 'Test User' という値を設定しています。
call
メソッド: Livewireコンポーネントのメソッドを呼び出すためのメソッドです。例えば、->call('submitForm')
は、Form
コンポーネントの submitForm
メソッドを呼び出しています。
assertSee
メソッド: 特定のテキストが表示されているかどうかを確認するためのメソッドです。例えば、->assertSee('お問い合わせありがとうございました。')
は、指定したテキストが表示されていることを確認しています。
assertHasErrors
メソッド: Livewireコンポーネントのバリデーションエラーが正しく発生しているかを確認するためのメソッドです。例えば、->assertHasErrors(['name' => 'required'])
は、name
フィールドが必須であるというバリデーションエラーが発生していることを確認しています。
テストを実行してみます。
➜ php artisan test --filter Livewire
PASS Tests\Feature\Livewire\FormTest
✓ livewire form 0.22s
✓ form submits 0.06s
✓ form name required 0.02s
✓ form message has min characters 0.02s
Tests: 4 passed (6 assertions)
Duration: 0.40s
まとめ
Livewireのテストは、Livewireコンポーネントの動作や状態を確認し、アプリケーションの期待される挙動を検証するためのものです。Livewireテストは通常、PHPUnitを使用して行われます。
Livewireテストの基本的な手順:
-
テストクラスの作成:
Tests\Feature\Livewire
ディレクトリ内にLivewireコンポーネントに対応するテストクラスを作成します。 -
Livewireコンポーネントのテスト:
Livewire::test
メソッドを使用してLivewireコンポーネントをテストモードで起動します。 -
プロパティやメソッドのテスト: Livewireコンポーネントのプロパティやメソッドに対してテストを行います。
-
アサーションの使用:
assertSee
やassertHasErrors
などのアサーションメソッドを使用して、期待される結果を検証します。
メソッド | 説明 |
---|---|
get($uri) |
指定されたURIに対してGETリクエストを行い、レスポンスを取得します。 |
post($uri, $data) |
指定されたURIに対してPOSTリクエストを行い、データを送信します。 |
Livewire::test($component) |
指定されたLivewireコンポーネントをテストモードで起動します。 |
set($property, $value) |
Livewireコンポーネントのプロパティに値を設定します。 |
call($method, $parameters) |
Livewireコンポーネントのメソッドを呼び出します。 |
assertSee($text) |
レスポンスに指定したテキストが表示されていることを確認します。 |
assertHasErrors($errors) |
Livewireコンポーネントで指定されたバリデーションエラーが存在することを確認します。 |
assertStatus($code) |
レスポンスのHTTPステータスコードが指定されたコードと一致することを確認します。 |
assertRedirect($uri) |
レスポンスが指定されたURIにリダイレクトされたことを確認します。 |
Discussion