🦓

[Laravel/Livewire]コンポーネントをテストする

2023/11/17に公開

はじめに

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を使用すると、フィールドが入力されたときにネットワークリクエストをトリガーするように入力に対してユーザーにリアルタイムのバリデーションを提供することができます。

Livewireのリアルタイムバリデーション

resources/views/livewire/form.blade.php
<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 コンポーネントのメソッドに制御が渡されます。

これによりページ全体を再読み込みせずに、動的にフォームの送信と応答を処理できます。

バリデーションロジックを追加する

フォームの各プロパティを定義します。

app/livewire/form.php
<?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');
    }
}

これで非同期でフォームの送信とエラーメッセージ、フラッシュメッセージの表示ができました。

Image from Gyazo

テストケースを作成する

フォームが正しく機能しているかどうかを確認するためにテストを作成します。

➜   php artisan make:livewire form --test

   INFO  Test [tests/Feature/Livewire/FormTest.php] created successfully.  

テストメソッドは /** @test */ アノテーションを使用して定義されます。

tests/livewire/form/FormTest.php
<?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テストの基本的な手順:

  1. テストクラスの作成: Tests\Feature\Livewire ディレクトリ内にLivewireコンポーネントに対応するテストクラスを作成します。

  2. Livewireコンポーネントのテスト: Livewire::test メソッドを使用してLivewireコンポーネントをテストモードで起動します。

  3. プロパティやメソッドのテスト: Livewireコンポーネントのプロパティやメソッドに対してテストを行います。

  4. アサーションの使用: assertSeeassertHasErrors などのアサーションメソッドを使用して、期待される結果を検証します。

メソッド 説明
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にリダイレクトされたことを確認します。

よく使うテストメソッド

Livewireテストドキュメント

Discussion