どうもこんにちは。
今回は、Playwrightを使用したE2Eテストを作成している中で添付ファイルのアップロード部分の実装でつまづいたので共有します。
ドロップゾーンのHTML
アプリケーションのドロップゾーンは以下のようなHTMLで実装されています。
JSのDropzoneライブラリが使用されています。
<div class="dropzone dz-clickable" id="sample_file_uploader">
<div class="dz-default dz-message">
<button class="dz-button" type="button">
<i class="fa fa-file-o fa-2x"></i>
<br>
<br>
ファイルをここにドロップするか<br>
ここをクリックして下さい
</button>
</div>
</div>
E2Eテスト側の実装
E2EテストはTypeScriptで実装しています。
メインで実行するmain.spec.tsと各機能ごとの処理が記載されているヘルパーファイルに分けています。
以下が実装コードです。
main.spec.ts
import { test } from '@playwright/test';
import { login } from './helpers/auth';
import { exec_sample } from './helpers/sample';
test('管理者ユーザでログインした場合', async ({ page }) => {
// ... 変数の定義などは省略 ...
// ログイン
await login(page, url, user_name, password);
// 機能ごとの処理を呼び出し
await exec_sample(page, sample_name);
}
sample.ts
import { Page, expect } from '@playwright/test';
import * as path from 'path';
export async function exec_sample(page: Page, sample_name: string) {
// サンプル一覧画面へ遷移
await page.getByRole('link', { name: 'サンプル' }).click();
await page.waitForURL('**/samples');
console.log('・・・サンプル一覧画面表示OK');
// 新規登録画面へ遷移
await page.getByRole('link', { name: '新規登録' }).click();
await expect(page.locator('h1 small', { hasText: '新規登録' })).toBeVisible();
console.log('・・・サンプル新規登録画面表示OK');
// 名称の項目のテキストボックスにデータを入力
await page.getByRole('textbox', { name: '名称' }).click();
await page.getByRole('textbox', { name: '名称' }).fill(sample_name);
// ファイルをアップロード
const fileChooserPromise = page.waitForEvent('filechooser');
await page.locator('#sample_file_uploader').click();
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(path.join(__dirname, '../images/sample_logo.png'));
// ファイルがアップロードされるのを待つ
await page.locator('#screen_structure_file_uploader .dz-preview.dz-success.dz-complete').waitFor({ state: 'visible', timeout: 10000 });
console.log('・・・ファイルアップロード完了');
// 登録を実行
await page.getByRole('button', { name: '登録' }).click();
await expect(page.locator('h1 small', { hasText: '閲覧' })).toBeVisible();
console.log('・・・画面構成新規登録OK');
}
解説
ファイルのアップロードには、filechooserというハンドラを使用しています。
また、アップロードする画像ファイルは予め任意のディレクトリに保管しておく必要があります。
流れ
流れとしては以下です。
-
testsディレクトリの中にimagesディレクトリを作成する -
imagesディレクトリの中に、アップロードしたい画像ファイルを保存する - 以下のコードを書く
// 1. `filechooser`イベントを待機するPromiseを作成
const fileChooserPromise = page.waitForEvent('filechooser');
// 2. ファイルアップロード要素をクリックしてファイル選択ダイアログをトリガー
await page.locator('#sample_file_uploader').click();
// 3. `filechooser`イベントが発火するまで待機し、FileChooserオブジェクトを取得
const fileChooser = await fileChooserPromise;
// 4. 選択するファイルをセットする
await fileChooser.setFiles(path.join(__dirname, '../images/sample_logo.png'));
// ファイルがアップロードされるのを待つ
await page.locator('#sample_file_uploader .dz-preview.dz-success.dz-complete').waitFor({ state: 'visible', timeout: 10000 });
console.log('・・・ファイルアップロード完了');
ファイルのアップロードに時間のかかるように実装されている場合、waitForで待機する必要があります。
待機しないと、アップロードが完了しないまま登録ボタンをクリックすることになってしまうので注意です。
以上