Add acceptance tests for the new totp key confirmation

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
Christoph Wurst 2017-03-14 11:57:21 +01:00
Родитель c1581c6f52
Коммит b46f432e79
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: CC42AC2A7F0E56D8
1 изменённых файлов: 51 добавлений и 7 удалений

Просмотреть файл

@ -22,6 +22,7 @@
namespace OCA\TwoFactorTOTP\Tests\Acceptance;
use Base32\Base32;
use Facebook\WebDriver\Exception\ElementNotSelectableException;
use Facebook\WebDriver\WebDriver;
use Facebook\WebDriver\WebDriverBy;
@ -29,9 +30,12 @@ use Facebook\WebDriver\WebDriverExpectedCondition;
use OC;
use OCA\TwoFactorTOTP\Db\TotpSecret;
use OCA\TwoFactorTOTP\Db\TotpSecretMapper;
use OCA\TwoFactorTOTP\Service\ITotp;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\IUser;
use Otp\GoogleAuthenticator;
use Otp\Otp;
use PHPUnit_Framework_AssertionFailedError;
/**
* @group Acceptance
@ -80,17 +84,17 @@ class TOTPAcceptenceTest extends AcceptanceTest {
$this->webDriver->findElement(WebDriverBy::cssSelector('form[name=login] input[type=submit]'))->click();
// Go to personal settings
$this->webDriver->wait(20, 1000)->until(WebDriverExpectedCondition::elementToBeClickable(WebDriverBy::id('expandDisplayName')));
$this->webDriver->wait(20, 200)->until(WebDriverExpectedCondition::elementToBeClickable(WebDriverBy::id('expandDisplayName')));
$this->webDriver->findElement(WebDriverBy::id('expandDisplayName'))->click();
$this->webDriver->findElement(WebDriverBy::linkText('Personal'))->click();
// Go to TOTP settings
$this->webDriver->wait(20, 1000)->until(WebDriverExpectedCondition::elementToBeClickable(WebDriverBy::linkText('TOTP second-factor auth')));
$this->webDriver->wait(20, 200)->until(WebDriverExpectedCondition::elementToBeClickable(WebDriverBy::linkText('TOTP second-factor auth')));
$this->webDriver->findElement(WebDriverBy::linkText('TOTP second-factor auth'))->click();
// Enable TOTP
usleep(15 * 1000 * 1000); // Hard-coded sleep because the scripts need some time load the page
$this->webDriver->wait(20, 1000)->until(function(WebDriver $driver) {
// Wait for state being loaded from the server
$this->webDriver->wait(20, 200)->until(function(WebDriver $driver) {
try {
return count($driver->findElements(WebDriverBy::id('totp-enabled'))) > 0;
} catch (ElementNotSelectableException $ex) {
@ -100,7 +104,47 @@ class TOTPAcceptenceTest extends AcceptanceTest {
$this->webDriver->executeScript('arguments[0].click(); console.log(arguments[0]);', [
$this->webDriver->findElement(WebDriverBy::id('totp-enabled')),
]);
$this->webDriver->wait(20, 1000)->until(WebDriverExpectedCondition::elementTextContains(WebDriverBy::id('twofactor-totp-settings'), 'This is your new TOTP secret:'));
$this->webDriver->wait(15, 200)->until(WebDriverExpectedCondition::elementTextContains(WebDriverBy::id('twofactor-totp-settings'), 'This is your new TOTP secret:'));
$this->assertHasSecret(ITotp::STATE_CREATED);
// Enter a wrong OTP
$this->webDriver->findElement(WebDriverBy::id('totp-confirmation'))->sendKeys('000000');
$this->webDriver->findElement(WebDriverBy::id('totp-confirmation-submit'))->click();
// Wait for the notification
$this->webDriver->wait(15, 200)->until(WebDriverExpectedCondition::elementTextContains(WebDriverBy::id('notification'), 'Could not verify your key. Please try again'));
// Enter a correct OTP
$this->webDriver->findElement(WebDriverBy::id('totp-confirmation'))->sendKeys($this->getValidTOTP());
$this->webDriver->findElement(WebDriverBy::id('totp-confirmation-submit'))->click();
// Try to locate checked checkbox
$this->webDriver->wait(20, 200)->until(function(WebDriver $driver) {
try {
return $driver->findElement(WebDriverBy::id('totp-enabled'))->getAttribute('checked') === 'true';
} catch (ElementNotSelectableException $ex) {
return false;
}
});
$this->assertHasSecret(ITotp::STATE_ENABLED);
}
private function assertHasSecret($state) {
try {
$secret = $this->secretMapper->getSecret($this->user);
if ($state !== (int) $secret->getState()) {
throw new PHPUnit_Framework_AssertionFailedError('TOTP secret has wrong state');
}
} catch (DoesNotExistException $ex) {
throw new PHPUnit_Framework_AssertionFailedError('User does not have a totp secret');
}
}
private function getValidTOTP() {
$dbSecret = $this->secretMapper->getSecret($this->user);
$secret = OC::$server->getCrypto()->decrypt($dbSecret->getSecret());
$otp = new Otp();
return $otp->totp(Base32::decode($secret));
}
private function createSecret() {
@ -123,7 +167,7 @@ class TOTPAcceptenceTest extends AcceptanceTest {
$this->webDriver->findElement(WebDriverBy::id('password'))->sendKeys('admin');
$this->webDriver->findElement(WebDriverBy::cssSelector('form[name=login] input[type=submit]'))->click();
$this->webDriver->wait(20, 1000)->until(function(WebDriver $driver) {
$this->webDriver->wait(20, 200)->until(function(WebDriver $driver) {
try {
return $driver->findElements(WebDriverBy::className('totp-form'));
} catch (ElementNotSelectableException $ex) {
@ -135,7 +179,7 @@ class TOTPAcceptenceTest extends AcceptanceTest {
$this->webDriver->findElement(WebDriverBy::name('challenge'))->sendKeys('000000');
$this->webDriver->findElement(WebDriverBy::cssSelector('button[type="submit"]'))->submit();
$this->webDriver->wait(20, 1000)->until(WebDriverExpectedCondition::elementTextContains(WebDriverBy::className('warning'), 'Error while validating your second factor'));
$this->webDriver->wait(20, 200)->until(WebDriverExpectedCondition::elementTextContains(WebDriverBy::className('warning'), 'Error while validating your second factor'));
$this->assertEquals('http://localhost:8080/index.php/login/challenge/totp', $this->webDriver->getCurrentURL());
}