Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shopping/payment.php のテストを追加 #532

Merged
merged 13 commits into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/penetration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ jobs:
- 'test/front_login/contact.test.ts'
- 'test/front_login/cart/cart.test.ts'
- 'test/front_login/cart/cart_delete.test.ts'
- 'test/front_login/shopping/shopping_deliv.test.ts'
- 'test/front_login/shopping/shopping_payment.test.ts'

steps:
- name: Checkout
Expand Down
19 changes: 19 additions & 0 deletions e2e-tests/fixtures/cartin.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { test as base } from '@playwright/test';
import PlaywrightConfig from '../../playwright.config';
import { ProductsDetailPage } from '../pages/products/detail.page';
import { CartPage } from '../pages/cart.page';

/** 商品をカートに入れて購入手続きへ進むフィクスチャ. */
export const test = base.extend({
page: async ({ page }, use) => {
await page.goto(PlaywrightConfig.use.baseURL); // トップへ遷移しないと、スキャン後にカートが空になってしまう
const productsDetailPage = new ProductsDetailPage(page);
await productsDetailPage.goto(1);
await productsDetailPage.cartIn(2, '抹茶', 'S');
const cartPage = new CartPage(page);
await cartPage.gotoNext();
use(page);
}
});

export { expect } from '@playwright/test';
11 changes: 11 additions & 0 deletions e2e-tests/fixtures/shopping_deliv.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { test as base } from './cartin.fixture';
import PlaywrightConfig from '../../playwright.config';

export const test = base.extend({
page: async ({ page }, use) => {
await page.click('input[alt=選択したお届け先に送る]');
use(page);
}
});

export { expect } from '@playwright/test';
20 changes: 20 additions & 0 deletions e2e-tests/pages/cart.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Locator, Page } from '@playwright/test';
import PlaywrightConfig from '../../playwright.config';

export class CartPage {
readonly page: Page;
readonly nextButton: Locator;

constructor(page: Page) {
this.page = page;
this.nextButton = page.locator('input[name=confirm][alt=購入手続きへ]');
}

async goto() {
await this.page.goto(`${PlaywrightConfig.use.baseURL}/cart/index.php`);
}

async gotoNext() {
await this.nextButton.click();
}
}
33 changes: 33 additions & 0 deletions e2e-tests/pages/products/detail.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Locator, Page } from '@playwright/test';
import PlaywrightConfig from '../../../playwright.config';

export class ProductsDetailPage {
readonly page: Page;
readonly classCategoryId1: Locator;
readonly classCategoryId2: Locator;
readonly quantity: Locator;
readonly cartInButton: Locator;

constructor(page: Page) {
this.page = page;
this.classCategoryId1 = page.locator('select[name=classcategory_id1]');
this.classCategoryId2 = page.locator('select[name=classcategory_id2]');
this.quantity = page.locator('input[name=quantity]');
this.cartInButton = page.locator('[alt=カゴに入れる]');
}

async goto(productId: number) {
await this.page.goto(`${PlaywrightConfig.use.baseURL}/products/detail.php?product_id=${productId}`);
}

async cartIn(quantity?: number, classCategory1?: string, classCategory2?: string) {
await this.quantity.fill(String(quantity ?? 1));
if (classCategory1 !== undefined) {
await this.classCategoryId1.selectOption({ label: classCategory1 });
if (classCategory2 !== undefined) {
await this.classCategoryId2.selectOption({ label: classCategory2 });
}
}
await this.cartInButton.click();
}
}
64 changes: 64 additions & 0 deletions e2e-tests/test/front_login/shopping/shopping_deliv.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import PlaywrightConfig from '../../../../playwright.config';
import { ZapClient, ContextType, Risk, HttpMessage } from '../../../utils/ZapClient';
import { intervalRepeater } from '../../../utils/Progress';
const zapClient = new ZapClient();

const url = `${PlaywrightConfig.use.baseURL}/shopping/deliv.php`;

// 商品をカートに入れて購入手続きへ進むフィクスチャ
import { test, expect } from '../../../fixtures/cartin.fixture';

