2024-10-03
筆者が苦戦したE2Eテストコードを記録として残す。
特に、fixtureを使ったDBへのレコード作成!!ファイル同士の関連性が分からな過ぎた (´;ω;`)
前提条件
- ECCUBE がローカルに保存されている事
コード全体
(1) 【spec】E2Eテストコード
《場所》
e2e-tests/spec/admin/tenant/individual_settings.spec.ts
《test関数説明》
個別設定:個別設定ページで値を入力し保存・反映がされるか確認
定休日カレンダー設定_新規作成:定休日が新規作成できるかどうか確認
定休日カレンダー設定_複数行_ページ遷移確認:定休日レコードが複数ある場合のページネーション確認
import {test} from "../../../fixtures/admin_login.fixture";
import {AdminShopIndividualSettingsPage} from "../../../pages/admin/tenant/individual_settings.page";
test('個別設定',
{tag: ["@tenant_owner_a"]},
async ({loginPage,page}) => {
const ShopIndividualSettingsPage = new AdminShopIndividualSettingsPage(page);
// ログイン確認
await loginPage.seeAfterLoginSuccess();
// 店舗設定を開く
await ShopIndividualSettingsPage.gotoIndividualSetting();
// タブタイトルの存在確認
await ShopIndividualSettingsPage.seeTabTitle();
// 値入力
await ShopIndividualSettingsPage.fillIndividualSetting(
{
businessHours: 'サンプル営業時間',
postage: '123456789',
taxSet: '999999999'
}
);
// 保存
await ShopIndividualSettingsPage.clickRegisterButton();
// 反映確認
await ShopIndividualSettingsPage.seeInputIndividualSetting();
// 値入力
await ShopIndividualSettingsPage.fillIndividualSetting(
{
businessHours: '',
postage: '',
taxSet: ''
}
);
// 保存
await ShopIndividualSettingsPage.clickRegisterButton();
// 反映確認
await ShopIndividualSettingsPage.seeDeleteIndividualSetting();
await ShopIndividualSettingsPage.seeSavedMessage();
}
);
test('定休日カレンダー設定_新規作成',
{tag: ["@tenant_owner_a"]},
async ({loginPage,page}) => {
const ShopIndividualSettingsPage = new AdminShopIndividualSettingsPage(page);
// ログイン確認
await loginPage.seeAfterLoginSuccess();
// 店舗設定を開く
await ShopIndividualSettingsPage.gotoIndividualSetting();
// 値入力
await ShopIndividualSettingsPage.fillCalendarHoliday(
{
calendarTitle: '定休日はありません_新規作成',
calendarHoliday: '2024-10-07'
}
);
// 保存
await ShopIndividualSettingsPage.clickCreateButton();
await ShopIndividualSettingsPage.clickRegisterButton();
// 反映確認
await ShopIndividualSettingsPage.seeInputHolidayCalendar();
}
);
test('定休日カレンダー設定_複数行_ページ遷移確認',
{tag: ["@tenant_owner_a"]},
async ({loginPage,page}) => {
const ShopIndividualSettingsPage = new AdminShopIndividualSettingsPage(page);
// ログイン確認
await loginPage.seeAfterLoginSuccess();
// 店舗設定を開く
await ShopIndividualSettingsPage.gotoIndividualSetting();
// 11行のカレンダー作成
await ShopIndividualSettingsPage.createCalendar(10);
// 次へボタン押下
await ShopIndividualSettingsPage.clickNextPageButton();
// 画面遷移されているか確認
await ShopIndividualSettingsPage.seePrevPageButton();
}
);
(2) 【page】(1)で使うクラス・関数まとめ
《場所》
e2e-tests/pages/admin/tenant/individual_settings.page.ts
import {expect, Locator, Page} from "@playwright/test";
import {ECCUBE_ADMIN_ROUTE} from "../../../config/default.config";
import {createCalendar} from "../../../fixtures/admin/tenant/individual_settings.fixture";
export class AdminShopIndividualSettingsPage {
readonly page: Page;
readonly url: string;
readonly businessHours: Locator; // 店舗情報
readonly postage: Locator; // 送料
readonly taxSet: Locator; // 税設定
readonly registerButton: Locator; // 登録
readonly createButton: Locator; // 新規作成
readonly calendarTitle: Locator; // 入力:カレンダータイトル
readonly calendarHoliday: Locator; // 入力:定休日
readonly confCalenderTitle: Locator; // 確認:カレンダータイトル
readonly calenderRow01: Locator; // 登録カレンダー1行目
readonly nextPage: Locator; // 次へ
readonly prevPage: Locator; // 前へ
constructor(page: Page) {
this.page = page;
this.url = `${ECCUBE_ADMIN_ROUTE}/tenant/tradelaw`;
this.businessHours = page.locator('#shop_master_business_hour');
this.postage = page.locator('#shop_master_delivery_free_amount');
this.taxSet = page.locator('#shop_master_invoice_registration_number');
this.calendarTitle = page.locator('#calendar_item_new #calendar_title');
this.calendarHoliday = page.locator('#calendar_item_new #calendar_holiday');
this.nextPage = page.locator('.pagination .page-item:has-text("次へ")');
this.prevPage = page.locator('.pagination .page-item:has-text("前へ")');
this.registerButton = page.getByRole('button', {name: '登録'});
this.createButton = page.getByRole('button', {name: '新規作成'});
this.calenderRow01 = page.locator('.card-body .table tbody tr').nth(1);
}
// 対象URLへ遷移
async goto() {
await this.page.goto(this.url);
}
// メニュー操作
async gotoIndividualSetting() {
await this.page.getByRole('link', {name: '店舗設定'}).click();
await this.page.getByRole('link', {name: '個別設定'}).click();
}
// タブタイトルの存在確認
async seeTabTitle() {
await expect(this.page).toHaveTitle('店舗設定 個別設定 - EC-CUBE SHOP_tenant_1');
}
// 値入力:
// 定休日以外の設定
async fillIndividualSetting(individualSetting: {
businessHours: string,
postage: string,
taxSet: string,
}){
await this.businessHours.fill(individualSetting.businessHours);
await this.postage.fill(individualSetting.postage);
await this.taxSet.fill(individualSetting.taxSet);
}
// 定休日設定
async fillCalendarHoliday(calendarHolidaySetting: {
calendarTitle: string,
calendarHoliday: string,
}){
await this.calendarTitle.fill(calendarHolidaySetting.calendarTitle);
await this.calendarHoliday.fill(calendarHolidaySetting.calendarHoliday);
}
// 反映確認:
// 入力判定
async seeInputIndividualSetting() {
await expect(this.businessHours).toHaveValue('サンプル営業時間');
await expect(this.postage).toHaveValue('123,456,789');
await expect(this.taxSet).toHaveValue('999999999');
}
async seeInputHolidayCalendar() {
await expect(this.calenderRow01).toContainText('定休日はありません_新規作成');
await expect(this.calenderRow01).toContainText('2024/10/07');
}
// 削除判定
async seeDeleteIndividualSetting() {
await expect(this.businessHours).toHaveValue('');
await expect(this.postage).toHaveValue('');
await expect(this.taxSet).toHaveValue('');
}
// async seeDeleteHolidayCalendar() {
// await expect(this.businessHours).toHaveValue('');
// await expect(this.postage).toHaveValue('');
// }
// 登録ボタン押下
async clickRegisterButton() {
await this.registerButton.click();
}
// 新規作成ボタン押下
async clickCreateButton() {
await this.createButton.click();
}
// 登録ボタンの表示確認
async seeRegisterButton() {
await expect(this.registerButton).toBeVisible();
}
// 次へボタン押下
async clickNextPageButton() {
await this.nextPage.click();
}
// 前へボタン押下
async seePrevPageButton() {
await expect(this.prevPage).toBeVisible();
}
// 登録完了メッセージ
async seeSavedMessage() {
await expect(this.page.locator('.alert-success')).toContainText('保存しました');
}
// 定休日レコード作成
async createCalendar(
record: number,
) {
for (let i = 0; i < record; i++) {
await createCalendar();
}
}
}
(3) 【type】ECCUBEから返ってきてほしいリスポンスの期待型
《場所》
e2e-tests/types/calendar.type.ts
export type Calendar = {
"id": number,
"title": string,
"holiday": string,
"create_date": string,
"update_date": string,
"baseInfo": {
"id": number
}
}
(4)【fixtures】APIを使用
《場所》
e2e-tests/fixtures/admin/tenant/individual_settings.fixture.ts
import {request} from "@playwright/test";
import {Calendar} from "../../../types/calendar.type";
/**
* 定休日カレンダーのレコード作成
*/
// Promise<typeファイル->type名>
export const createCalendar = async (): Promise<Calendar> => {
// 新規HTTPリクエストする
const context = await request.newContext();
// GETでURLにアクセスー>リスポンスを返却
// APIクッキーの作成
await context.get(`/fixture/get_mall_role`);
// ECCUBE側(FixtureController.php)の指定ルートにPOST依頼をかけている
// 処理結果を変数に格納
const CalendarResponse = await context.post('/fixture/calendar/generate_calendar');
// 結果をJSONに変換
return await CalendarResponse.json();
}
(5) 【generator】DBの操作
《場所》
tests/Eccube/Tests/Fixture/Generator.php
/**
* Calendar オプジェクトを生成して返す.
* @return Calendar
*/
public function createCalendar()
{
// 新規カレンダーオブジェクトを作成
$Calendar = new Calendar();
// カレンダーを登録したい店舗を変数に格納
$tenant_a = 2;
$tenant = $this->entityManager->getRepository(BaseInfo::class)->find($tenant_a);
// レコードに値を設定し保存
$title = '年中無休で営業しております';
$Calendar
->setBaseInfo($tenant)
->setTitle($title)
->setHoliday(new \DateTime())
->setCreateDate(new \DateTime())
->setUpdateDate(new \DateTime());
$this->entityManager->persist($Calendar);
$this->entityManager->flush();
// 登録結果を返す
return $Calendar;
}
(6) 【fixture】ECCUBE側でHTTPリクエストの受け取り + レコード作成
/**
* 定休日カレンダーの作成
*/
// ルート名は任意
#[Route(
'/calendar/generate_calendar',
name: 'generate_calendar',
methods: ['POST'],
)]
public function generateCalendarWithClass(Request $request, bool $baseOrderOnly = true): Response
{
// カレンダーレコードを作成。
$Calendar = $this->generator->createCalendar();
// createCalendar()の実行結果をjsonファイルとして返す。
return new Response(
$Calendar->toJSON(),
Response::HTTP_CREATED,
['Content-Type' => 'application/json']
);
}
関連サイト
【ECCUBE】【Playwrite】fixtrueを使ってDBにレコードを追加する方法