前回の画面表示テストに続き、今回もLaravelユーザー認証のテストです。正しいEメールとパスワードでログインが成功するケースと、間違ったパスワードでログインしログインに失敗する2つのケースについて、テストを作成します。

エラーメッセージの日本語化

前回、Laravelと認証機能のBreezeをインストールした直後の環境でテストを作成しました。後でご紹介するログイン失敗のケースではエラーメッセージも含めてアサートしたいので、まずは日本語化の設定から進めてゆきます。

Githubで公開されているBreezejpという日本語化パッケージを使わせていただきます。名前にBreezeとついていますがJetstreamLaravel UIなどの環境でも使用可能とのこと。適用方法もとても簡単で、以下の2つのコマンドを実行するだけです。

まず、composerでパッケージをインストールします。

$ composer require askdkc/breezejp --dev

次に以下のコマンドを実行。

$ php artisan breezejp
Laravel Breeze用に日本語翻訳ファイルを準備します
config/app.phpのlocaleをjaにします

 GitHubリポジトリにスターの御協力をお願いします🙏 (yes/no) [yes]:
 > yes

Thank you! / ありがとう💓
日本語ファイルのインストールが完了しました!

これでプロジェクト直下にlangディレクトリと、日本語用ファイルが作成できました。また出力内容からも分かるように、言語ファイルの設置だけでなくconfig/app.phplocalejaに変更してくれています。

これで日本語化の設定は完了です。

ここまででBreezeと、Breezejpの2つが出てきました。名前が似ていて少しややこしいのですが、前者は認証機能を簡単に実装できるパッケージで(前回の記事でインストールしました)、後者は今回インストールした日本語化のパッケージになります。

テスト用Userデータ

次に、テストに必要なダミーユーザーを作成するためのFactoryについてです。Laravelデフォルトですでに用意されているので、内容を確認してみます。

...
class UserFactory extends Factory
{
    protected static ?string $password;

    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => static::$password ??= Hash::make('password'),
            'remember_token' => Str::random(10),
        ];
    }
...

パスワードには、”password”という文字をハッシュ化した値が保存されるようになっているようですね。

ログイン成功のテスト

準備ができたので、テストをしてゆきましょう。まずはログイン成功のテストです。前回と同じくBreezeが用意してくれているユニットテストを使用しますが、アサートを少し追加しています。

    public function test_users_can_authenticate_using_the_login_screen(): void
    {
        $user = User::factory()->create();

        $this->assertGuest(); //未ログイン状態であることをチェック

        $response = $this->post('/login', [
            'email' => $user->email,
            'password' => 'password',
        ]);

        $this->assertAuthenticated(); //ログインが成功したことをチェック

        $response->assertRedirect(RouteServiceProvider::HOME);
    }

このテストでは、Laravelが用意してくれているログイン認証のための便利なアサーションを2つ使用しています。assertGuest()は、ユーザーが未ログインであること、またassertAuthenticated()は、ユーザーが認証済みであることをアサートしています。ログイン前後の認証状態を効率的にチェックできてとても便利ですね。

この2つの関数は通常、guardを引数として受け取ります。上記のテストでは引数を省略していますが、その場合にはconfig/auth.phpdefaultsセクションで定義されているwebガードがデフォルトとして使用されます。

では以下のように、guardsの定義にwebだけでなくadminも定義されている場合はどうでしょうか。

・・・
    'defaults' => [
        'guard'         => 'web',
        'passwords' => 'users',
    ],
・・・
    'guards' => [
        'web' => [
            'driver'   => 'session',
            'provider' => 'users',
        ],
        'admin' => [
            'driver'   => 'session',
            'provider' => 'admin',
        ],
    ],
・・・

adminガードに対して認証確認を行いたい場合は、以下のように引数にadminを渡します。環境に併せて適宜ご変更ください。

         $this->assertGuest('admin'); 
        $this->assertAuthenticated('admin');

ログイン失敗のテスト

次はログインに失敗する場合のテストです。正しいパスワードは先ほどのFactoryで設定されている通り”password”ですが、失敗するために”wrong-password“でログインしてみます。

    public function test_users_can_not_authenticate_with_invalid_password(): void
    {
        $user = User::factory()->create();

        $this->assertGuest(); //未ログイン状態であることをチェック

        $response = $this->post('/login', [
            'email' => $user->email,
            'password' => 'wrong-password',
        ]);

        $response->assertSessionHasErrors([
            'email' => 'ログイン情報が存在しません。'
        ]);

        $this->assertGuest();
    }

エラーメッセージは先ほど日本語化したため、正しく設定されていれば日本語のメッセージが返るはずです。

では、ログイン成功・失敗のテストを実行してみましょう。

$ php artisan test --filter=AuthenticationTest

   PASS  Tests\Feature\Auth\AuthenticationTest
  ✓ users can authenticate using the login screen                                              0.58s  
  ✓ users can not authenticate with invalid password                                           0.27s  

  Tests:    2 passed (8 assertions)
  Duration: 1.04s

テストが成功しました!

次回は、ログアウト関連のテストをご紹介します。

By hmatsu