Laravel & Inertiaのテストでresource/js以外をテスト対象にする方法

2023/03/27に公開

背景

LaravelとInertia.jsでSPAを作成しています。
ユーザー画面と管理画面でディレクトリを分けています。

ユーザー画面

resources/js/Pages配下にページを作成しています。

  • resources/js/Pages/User/Show.vueを作成済

コントローラー

use Inertia\Inertia;

class UserController extends Controller
{
    public function show(User $user)
    {
        return Inertia::render('User/Show', [
          'user' => $user
        ]);
    }
}

ルーティング

Route::get('/show', [UserController::class, 'show'])->name('show');

管理画面

resources/js-admin/Pages配下にページを作成しています。

  • resources/js-admin/Pages/Admin/Show.vueを作成済

コントローラー

use Inertia\Inertia;

class AdminController extends Controller
{
    public function show(User $admin)
    {
        return Inertia::render('Admin/Show', [
          'admin' => $admin
        ]);
    }
}

ルーティング

Route::get('/admin/show', [AdminController::class, 'show'])->name('admin.show');

テストを書いていく

テストには、Pestを利用しています。

ユーザー画面

test('ログインユーザーの場合、ユーザー画面に遷移できること', function () {
    // ユーザー作成
    $user = User::factory()->create();
        // 作成したユーザーをログインさせて、UserControllerのshowメソッド呼び出し
    $response = $this->actingAs($user)->get(route('show'));

    $response->assertOk();
    $response->assertInertia(function (Assert $assert) {
        $assert->component('User/Show');
    });
});

上記のテストを実行すると問題なく成功します。

管理画面

では、以下の管理画面のテストは成功するでしょうか?

test('管理者の場合、管理画面に遷移できること', function () {
    // 管理者作成
    $superAdmin = User::factory()->superAdmin()->create();
        // 作成した管理者をログインさせて、AdminControllerのshowメソッド呼び出し
    $response = $this->actingAs($superAdmin)->get(route('admin.show'));

    $response->assertOk();
    $response->assertInertia(function (Assert $assert) {
        $assert->component('Admin/Show');
    });
});

↑このテストは失敗します。

Inertia page component file [Admin/Show] does not exist.

テスト失敗の原因

なぜ同じようなテストを書いても、前者は成功し、後者は失敗するのでしょうか?

その原因は、Inertiaのconfigにありました。
vendor/inertiajs/inertia-laravel/config/inertia.phpを見てみましょう。

<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Server Side Rendering
    |--------------------------------------------------------------------------
    |
    | These options configures if and how Inertia uses Server Side Rendering
    | to pre-render the initial visits made to your application's pages.
    |
    | Do note that enabling these options will NOT automatically make SSR work,
    | as a separate rendering service needs to be available. To learn more,
    | please visit https://inertiajs.com/server-side-rendering
    |
    */

    'ssr' => [
        'enabled' => false,
        'url' => 'http://127.0.0.1:13714/render',
    ],

    /*
    |--------------------------------------------------------------------------
    | Testing
    |--------------------------------------------------------------------------
    |
    | The values described here are used to locate Inertia components on the
    | filesystem. For instance, when using `assertInertia`, the assertion
    | attempts to locate the component as a file relative to any of the
    | paths AND with any of the extensions specified here.
    |
    */

    'testing' => [
        'ensure_pages_exist' => true,
        'page_paths' => [
            resource_path('js/Pages'),
        ],
        'page_extensions' => [

            'js',
            'jsx',
            'svelte',
            'ts',
            'tsx',
            'vue',
        ],
    ],
];

重要なのは、以下の部分です。

'testing' => [
       // 'ensure_pages_exist' => true,
        'page_paths' => [
            resource_path('js/Pages'),
        ],
        //'page_extensions' => [
        //
        //  'js',
        //  'jsx',
        //  'svelte',
        //  'ts',
        //  'tsx',
        //  'vue',
       // ],
    ],

そうです。テスト実行時にデフォルトで読み込まれるパスは、resources/js/Pagesのみなのです。
管理画面のページを管理しているディレクトリは、どこか思い出してみましょう。。

...

...

resources/js-admin/Pages !?

そうなんです。resources/js-admin/Pagesなんです。
本来だと、resoruces/js-admin/Pages/Admin/Show.vueを探して欲しいところを、Inertia君はresources/js/Pages/Admin/Show.vueを探していました。
これが原因です。

解決策

この問題の解決策は非常にシンプルです。
テスト中だけ一時的にpage_pathsを書き換えてやれば、OKです。

テストに下記のように1行追加してください。

test('管理者の場合、管理画面に遷移できること', function () {
    // パス書き換え
+    Config::set('inertia.testing.page_paths',[resource_path('js-admin/Pages')]);
    
    // 管理者作成
    $superAdmin = User::factory()->superAdmin()->create();
        // 作成した管理者をログインさせて、AdminControllerのshowメソッド呼び出し
    $response = $this->actingAs($superAdmin)->get(route('admin.show'));

    $response->assertOk();
    $response->assertInertia(function (Assert $assert) {
        $assert->component('Admin/Show');
    });
});

Config::set('inertia.testing.page_paths',[resource_path('js-admin/Pages')]);

↑この記述をすることで、resources/js-admin/Pages配下のAdmin/Show.vueを検索してくれるようになります。
そして、テストも成功します。

めでたし、めでたし。

Discussion