Livewireでのファイルダウンロードテスト
Livewireを使ったファイルダウンロード処理のテストを書く際、一癖あったためまとめる
テスト対象のコンポーネント
downloadメソッドが呼ばれたら、csvファイルをダウンロードする
サンプルコード
code:CsvDownload.php
class CsvDownload extends Component
{
public function render(): View
{
return view('livewire.download')
}
public function download(): StreamResponse
{
$filename = 'users_' . date('Y-m-d_H-i-s') . '.csv';
$data = [
];
return Response::streamDownload(
function() use ($headerColumns, $data) {
$stream = fopen('php://temp', 'w');
fputcsv($stream, $headerColumns);
foreach($data as $row) {
fputcsv($stream, $row);
}
fclose($stream);
},
$filename,
)
}
}
テストコード
Livewireでは、ファイルダウンロード時にファイルコンテンツをbase64にエンコードしてフロントエンドに渡し、クライアント側でデコードしバイナリに変換してダウンロードするようにしている
ajaxでダウンロード処理をする際は、上記のようなフローになるっぽい
また、クライアントで実行されるダウンロード処理・データや、画面更新などの副作用処理・データはLivewire Componentのレスポンスに含まれているeffects プロパティ内に含まれている
画面を非同期更新する際は、Livewireがいい感じにupdateエンドポイントを叩いて、そのレスポンスに含まれているeffectsの値を使って画面を更新している
https://scrapbox.io/files/6846de11dd56a34dfe0b99f2.png
なのでLivewire::testで`ファイルダウンロードのテストをする際も、上記のことを把握しておかないと、あれ?ダウンロード対象のコンテンツがないぞ?となる、、
サンプルコード
code:CsvDownloadTest.php
class CsvDownloadTest extends TestCase
{
public function test_download(): void
{
$response = Livewire::test(CsvDownload::class)
->call('download');
// ダウンロードコンテンツを取得
// ファイルコンテンツはbase64化されていることに注意
// デコードして下のデータに変換
$content = base64_decode($base64Content);
$actualRows = expload("\n", $content)
$this->assertSame('ID,名前,メールアドレス', $actualRows0); }
}
補足
base64化している該当コード