Last active
February 6, 2018 01:28
-
-
Save vslinko/577a9aaf7563055ed1dcbb6e2cc84e72 to your computer and use it in GitHub Desktop.
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
const puppeteer = require('puppeteer'); | |
const readline = require('readline-sync'); | |
const util = require('util'); | |
const fs = require('fs'); | |
const USERNAME = 'USERNAME'; | |
const EXPECTED_TEMPLATE_NAME = 'EXPECTED_TEMPLATE_NAME'; | |
const EXPECTED_ACCOUNT_NUMBER = 'EXPECTED_ACCOUNT_NUMBER'; | |
function questionAsync(text, hidden = false) { | |
return new Promise((resolve) => { | |
resolve( | |
readline.question(text, { | |
hideEchoBack: hidden, | |
}) | |
); | |
}); | |
} | |
function priceToNumber(price) { | |
if (!/^[\d\s]+([\.,]\d+)?$/.test(price)) { | |
throw new Error(`Невалидная сумма "${price}"`); | |
} | |
return Number(price.replace(',', '.').replace(/[^\.0-9]/g, '')); | |
} | |
(async () => { | |
let browser, page; | |
const folderName = new Date().getTime(); | |
try { | |
fs.mkdirSync(String(folderName)); | |
console.log('Открываю браузер'); | |
browser = await puppeteer.launch(); | |
console.log('Открываю главную'); | |
page = await browser.newPage(); | |
await page.goto('https://ib.psbank.ru'); | |
console.log('Открываю попап авторизации'); | |
await page.waitForSelector('.login-link'); | |
await page.click('.login-link'); | |
await page.waitForSelector('input[name=clientNumber]'); | |
console.log('Авторизуюсь'); | |
await page.keyboard.type(USERNAME); | |
const password = await questionAsync('Введите пароль: ', true); | |
await page.focus('input[name=password]'); | |
await page.keyboard.type(password); | |
await page.screenshot({path: `${folderName}/1-loginPage.png`}); | |
await page.click('input[value="Войти"]'); | |
await Promise.all([ | |
page.waitForSelector('.code-input-number'), | |
page.waitForSelector('input[name=secondStepSmsCode]'), | |
]); | |
const firstSmsId = (await (await (await page.$('.code-input-number')).getProperty('textContent')).jsonValue()).replace(/ /g, ''); | |
const firstSmsText = await questionAsync(`Введите код ${firstSmsId}: `); | |
await page.focus('input[name=secondStepSmsCode]'); | |
await page.keyboard.type(firstSmsText); | |
console.log('Жду загрузки дашборда'); | |
await Promise.all([ | |
page.waitForSelector('.my-templates h2 a'), | |
page.waitForSelector('.balance'), | |
]); | |
await page.screenshot({path: `${folderName}/2-mainPage.png`}); | |
const balance = await page.evaluate(() => { | |
return document.querySelector('.balance').textContent; | |
}); | |
const balanceNumber = priceToNumber(balance.trim()); | |
const toPay = balanceNumber > 10000 ? 10000 : balanceNumber; | |
console.log('Текущий баланс:', balance); | |
console.log('Сумма операции:', toPay); | |
console.log('Открываю страницу шаблонов'); | |
await page.click('.my-templates h2 a'); | |
await page.waitForSelector('span.name[role=button]'); | |
await page.screenshot({path: `${folderName}/3-templatesPage.png`}); | |
console.log('Открываю нужный шаблон'); | |
const templates = await page.$$('span.name[role=button]'); | |
const templateNames = await Promise.all(templates.map(async (template) => { | |
const property = await template.getProperty('textContent'); | |
return await property.jsonValue(); | |
})); | |
const templateIndex = templateNames.indexOf(EXPECTED_TEMPLATE_NAME); | |
if (templateIndex < 0) { | |
throw new Error(`Не могу найти шаблон "${EXPECTED_TEMPLATE_NAME}"`); | |
} | |
await templates[templateIndex].click(); | |
console.log('Проверяю данные транзакции'); | |
await Promise.all([ | |
page.waitForSelector('input[name*=Sum]'), | |
page.waitForSelector('input[name*=ReceiverAccountNumber]'), | |
page.waitForSelector('.op-footer .button-primary'), | |
]); | |
await page.focus('input[name*=Sum]'); | |
await page.keyboard.type(String(toPay)); | |
await page.focus('input[name*=ReceiverAccountNumber]'); | |
const {accountNumber, operationAmount} = await page.evaluate(() => { | |
return { | |
operationAmount: document.querySelector('input[name*=Sum]').value, | |
accountNumber: document.querySelector('input[name*=ReceiverAccountNumber]').value, | |
}; | |
}); | |
if (accountNumber !== EXPECTED_ACCOUNT_NUMBER) { | |
throw new Error(`Неверный номер счета "${accountNumber}"`); | |
} | |
if (priceToNumber(operationAmount) !== toPay) { | |
throw new Error(`Неверная сумма операции "${operationAmount}"`); | |
} | |
console.log('Подтверждаю транзакцию'); | |
const nextButton = await page.$('.op-footer .button-primary'); | |
const nextButtonText = await (await nextButton.getProperty('textContent')).jsonValue(); | |
if (nextButtonText !== 'Далее') { | |
throw new Error(`Неверный текст кнопки "${nextButtonText}"`); | |
} | |
await page.screenshot({path: `${folderName}/4-popup.png`}); | |
await nextButton.click(); | |
await Promise.all([ | |
page.waitForSelector('.code-number'), | |
page.waitForSelector('input[name=secondStepSmsCode]'), | |
]); | |
const comissionAlert = await page.evaluate(() => { | |
const popups = document.querySelectorAll('.operation-execution'); | |
if (popups.length !== 1) { | |
return true; | |
} | |
return popups[0].textContent.indexOf('Комиссия') >= 0; | |
}); | |
if (comissionAlert) { | |
throw new Error(`Обнаружена комиссия`); | |
} | |
await page.screenshot({path: `${folderName}/5-popup_sms.png`}); | |
const secondSmsId = await (await (await page.$('.code-number')).getProperty('textContent')).jsonValue(); | |
const secondSmsText = await questionAsync(`Введите код ${secondSmsId}: `); | |
await page.focus('input[name=secondStepSmsCode]'); | |
await page.keyboard.type(secondSmsText); | |
console.log('Жду завершения операции'); | |
await page.waitForFunction(() => { | |
return document.querySelector('.step-caption').textContent === "Операция проведена!"; | |
}); | |
await page.screenshot({path: `${folderName}/6-popup_result.png`}); | |
console.log('Операция проведена!'); | |
await browser.close(); | |
} catch (e) { | |
console.error(e); | |
if (page) { | |
await page.screenshot({path: `${folderName}/error.png`}); | |
} | |
if (browser) { | |
await browser.close(); | |
} | |
} | |
})(); |
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
{ | |
"name": "psb", | |
"version": "1.0.0", | |
"scripts": { | |
"start": "node index.js" | |
}, | |
"dependencies": { | |
"puppeteer": "^1.0.0", | |
"readline-sync": "^1.4.7" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment