From 0d7ef4b5ef20c891e967ac0b53a9e77ae14097ef Mon Sep 17 00:00:00 2001 From: Kentaro Ohkouchi Date: Tue, 22 Mar 2022 18:08:03 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=AB=E3=83=BC=E3=83=88=E3=83=9A=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=20fixtur?= =?UTF-8?q?e=20=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97=E3=81=9F=E3=82=82?= =?UTF-8?q?=E3=81=AE=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 手続き型の処理だと、スキャン後にカートが空になってしまい、カート加算/減算のテストができないため --- e2e-tests/pages/cart.page.ts | 25 ++- e2e-tests/test/front_login/cart/cart.test.ts | 171 ++++++++----------- 2 files changed, 95 insertions(+), 101 deletions(-) diff --git a/e2e-tests/pages/cart.page.ts b/e2e-tests/pages/cart.page.ts index ff42977044..9bfe4fa5cf 100644 --- a/e2e-tests/pages/cart.page.ts +++ b/e2e-tests/pages/cart.page.ts @@ -3,18 +3,41 @@ import PlaywrightConfig from '../../playwright.config'; export class CartPage { readonly page: Page; + readonly url: string; + readonly nextButton: Locator; constructor(page: Page) { this.page = page; + this.url = `${PlaywrightConfig.use.baseURL}/cart/index.php`; this.nextButton = page.locator('input[name=confirm][alt=購入手続きへ]'); } async goto() { - await this.page.goto(`${PlaywrightConfig.use.baseURL}/cart/index.php`); + await this.page.goto(this.url); } async gotoNext() { await this.nextButton.click(); } + + getAdditionButton(row?: number) { + return this.page.locator(`table[summary=商品情報] >> tr >> nth=${row ?? 1} >> td >> nth=4 >> [alt="+"]`); + } + + getSubtructionButton(row?: number) { + return this.page.locator(`table[summary=商品情報] >> tr >> nth=${row ?? 1} >> td >> nth=4 >> [alt="-"]`); + } + + getQuantity(row?: number) { + return this.page.locator(`table[summary=商品情報] >> tr >> nth=${row ?? 1} >> td >> nth=4`); + } + + async addition(row?: number) { + await this.getAdditionButton(row).click(); + } + + async subtruction(row?: number) { + await this.getSubtructionButton(row).click(); + } } diff --git a/e2e-tests/test/front_login/cart/cart.test.ts b/e2e-tests/test/front_login/cart/cart.test.ts index ad5000b950..5f01e9fcfe 100644 --- a/e2e-tests/test/front_login/cart/cart.test.ts +++ b/e2e-tests/test/front_login/cart/cart.test.ts @@ -1,48 +1,30 @@ -import { test, expect, chromium, Page } from '@playwright/test'; +import { Page } from '@playwright/test'; import PlaywrightConfig from '../../../../playwright.config'; -import { ZapClient, Mode, ContextType, Risk, HttpMessage } from '../../../utils/ZapClient'; +import { ZapClient, ContextType, Risk } from '../../../utils/ZapClient'; import { intervalRepeater } from '../../../utils/Progress'; const zapClient = new ZapClient(); const url = `${PlaywrightConfig.use.baseURL}/cart/index.php`; +import { CartPage } from '../../../pages/cart.page'; + +// 商品をカートに入れて購入手続きへ進むフィクスチャ +import { test, expect } from '../../../fixtures/cartin.fixture'; test.describe.serial('カートページのテストをします', () => { - let page: Page; test.beforeAll(async () => { - await zapClient.setMode(Mode.Protect); - await zapClient.newSession('/zap/wrk/sessions/front_login_cart', true); - await zapClient.importContext(ContextType.FrontLogin); - - if (!await zapClient.isForcedUserModeEnabled()) { - await zapClient.setForcedUserModeEnabled(); - expect(await zapClient.isForcedUserModeEnabled()).toBeTruthy(); - } - const browser = await chromium.launch(); - page = await browser.newPage(); - await page.goto(url); - }); - - const detailURL = `${PlaywrightConfig.use.baseURL}/products/detail.php?product_id=1`; - test('商品詳細ページを表示します', async () => { - await page.goto(detailURL); - await expect(page.locator('#detailrightbloc > h2')).toContainText('アイスクリーム'); + await zapClient.startSession(ContextType.FrontLogin, 'front_login_cart'); }); - test('商品をカートに入れます', async () => { - await page.selectOption('select[name=classcategory_id1]', { label: '抹茶' }); - await page.selectOption('select[name=classcategory_id2]', { label: 'S' }); - await page.fill('input[name=quantity]', '2'); - await page.click('[alt=カゴに入れる]'); - }); - - test('カートの内容を確認します', async () => { + test('カートの内容を確認します', async ( { page } ) => { + const cartPage = new CartPage(page); + await cartPage.goto(); await expect(page.locator('h2.title')).toContainText('現在のカゴの中'); await expect(page.locator('table[summary=商品情報] >> tr >> nth=1')).toContainText('アイスクリーム'); }); test.describe('テストを実行します[GET] @attack', () => { let scanId: number; - test('アクティブスキャンを実行します', async () => { + test('アクティブスキャンを実行します', async ( { page } ) => { scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'GET'); await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000, page); }); @@ -53,30 +35,30 @@ test.describe.serial('カートページのテストをします', () => { }); }); - test('カートの数量を加算します', async () => { - await page.reload(); - const quantity = parseInt(await page.locator('table[summary=商品情報] >> tr >> nth=1 >> td >> nth=4').textContent()); - await page.click('table[summary=商品情報] >> tr >> nth=1 >> td >> nth=4 >> [alt="+"]'); - await expect(page.locator('table[summary=商品情報] >> tr >> nth=1 >> td >> nth=4')).toContainText(String(quantity + 1)); + const getMessage = async (page: Page, additionParams: string) => { + const result = await zapClient.getMessages(url, await zapClient.getNumberOfMessages(url) - 1, 1); + const message = result.pop(); + const transactionid = await page.locator('input[name=transactionid]').first().inputValue(); + const requestBody = message.requestBody.replace(/transactionid=[a-z0-9]+/, `transactionid=${transactionid}`); + await zapClient.sendRequest(`${message.requestHeader}${requestBody}${additionParams}`); + return await zapClient.getLastMessage(url); + }; + + test('カートの数量を加算します', async ( { page } ) => { + const cartPage = new CartPage(page); + await cartPage.goto(); + const quantity = parseInt(await cartPage.getQuantity().textContent()); + await cartPage.addition(); + await expect(cartPage.getQuantity()).toContainText(String(quantity + 1)); }); test.describe('数量加算のテストを実行します[POST] @attack', () => { - - let message: HttpMessage; - let requestBody: string; - test('履歴を取得します', async () => { - const result = await zapClient.getMessages(url, await zapClient.getNumberOfMessages(url) - 1, 1); - message = result.pop(); - expect(message.requestBody).toContain('mode=up'); - }); - test('transactionid を取得し直します', async () => { - await page.goto(url); - const transactionid = await page.locator('input[name=transactionid]').first().inputValue(); - requestBody = message.requestBody.replace(/transactionid=[a-z0-9]+/, `transactionid=${transactionid}`); - }); - let scanId: number; - test('アクティブスキャンを実行します', async () => { + test('アクティブスキャンを実行します', async ( { page } ) => { + const cartPage = new CartPage(page); + await cartPage.goto(); + await cartPage.addition(); + const requestBody = await getMessage(page, '&mode_up=dummy').then(httpMessage => httpMessage.requestBody); expect(requestBody).toContain('mode=up'); scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'POST', requestBody); await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000, page); @@ -88,35 +70,50 @@ test.describe.serial('カートページのテストをします', () => { }); }); - test('カートの数量を減算します', async () => { - await page.reload(); - const quantity = parseInt(await page.locator('table[summary=商品情報] >> tr >> nth=1 >> td >> nth=4').textContent()); - await page.click('table[summary=商品情報] >> tr >> nth=1 >> td >> nth=4 >> [alt="-"]'); - await expect(page.locator('table[summary=商品情報] >> tr >> nth=1 >> td >> nth=4')).toContainText(String(quantity - 1)); + test('カートの数量を減算します', async ( { page } ) => { + const cartPage = new CartPage(page); + await cartPage.goto(); + const quantity = parseInt(await cartPage.getQuantity().textContent()); + await cartPage.subtruction(); + await expect(cartPage.getQuantity()).toContainText(String(quantity - 1)); }); test.describe('数量減算のテストを実行します[POST] @attack', () => { - - let message: HttpMessage; - let requestBody: string; - test('履歴を取得します', async () => { - const result = await zapClient.getMessages(url, await zapClient.getNumberOfMessages(url) - 1, 1); - message = result.pop(); - }); - test('transactionid を取得し直します', async () => { - await page.goto(url); - const transactionid = await page.locator('input[name=transactionid]').first().inputValue(); - requestBody = message.requestBody.replace(/transactionid=[a-z0-9]+/, `transactionid=${transactionid}`); - }); - let manuallyMessage: HttpMessage; - test('数量減算の requestBody に書き換えて手動送信します', async () => { - requestBody = requestBody.replace(/mode=down/, 'mode=down&mode_down=dummy'); - await zapClient.sendRequest(message.requestHeader + requestBody); - manuallyMessage = await zapClient.getLastMessage(url); - }); let scanId: number; - test('アクティブスキャンを実行します', async () => { - expect(manuallyMessage.requestBody).toContain('mode=down'); + test('アクティブスキャンを実行します', async ( { page } ) => { + const cartPage = new CartPage(page); + await cartPage.goto(); + const transactionid = await page.locator('input[name=transactionid]').first().inputValue(); + // JavaScript でカートの数量を増やしておく + await page.evaluate(async (transactionid: string) => { + await (async () => { + const searchParams = data => { + const params = new URLSearchParams(); + Object.keys(data).forEach(key => params.append(key, data[key])); + return params; + }; + const response = await fetch('/cart/index.php', { + method: 'POST', + cache: 'no-cache', + headers: { + 'ContentType': 'application/x-www-form-urlencoded' + }, + body: searchParams({ + transactionid: transactionid, + mode: 'setQuantity', + quantity: '1000', + cart_no: '1', + cartKey: '1' + }) + }); + + return response.body + })(); + }, transactionid); + + await cartPage.subtruction(); + const requestBody = await getMessage(page, '&mode_down=dummy').then(httpMessage => httpMessage.requestBody); + expect(requestBody).toContain('mode=down'); scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'POST', requestBody); await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000, page); }); @@ -126,30 +123,4 @@ test.describe.serial('カートページのテストをします', () => { .then(alerts => expect(alerts).toEqual([])); }); }); - - test('購入手続きへ進みます', async () => { - await page.goto(url); - await page.click('input[name=confirm][alt=購入手続きへ]'); - await expect(page.locator('h2.title')).toContainText('お届け先の指定'); - }); - - test.describe('購入手続きへ進むテストを実行します[POST] @attack', () => { - let message: HttpMessage; - test('履歴を取得します', async () => { - message = await zapClient.getLastMessage(url); - expect(message.requestHeader).toContain(`POST ${url}`); - expect(message.responseHeader).toContain('HTTP/1.1 302 Found'); - }); - - let scanId: number; - test('アクティブスキャンを実行します', async () => { - scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'POST', message.requestBody); - await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000, page); - }); - - test('結果を確認します', async () => { - await zapClient.getAlerts(url, 0, 1, Risk.High) - .then(alerts => expect(alerts).toEqual([])); - }); - }); });