-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
968 additions
and
2,048 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,6 @@ | |
"useBuiltIns": "usage", | ||
"corejs": 2 | ||
} | ||
], | ||
"@babel/preset-typescript" | ||
] | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,12 +47,18 @@ jobs: | |
docker-compose exec -T postgres psql --user=eccube_db_user eccube_db -c "UPDATE dtb_customer SET email = '[email protected]' WHERE customer_id = (SELECT MAX(customer_id) FROM dtb_customer WHERE status = 2 AND del_flg = 0);" | ||
- run: sleep 1 | ||
- run: yarn install | ||
- run: | | ||
yarn install | ||
yarn run playwright install --with-deps chromium | ||
yarn playwright install-deps chromium | ||
- name: Run to E2E testing | ||
env: | ||
GROUP: ${{ matrix.group }} | ||
HTTPS_PROXY: 'localhost:8090' | ||
ZAP_PROXY_HOST: 'localhost:8090' | ||
CI: 1 | ||
FORCE_COLOR: 1 | ||
# Use runner's chromedriver to run on the latest version of google-chrome | ||
run: yarn test:e2e e2e-tests/${GROUP} | ||
|
||
|
@@ -102,9 +108,6 @@ jobs: | |
env: | ||
DB_TYPE: ${{ matrix.db }} | ||
run: echo "COMPOSE_FILE=docker-compose.yml:docker-compose.${DB_TYPE}.yml:docker-compose.dev.yml:docker-compose.owaspzap.yml:docker-compose.owaspzap.daemon.yml" >> $GITHUB_ENV | ||
- run: | | ||
ls -al data/config | ||
ls -al html/upload/save_image | ||
- name: Setup to EC-CUBE | ||
env: | ||
HTTP_URL: https://127.0.0.1:8085/ | ||
|
@@ -113,23 +116,23 @@ jobs: | |
run: | | ||
sudo chown -R 1001:1000 zap | ||
sudo chmod -R g+w zap | ||
touch data/config/config.php | ||
ls -al data/config | ||
ls -al html/upload/save_image | ||
sh -c 'echo "<?php" >> data/config/config.php' | ||
docker-compose build --build-arg TAG=${TAG} ec-cube | ||
docker-compose up -d | ||
rm data/config/config.php | ||
- run: sleep 1 | ||
- run: yarn install | ||
- run: | | ||
ls -al data/config | ||
ls -al html/upload/save_image | ||
docker-compose exec -T ec-cube ls -al /var/www/app/data/config | ||
docker-compose exec -T ec-cube ls -al /var/www/app/html/upload/save_image | ||
yarn install | ||
yarn run playwright install --with-deps chromium | ||
yarn playwright install-deps chromium | ||
- name: Run to E2E testing | ||
env: | ||
ZAP_PROXY_HOST: 'localhost:8090' | ||
HTTPS_PROXY: 'localhost:8090' | ||
CI: 1 | ||
FORCE_COLOR: 1 | ||
DB_TYPE: ${{ matrix.db }} | ||
DB_USER: ${{ matrix.dbuser }} | ||
DB_PASSWORD: ${{ matrix.dbpass }} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,8 @@ | ||
import { Builder, By, until } from 'selenium-webdriver' | ||
import { ZapClient, Mode, ContextType, Risk } from '../../utils/ZapClient'; | ||
import { test, expect, chromium, Page } from '@playwright/test'; | ||
import { ZapClient, Mode, ContextType, Risk, HttpMessage } from '../../utils/ZapClient'; | ||
import { intervalRepeater } from '../../utils/Progress'; | ||
import { SeleniumCapabilities } from '../../utils/SeleniumCapabilities'; | ||
const zapClient = new ZapClient(); | ||
|
||
|
||
jest.setTimeout(6000000); | ||
|
||
const inputNames = [ | ||
'name01', 'name02', 'kana01', 'kana02', 'zip01', 'zip02', 'addr01', 'addr02', | ||
'tel01', 'tel02', 'tel03' | ||
|
@@ -16,121 +12,129 @@ type InputName = { | |
}; | ||
|
||
const baseURL = 'https://ec-cube'; | ||
const url = baseURL + '/contact/'; | ||
const url = baseURL + '/contact/index.php'; | ||
|
||
test.describe.serial('お問い合わせページのテストをします', () => { | ||
let page: Page; | ||
test.beforeAll(async () => { | ||
await zapClient.setMode(Mode.Protect); | ||
await zapClient.newSession('/zap/wrk/sessions/front_login_contact', 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); | ||
}); | ||
|
||
beforeAll(async () => { | ||
await zapClient.setMode(Mode.Protect); | ||
await zapClient.newSession('/zap/wrk/sessions/front_login_contact', true); | ||
await zapClient.importContext(ContextType.FrontLogin); | ||
test('お問い合わせページを表示します', async () => { | ||
await expect(page).toHaveTitle(/お問い合わせ/); | ||
await expect(page.locator('h2.title')).toContainText('お問い合わせ'); | ||
}); | ||
|
||
if (!await zapClient.isForcedUserModeEnabled()) { | ||
await zapClient.setForcedUserModeEnabled(); | ||
expect(await zapClient.isForcedUserModeEnabled()).toBeTruthy(); | ||
} | ||
}); | ||
test.describe('テストを実行します[GET] @attack', () => { | ||
let scanId: number; | ||
test('アクティブスキャンを実行します', async () => { | ||
scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'GET'); | ||
await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000, page); | ||
}); | ||
|
||
describe('お問い合わせページを表示する', () => { | ||
test('[E2E] お問い合わせページを表示し、ログイン状態を確認する', async () => { | ||
const driver = await new Builder() | ||
.withCapabilities(SeleniumCapabilities) | ||
.build(); | ||
try { | ||
expect.assertions(15); | ||
await driver.get(url); | ||
await driver.wait( | ||
until.elementLocated(By.css('h2.title')), 10000) | ||
.getText().then(title => expect(title).toBe('お問い合わせ(入力ページ)')); | ||
|
||
inputNames.forEach( | ||
async (name) => await driver.findElement(By.name(name)).getAttribute('value') | ||
.then(value => expect(value).toEqual(expect.anything())) | ||
); | ||
await driver.findElement(By.name('email')).getAttribute('value').then(value => expect(value).toBe('[email protected]')); | ||
await driver.findElement(By.name('email02')).getAttribute('value').then(value => expect(value).toBe('[email protected]')); | ||
|
||
} finally { | ||
driver && await driver.quit(); | ||
} | ||
test('結果を確認します', async () => { | ||
await zapClient.getAlerts(url, 0, 1, Risk.High) | ||
.then(alerts => expect(alerts).toEqual([])); | ||
}); | ||
}); | ||
|
||
describe('[ATTACK] お問い合わせページの表示をスキャンする', () => { | ||
test('GET でお問い合わせページをスキャンする', async () => { | ||
const scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'GET'); | ||
test('ログイン状態を確認します', async () => { | ||
await page.goto(baseURL); // ログアウトしてしまう場合があるので一旦トップへ遷移する | ||
await page.goto(url); | ||
await expect(page.locator('#header')).toContainText('ようこそ'); | ||
inputNames.forEach(async (name) => expect(page.locator(`input[name=${name}]`)).not.toBeEmpty()); | ||
await expect(page.locator('input[name=email]')).toHaveValue('[email protected]'); | ||
await expect(page.locator('input[name=email02]')).toHaveValue('[email protected]'); | ||
}); | ||
|
||
await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000); | ||
let confirmMessage: HttpMessage; | ||
test('お問い合わせ内容を入力します', async () => { | ||
await page.fill('textarea[name=contents]', 'お問い合わせ入力'); | ||
await page.click('input[name=confirm]'); | ||
confirmMessage = await zapClient.getLastMessage(url); | ||
}); | ||
|
||
const alerts = await zapClient.getAlerts(url, 0, 1, Risk.High); | ||
alerts.forEach(alert => { | ||
throw new Error(alert.name); | ||
}); | ||
expect(alerts).toHaveLength(0); | ||
test('入力内容を確認します', async () => { | ||
await expect(page.locator('h2.title')).toContainText('お問い合わせ(確認ページ)'); | ||
inputNames.forEach(async (name) => { | ||
await expect(page.locator(`input[name=${name}]`)).toBeHidden(); | ||
await expect(page.locator(`input[name=${name}]`)).not.toBeEmpty(); | ||
}); | ||
await expect(page.locator('input[name=email]')).toBeHidden(); | ||
await expect(page.locator('input[name=email]')).toHaveValue('[email protected]'); | ||
await expect(page.locator('input[name=contents]')).toBeHidden(); | ||
await expect(page.locator('input[name=contents]')).toHaveValue('お問い合わせ入力'); | ||
|
||
await expect(page.locator('#form1 >> tr:nth-child(1) > td')).toContainText(await page.locator('input[name=name01]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(1) > td')).toContainText(await page.locator('input[name=name02]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(2) > td')).toContainText(await page.locator('input[name=kana01]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(2) > td')).toContainText(await page.locator('input[name=kana02]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(3) > td')).toContainText(await page.locator('input[name=zip01]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(3) > td')).toContainText(await page.locator('input[name=zip02]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(4) > td')).toContainText(await page.locator('input[name=addr01]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(4) > td')).toContainText(await page.locator('input[name=addr02]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(5) > td')).toContainText(await page.locator('input[name=tel01]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(5) > td')).toContainText(await page.locator('input[name=tel02]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(5) > td')).toContainText(await page.locator('input[name=tel03]').inputValue()); | ||
await expect(page.locator('#form1 >> tr:nth-child(6) > td')).toContainText('[email protected]'); | ||
await expect(page.locator('#form1 >> tr:nth-child(7) > td')).toContainText('お問い合わせ入力'); | ||
}); | ||
}); | ||
|
||
describe('お問い合わせ確認ページを表示する', () => { | ||
test('[E2E] お問い合わせページに入力し、確認画面に進む', async () => { | ||
const driver = await new Builder() | ||
.withCapabilities(SeleniumCapabilities) | ||
.build(); | ||
try { | ||
await driver.get(url); | ||
await driver.wait( | ||
until.elementLocated(By.css('h2.title')), 10000) | ||
.getText().then(title => expect(title).toBe('お問い合わせ(入力ページ)')); | ||
|
||
// 入力値を代入しておく | ||
let inputField: InputName = {}; | ||
inputNames.forEach( | ||
async (name) => await driver.findElement(By.name(name)).getAttribute('value') | ||
.then(value => inputField[name] = value) | ||
); | ||
|
||
await driver.findElement(By.name('contents')).sendKeys('お問い合わせ内容入力'); | ||
await driver.findElement(By.name('confirm')).click(); | ||
|
||
await driver.wait( | ||
until.elementLocated(By.css('h2.title')), 10000) | ||
.getText().then(title => expect(title).toBe('お問い合わせ(確認ページ)')); | ||
|
||
// hidden に入力されているかどうか | ||
inputNames.forEach( | ||
async (name) => await driver.findElement(By.name(name)).getAttribute('value') | ||
.then(value => expect(value).toBe(inputField[name])) | ||
); | ||
// 確認画面に表示されているかどうか | ||
await driver.findElement(By.xpath('//*[@id="form1"]/table/tbody/tr[1]/td')).getText() | ||
.then(value => expect(value).toBe(`${inputField.name01} ${inputField.name02}`)); | ||
await driver.findElement(By.xpath('//*[@id="form1"]/table/tbody/tr[2]/td')).getText() | ||
.then(value => expect(value).toBe(`${inputField.kana01} ${inputField.kana02}`)); | ||
await driver.findElement(By.xpath('//*[@id="form1"]/table/tbody/tr[3]/td')).getText() | ||
.then(value => expect(value).toBe(`〒${inputField.zip01}-${inputField.zip02}`)); | ||
await driver.findElement(By.xpath('//*[@id="form1"]/table/tbody/tr[4]/td')).getText() | ||
.then(value => expect(value).toContain(`${inputField.addr01}${inputField.addr02}`)); | ||
await driver.findElement(By.xpath('//*[@id="form1"]/table/tbody/tr[5]/td')).getText() | ||
.then(value => expect(value).toBe(`${inputField.tel01}-${inputField.tel02}-${inputField.tel03}`)); | ||
await driver.findElement(By.xpath('//*[@id="form1"]/table/tbody/tr[6]/td')).getText() | ||
.then(value => expect(value).toBe('[email protected]')); | ||
await driver.findElement(By.xpath('//*[@id="form1"]/table/tbody/tr[7]/td')).getText() | ||
.then(value => expect(value).toBe('お問い合わせ内容入力')); | ||
} finally { | ||
driver && await driver.quit(); | ||
} | ||
let completeMessage: HttpMessage; | ||
test('お問い合わせ内容を送信します', async () => { | ||
await page.click('#send'); | ||
await expect(page.locator('h2.title')).toContainText('お問い合わせ(完了ページ)'); | ||
completeMessage = await zapClient.getLastMessage(url); | ||
}); | ||
|
||
describe('[ATTACK] お問い合わせ(確認ページ)をスキャンする', () => { | ||
test('POST でお問い合わせ(確認ページ)をスキャンする', async () => { | ||
test.describe('テストを実行します[POST][入力→確認] @attack', () => { | ||
let requestBody: string; | ||
test('transactionid を取得し直します', async () => { | ||
await page.goto(url); | ||
const transactionid = await page.locator('input[name=transactionid]').first().inputValue(); | ||
requestBody = confirmMessage.requestBody.replace(/transactionid=[a-z0-9]+/, `transactionid=${transactionid}`); | ||
}); | ||
|
||
test('アクティブスキャンを実行します', async () => { | ||
expect(requestBody).toContain('mode=confirm'); | ||
const scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'POST', 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([])); | ||
}); | ||
}); | ||
|
||
const message = await zapClient.getLastMessage(url); | ||
const scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'GET', message.requestBody); // XXX なぜか method=POST にすると url_not_found のエラーになる. GET にしていても POST でスキャンされる | ||
test.describe('テストを実行します[POST][確認→完了] @attack', () => { | ||
let requestBody: string; | ||
test('transactionid を取得し直します', async () => { | ||
await page.goto(url); | ||
const transactionid = await page.locator('input[name=transactionid]').first().inputValue(); | ||
requestBody = completeMessage.requestBody.replace(/transactionid=[a-z0-9]+/, `transactionid=${transactionid}`); | ||
}); | ||
|
||
await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000); | ||
test('アクティブスキャンを実行します', async () => { | ||
expect(completeMessage.responseHeader).toContain('HTTP/1.1 302 Found'); | ||
expect(requestBody).toContain('mode=complete'); | ||
const scanId = await zapClient.activeScanAsUser(url, 2, 110, false, null, 'POST', requestBody); | ||
await intervalRepeater(async () => await zapClient.getActiveScanStatus(scanId), 5000, page); | ||
}); | ||
|
||
const alerts = await zapClient.getAlerts(url, 0, 1, Risk.High); | ||
alerts.forEach(alert => { | ||
throw new Error(alert.name); | ||
}); | ||
expect(alerts).toHaveLength(0); | ||
test('結果を確認します', async () => { | ||
await zapClient.getAlerts(url, 0, 1, Risk.High) | ||
.then(alerts => expect(alerts).toEqual([])); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.