ElixirVault/tests/SeleniumTests/App/PubUsers/pubUserPwdResetTest.php

285 lines
12 KiB
PHP

<?php
declare(strict_types=1);
namespace LoretaAudit\Tests\SeleniumTests\App\PubUsers;
use BRSystems\Core\Library\cGoogle2FA\cGoogle2FA;
use DOMDocument;
use DOMXPath;
use Facebook\WebDriver\WebDriverBy;
use LoretaAudit\Tests\BasePhpUnitSeleniumCase;
use LoretaAudit\Tests\DataSetup\Constants\siteAccounts;
use LoretaAudit\Tests\DataSetup\Constants\siteLanguages;
use LoretaAudit\Tests\DataSetup\Constants\siteUsers;
use LoretaAudit\Tests\DataSetup\Traits\App\pubUsersTrait;
class pubUserPwdResetTest extends BasePhpUnitSeleniumCase
{
use pubUsersTrait;
const url = [
siteLanguages::LANG_LV => [
'url' => 'paroles-atgusana',
'header' => 'Paroles atgūšana',
'exists' => ['#user_data', 'button.btn.btn-block'],
'text-exists' => [
'Paroles atgūšana', 'Atpakaļ uz autentifikāciju',
'Lūdzu ievadiet lietotāja e-pastu vai lietotājvārdu, kuram vēlieties atgūt paroli.'
],
'inv-user' => 'Lietotājs nav atrasts vai ir bloķēts!',
'fill-field' => 'Lūdzu aizpildiet lauku!',
'fill-email' => 'Ievadīta nekorekta e-pasta adrese!',
'email-sent' => 'E-pasts tika nosūtīts',
'email-sent-error' => 'Lietotājs nav atrasts vai ir bloķēts!',
'linksToTexts' => [
'/ienakt-gramatvedibas-sistema' => [
'wait_id' => 'user_login',
'text' => 'Ienākt grāmatvedības sistēmā',
'text_selector' => 'div#form > .relative > p.font-20.semi-font'
],
],
'email-a' => 'Atjaunot paroli',
'email-subject' => 'Konts - Paroles atjaunošana',
'email-expected-body' => [
'Labdien', 'Esam saņēmuši pieprasījumu atjaunot nozaudētu ZUTENIS konta paroli.',
'Zemāk jūs atradīsit pagaidu ģenerētu paroli, kas būs derīga 2 stundas.',
'Pagaidu parole', 'Paroli var arī atjaunot, noklikšķinot uz pogas',
'Ar cieņu', 'Nepieciešama palīdzība?', 'info@zutenis.lv',
'Jūs saņēmāt šo e-pastu, jo šī e-pasta adrese ir reģistrēta www.ZUTENIS.lv'
],
'header-3pwd' => 'Mainīt lietotāja paroli',
'pwd-change-error' => [
'Lietotāja paroles atgūšana neizdevās!',
'Lūdzu, mēģiniet vēlreiz atiestatīt paroli',
'lūdzu, sazinieties ar atbalsta dienestu!',
],
]
];
protected function setUp(): void
{
parent::setUp();
$this->reloadDbTables(['mod_users']);
}
public function testPwdReset(): void
{
$loginData = $this->getLoginCredentialsByType(siteUsers::loginAppSelfEmployed);
foreach (self::url as $lang => $pageData) {
$this->url($pageData['url']);
$this->elementWait('user_data');
// Test error containing fields
$this->webDriver->executeScript('$("#user_data").focus().blur();');
$this->webDriver->action()->moveToElement($this->byId('user_data'))->perform();
$this->elementWait('#user_data + div.errMsg', self::CSS_SELECTOR);
$this->assertEquals($pageData['fill-field'], $this->byCssSelector('#user_data + div.errMsg')->getText());
$this->webDriver->executeScript('$("#user_data").focus().val("test").blur();');
$this->webDriver->action()->moveToElement($this->byId('user_data'))->perform();
$this->elementWait('#user_data + div.errMsg', self::CSS_SELECTOR);
$this->assertEquals($pageData['fill-email'], $this->byCssSelector('#user_data + div.errMsg')->getText());
// Input invalid login data
$this->byId("user_data")->clear()->sendKeys('test.test@gmail.com');
$this->byCssSelector("form#passRecovery_cnt button.btn.btn-block")->click();
$this->elementWait('div.status_error', self::CSS_SELECTOR);
$this->assertEquals($pageData['email-sent-error'], $this->byCssSelector('div.status_error')->getText());
$this->byId("user_data")->clear()->sendKeys($loginData['email']);
$this->byCssSelector("form#passRecovery_cnt button.btn.btn-block")->click();
$this->elementWait('div.status_ok', self::CSS_SELECTOR);
$this->assertEquals($pageData['email-sent'], $this->byCssSelector('div.status_ok')->getText());
// Fetch email from MailHog
$messages = $this->awaitEmailFromMailHog(
$loginData['email'],
$pageData['email-subject'],
60 * 5
);
// Validate mail content
$this->assertEquals($pageData['email-subject'], $this->emailHtmlDecode($messages->subject));
$this->assertExpected($pageData['email-expected-body'], $this->emailHtmlDecode($messages->body));
// Preserve user password reset db data state
$loginData['data'] = $this->cDb->_querySelectRow(
'mod_users', ['user_password', 'user_pwdtime', 'user_newpwd'], ['id' => $loginData['id']]);
// Get password reset url from mail
$doc = new DOMDocument();
$doc->loadHTML($messages->body);
$xpath = new DOMXpath($doc);
$activationUrl = $xpath->query("//a[contains(., '{$pageData['email-a']}')]")
->item(0)->attributes->item(0)->nodeValue;
$tempPassword = $xpath->query("//b[@id='pass']")->item(0)->nodeValue;
// Test password change from link case 1
//------------------------------------------------------------
$this->userPassRecoveryForm($activationUrl, $lang, $pageData, $loginData);
$this->logout();
// Test password change from link case 2 - error activation case
//------------------------------------------------------------
$this->url($activationUrl, true);
$this->elementWait('div#form div.status_error', self::CSS_SELECTOR);
$this->assertExpected($pageData['pwd-change-error'], $this->byCssSelector('div#form div.status_error')->getText());
// Test password change from link case 3 - manual password input login form
//------------------------------------------------------------
$this->url($loginData['url']);
$this->elementWait('user_login');
// Reset user db state to previous before password change
$this->cDb->_queryUpdate('mod_users', $loginData['data'], ['id' => $loginData['id']]);
// Input login data
$this->byId("user_login")->sendKeys($loginData['user']);
$this->byId("user_password")->sendKeys($tempPassword);
$this->byCssSelector("form#frm_input div#agree_to_terms")->click();
$this->byCssSelector("form#frm_input button.btn.btn-block")->click();
// Change password
$this->userPassRecoveryForm(null, $lang, $pageData, $loginData);
$this->logout();
// Test password change from link case 4 - no 2fa security - manual password input login form
//------------------------------------------------------------
$this->url($loginData['url']);
$this->elementWait('user_login');
// Reset user db state to previous before password change
$loginData['data']['user_2fa_secret_enabled'] = '';
$this->cDb->_queryUpdate('mod_users', $loginData['data'], ['id' => $loginData['id']]);
// Input login data
$this->byId("user_login")->sendKeys($loginData['user']);
$this->byId("user_password")->sendKeys($tempPassword);
$this->byCssSelector("form#frm_input div#agree_to_terms")->click();
$this->byCssSelector("form#frm_input button.btn.btn-block")->click();
// Change password
$this->userPassRecoveryForm(null, $lang, $pageData, $loginData, false);
$this->elementWait('#restricted-access a.logout', self::CSS_SELECTOR);
// Logout
$this->byCssSelector("#restricted-access a.logout")->click();
// Test password change from link case 5 - no 2fa security
//------------------------------------------------------------
// Reset user db state to previous before password change
$this->cDb->_queryUpdate('mod_users', $loginData['data'], ['id' => $loginData['id']]);
$this->userPassRecoveryForm($activationUrl, $lang, $pageData, $loginData, false);
$this->elementWait('#restricted-access a.logout', self::CSS_SELECTOR);
// Logout
$this->byCssSelector("#restricted-access a.logout")->click();
$this->reloadDbTables(['mod_users']);
}
}
public function userPassRecoveryForm(
string $url = null, string $lang = siteLanguages::LANG_LV,
array $pageData = [], array $loginData = [], bool $has2FASecurityEnabled = true
): void
{
// Activate account
if (!is_null($url)) {
$this->url($url, true);
}
if ($has2FASecurityEnabled) {
// Wait for 2FA activation request
$this->elementWait('frm_2fa_input');
// Validate 2fa code from google
$oGoogle2FA = new cGoogle2FA();
$next2FACode = $oGoogle2FA->getGoogleAuthCode($loginData['2fa']);
foreach (str_split($next2FACode) as $i => $char) {
$this->byCssSelector("input.code2fa[tabindex='" . ++$i . "']")->clear()->sendKeys($char);
}
}
// Check are we in right place
$this->elementWait('pwd_cnt');
$this->assertEquals($pageData['header-3pwd'], $this->byCssSelector('div.container .relative > p.font-20')->getText());
// Test password change
$this->fillAndSubmitPasswordChangeForm([
'newPass' => 'testmynewpassword12!@'
]);
$this->awaitAndSelectAccount(siteAccounts::ACCOUNT_SELF_EMPLOYED);
// Validate dashboard welcome messages
if ($has2FASecurityEnabled) {
$this->elementWait("#drop_cnt > .doc > .form-data div.container.dashboard-cnt", self::CSS_SELECTOR);
$this->assertExpected(pubUserLoginForcePwdChangeTest::url[$lang]['welcome-msg'], $this->byTagName('body')->getText());
}
$this->awaitAndAcceptCookies();
}
public function testLoginPageRedirectLinks(): void
{
foreach (self::url as $lang => $pageData) {
$this->url($pageData['url']);
$this->elementWait('user_data');
// Test pages clicks
$pagesToVisit = [];
$links = $this->webDriver->findElements(WebDriverBy::cssSelector('#passRecovery_cnt > a.link'));
foreach ($links as $link) {
$pagesToVisit[] = $link->getAttribute('href');
}
foreach ($pagesToVisit as $href) {
if (isset($pageData['linksToTexts'][$href])) {
$this->url($this->normalizeUrl($href));
sleep(2);
// Element Wait fails for some unknown reason
if (isset($pageData['linksToTexts'][$href]['wait_id']))
$this->elementWait($pageData['linksToTexts'][$href]['wait_id']);
elseif (isset($pageData['linksToTexts'][$href]['wait_tag']))
$this->elementWait($pageData['linksToTexts'][$href]['wait_tag'], self::TAG_NAME);
$this->assertEquals($pageData['linksToTexts'][$href]['text'], $this->byCssSelector($pageData['linksToTexts'][$href]['text_selector'])->getText());
}
}
}
}
public function testPwdResetPageLoaded(): void
{
foreach (self::url as $lang => $pageData) {
$this->url($pageData['url']);
$this->elementWait('user_data');
foreach ($pageData['exists'] as $selectorToFind) {
$this->assertTrue($this->elementExists($selectorToFind, self::CSS_SELECTOR));
}
$this->assertExpected($pageData['text-exists'], $this->byTagName('body')->getText());
}
}
}