test.describe.serial('お届け先指定画面のテストをします', () => {
test.beforeAll(async () => {
await zapClient.startSession(ContextType.FrontLogin, 'front_login_shopping_deliv')
.then(async () => expect(await zapClient.isForcedUserModeEnabled()).toBeTruthy());
});

test('お届け先指定画面へ遷移します', async ( { page }) => {
await page.goto(url); // url を履歴に登録しておく
await expect(page.locator('h2.title')).toContainText('お届け先の指定');
});

test.describe('テストを実行します[GET] @attack', () => {
let scanId: number;
test('アクティブスキャンを実行します', async ( { page } ) => {
scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'GET');
await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000, page);
});

test('結果を確認します', async () => {
await zapClient.getAlerts(url, 0, 1, Risk.High)
.then(alerts => expect(alerts).toEqual([]));
});
});

test('お支払方法・お届け時間等の指定画面へ遷移します', async ( { page } ) => {
await page.click('input[alt=選択したお届け先に送る]');
await expect(page.locator('h2.title')).toContainText('お支払方法・お届け時間等の指定');
});

test.describe('お支払方法・お届け時間等の指定へ進むテストを実行します[POST] @attack', () => {
let scanId: number;
test('アクティブスキャンを実行します', async ( { page } ) => {
await page.click('input[alt=選択したお届け先に送る]');
const message = await zapClient.getLastMessage(url);
expect(message.requestHeader).toContain(`POST ${url}`);
expect(message.responseHeader).toContain('HTTP/1.1 302 Found');

const getMessage = async () => {
// transactionid を取得し直して置換します
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}&mode_dummy=dummy`);
return await zapClient.getLastMessage(url);
};
scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'POST', await getMessage().then(httpMessage => httpMessage.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([]));
});
});
});
75 changes: 75 additions & 0 deletions e2e-tests/test/front_login/shopping/shopping_payment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Page } from '@playwright/test';
import PlaywrightConfig from '../../../../playwright.config';
import { ShoppingPaymentPage } from '../../../pages/shopping/payment.page';
import { ZapClient, ContextType, Risk } from '../../../utils/ZapClient';
import { intervalRepeater } from '../../../utils/Progress';
const zapClient = new ZapClient();

const url = `${PlaywrightConfig.use.baseURL}/shopping/payment.php`;

// お支払い方法・お届け時間の指定へ進むフィクスチャ
import { test, expect } from '../../../fixtures/shopping_deliv.fixture';

test.describe.serial('お支払方法・お届け時間等の指定画面のテストをします', () => {
test.beforeAll(async () => {
await zapClient.startSession(ContextType.FrontLogin, 'front_login_shopping_payment')
.then(async () => expect(await zapClient.isForcedUserModeEnabled()).toBeTruthy());
});

test('お支払方法・お届け時間等の指定画面へ遷移します', async ({ page }) => {
await expect(page.locator('h2.title')).toContainText('お支払方法・お届け時間等の指定');
await page.goto(url);
});

test.describe('テストを実行します[GET] @attack', () => {
let scanId: number;
test('アクティブスキャンを実行します', async ({ page }) => {
scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'GET');
await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000, page);
});

test('結果を確認します', async () => {
await zapClient.getAlerts(url, 0, 1, Risk.High)
.then(alerts => expect(alerts).toEqual([]));
});
});

test('注文確認画面へ遷移します', async ({ page }) => {
const paymentPage = new ShoppingPaymentPage(page);
await paymentPage.goto();
await paymentPage.fillOut();
await paymentPage.gotoNext();
await expect(page.locator('h2.title')).toContainText('入力内容のご確認');
});

/** 最新の transactionid で手動リクエストを送信し, HttpMessage を取得します */
const getMessage = async (page: Page) => {
const message = await zapClient.getLastMessage(url);
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}&mode_confirm=dummy`);
return await zapClient.getLastMessage(url);
};

test.describe('確認ページへ進むテストを実行します[POST] @attack', () => {
let scanId: number;
test('アクティブスキャンを実行します', async ({ page }) => {
const paymentPage = new ShoppingPaymentPage(page);
await paymentPage.goto();
await paymentPage.fillOut();
await paymentPage.gotoNext();
await expect(page.locator('h2.title')).toContainText('入力内容のご確認');

const message = await getMessage(page);
expect(message.requestHeader).toContain(`POST ${url}`);
expect(message.responseHeader).toContain('HTTP/1.1 302 Found');
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([]));
});
});
});
Loading