mirror of
https://github.com/elyby/accounts.git
synced 2025-05-31 14:11:46 +05:30
Rework tests structure. Upgrade codeception to 2.5.3. Merge params configuration into app configuration.
This commit is contained in:
29
api/tests/unit/TestCase.php
Normal file
29
api/tests/unit/TestCase.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace api\tests\unit;
|
||||
|
||||
use Mockery;
|
||||
|
||||
class TestCase extends \Codeception\Test\Unit {
|
||||
|
||||
/**
|
||||
* @var \api\tests\UnitTester
|
||||
*/
|
||||
protected $tester;
|
||||
|
||||
protected function tearDown() {
|
||||
parent::tearDown();
|
||||
Mockery::close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Список фикстур, что будут загружены перед тестом, но после зачистки базы данных
|
||||
*
|
||||
* @url http://codeception.com/docs/modules/Yii2#fixtures
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function _fixtures() {
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
2
api/tests/unit/_bootstrap.php
Normal file
2
api/tests/unit/_bootstrap.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Here you can initialize variables that will for your tests
|
74
api/tests/unit/components/ReCaptcha/ValidatorTest.php
Normal file
74
api/tests/unit/components/ReCaptcha/ValidatorTest.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\components\ReCaptcha;
|
||||
|
||||
use api\components\ReCaptcha\Validator;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use phpmock\mockery\PHPMockery;
|
||||
use ReflectionClass;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class ValidatorTest extends TestCase {
|
||||
|
||||
public function testValidateEmptyValue() {
|
||||
$validator = new Validator(mock(ClientInterface::class));
|
||||
$this->assertFalse($validator->validate('', $error));
|
||||
$this->assertEquals('error.captcha_required', $error, 'Get error.captcha_required, if passed empty value');
|
||||
}
|
||||
|
||||
public function testValidateInvalidValue() {
|
||||
$mockClient = mock(ClientInterface::class);
|
||||
$mockClient->shouldReceive('request')->andReturn(new Response(200, [], json_encode([
|
||||
'success' => false,
|
||||
'error-codes' => [
|
||||
'invalid-input-response', // The response parameter is invalid or malformed.
|
||||
],
|
||||
])));
|
||||
|
||||
$validator = new Validator($mockClient);
|
||||
$this->assertFalse($validator->validate('12341234', $error));
|
||||
$this->assertEquals('error.captcha_invalid', $error, 'Get error.captcha_invalid, if passed wrong value');
|
||||
}
|
||||
|
||||
public function testValidateWithNetworkTroubles() {
|
||||
$mockClient = mock(ClientInterface::class);
|
||||
$mockClient->shouldReceive('request')->andThrow(mock(ConnectException::class))->once();
|
||||
$mockClient->shouldReceive('request')->andReturn(new Response(200, [], json_encode([
|
||||
'success' => true,
|
||||
'error-codes' => [
|
||||
'invalid-input-response', // The response parameter is invalid or malformed.
|
||||
],
|
||||
])))->once();
|
||||
PHPMockery::mock($this->getClassNamespace(Validator::class), 'sleep')->once();
|
||||
|
||||
$validator = new Validator($mockClient);
|
||||
$this->assertTrue($validator->validate('12341234', $error));
|
||||
$this->assertNull($error);
|
||||
}
|
||||
|
||||
public function testValidateWithHugeNetworkTroubles() {
|
||||
$mockClient = mock(ClientInterface::class);
|
||||
$mockClient->shouldReceive('request')->andThrow(mock(ConnectException::class))->times(3);
|
||||
PHPMockery::mock($this->getClassNamespace(Validator::class), 'sleep')->times(2);
|
||||
|
||||
$validator = new Validator($mockClient);
|
||||
$this->expectException(ConnectException::class);
|
||||
$validator->validate('12341234', $error);
|
||||
}
|
||||
|
||||
public function testValidateValidValue() {
|
||||
$mockClient = mock(ClientInterface::class);
|
||||
$mockClient->shouldReceive('request')->andReturn(new Response(200, [], json_encode([
|
||||
'success' => true,
|
||||
])));
|
||||
$validator = new Validator($mockClient);
|
||||
$this->assertTrue($validator->validate('12341234', $error));
|
||||
$this->assertNull($error);
|
||||
}
|
||||
|
||||
private function getClassNamespace(string $className): string {
|
||||
return (new ReflectionClass($className))->getNamespaceName();
|
||||
}
|
||||
|
||||
}
|
197
api/tests/unit/components/User/ComponentTest.php
Normal file
197
api/tests/unit/components/User/ComponentTest.php
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\components\User;
|
||||
|
||||
use api\components\User\AuthenticationResult;
|
||||
use api\components\User\Component;
|
||||
use api\components\User\Identity;
|
||||
use common\models\Account;
|
||||
use common\models\AccountSession;
|
||||
use Emarref\Jwt\Claim;
|
||||
use Emarref\Jwt\Jwt;
|
||||
use Emarref\Jwt\Token;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\_support\ProtectedCaller;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\AccountSessionFixture;
|
||||
use common\tests\fixtures\MinecraftAccessKeyFixture;
|
||||
use Yii;
|
||||
use yii\web\Request;
|
||||
|
||||
class ComponentTest extends TestCase {
|
||||
use ProtectedCaller;
|
||||
|
||||
/**
|
||||
* @var Component|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
private $component;
|
||||
|
||||
public function _before() {
|
||||
parent::_before();
|
||||
$this->component = new Component($this->getComponentConfig());
|
||||
}
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'sessions' => AccountSessionFixture::class,
|
||||
'minecraftSessions' => MinecraftAccessKeyFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testCreateJwtAuthenticationToken() {
|
||||
$this->mockRequest();
|
||||
|
||||
$account = new Account(['id' => 1]);
|
||||
$result = $this->component->createJwtAuthenticationToken($account, false);
|
||||
$this->assertInstanceOf(AuthenticationResult::class, $result);
|
||||
$this->assertNull($result->getSession());
|
||||
$this->assertEquals($account, $result->getAccount());
|
||||
$payloads = (new Jwt())->deserialize($result->getJwt())->getPayload();
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals(time(), $payloads->findClaimByName(Claim\IssuedAt::NAME)->getValue(), '', 3);
|
||||
/** @noinspection SummerTimeUnsafeTimeManipulationInspection */
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals(time() + 60 * 60 * 24 * 7, $payloads->findClaimByName('exp')->getValue(), '', 3);
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals('ely|1', $payloads->findClaimByName('sub')->getValue());
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals('accounts_web_user', $payloads->findClaimByName('ely-scopes')->getValue());
|
||||
$this->assertNull($payloads->findClaimByName('jti'));
|
||||
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
$result = $this->component->createJwtAuthenticationToken($account, true);
|
||||
$this->assertInstanceOf(AuthenticationResult::class, $result);
|
||||
$this->assertInstanceOf(AccountSession::class, $result->getSession());
|
||||
$this->assertEquals($account, $result->getAccount());
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertTrue($result->getSession()->refresh());
|
||||
$payloads = (new Jwt())->deserialize($result->getJwt())->getPayload();
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals(time(), $payloads->findClaimByName(Claim\IssuedAt::NAME)->getValue(), '', 3);
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals(time() + 3600, $payloads->findClaimByName('exp')->getValue(), '', 3);
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals('ely|1', $payloads->findClaimByName('sub')->getValue());
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals('accounts_web_user', $payloads->findClaimByName('ely-scopes')->getValue());
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals($result->getSession()->id, $payloads->findClaimByName('jti')->getValue());
|
||||
}
|
||||
|
||||
public function testRenewJwtAuthenticationToken() {
|
||||
$userIP = '192.168.0.1';
|
||||
$this->mockRequest($userIP);
|
||||
/** @var AccountSession $session */
|
||||
$session = $this->tester->grabFixture('sessions', 'admin');
|
||||
$result = $this->component->renewJwtAuthenticationToken($session);
|
||||
$this->assertInstanceOf(AuthenticationResult::class, $result);
|
||||
$this->assertEquals($session, $result->getSession());
|
||||
$this->assertEquals($session->account_id, $result->getAccount()->id);
|
||||
$session->refresh(); // reload data from db
|
||||
$this->assertEquals(time(), $session->last_refreshed_at, '', 3);
|
||||
$this->assertEquals($userIP, $session->getReadableIp());
|
||||
$payloads = (new Jwt())->deserialize($result->getJwt())->getPayload();
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals(time(), $payloads->findClaimByName(Claim\IssuedAt::NAME)->getValue(), '', 3);
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals(time() + 3600, $payloads->findClaimByName('exp')->getValue(), '', 3);
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals('ely|1', $payloads->findClaimByName('sub')->getValue());
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals('accounts_web_user', $payloads->findClaimByName('ely-scopes')->getValue());
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals($session->id, $payloads->findClaimByName('jti')->getValue(), 'session has not changed');
|
||||
}
|
||||
|
||||
public function testParseToken() {
|
||||
$this->mockRequest();
|
||||
$token = $this->callProtected($this->component, 'createToken', new Account(['id' => 1]));
|
||||
$jwt = $this->callProtected($this->component, 'serializeToken', $token);
|
||||
$this->assertInstanceOf(Token::class, $this->component->parseToken($jwt), 'success get RenewResult object');
|
||||
}
|
||||
|
||||
public function testGetActiveSession() {
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
$result = $this->component->createJwtAuthenticationToken($account, true);
|
||||
$this->component->logout();
|
||||
|
||||
/** @var Component|\PHPUnit_Framework_MockObject_MockObject $component */
|
||||
$component = $this->getMockBuilder(Component::class)
|
||||
->setMethods(['getIsGuest'])
|
||||
->setConstructorArgs([$this->getComponentConfig()])
|
||||
->getMock();
|
||||
|
||||
$component
|
||||
->expects($this->any())
|
||||
->method('getIsGuest')
|
||||
->willReturn(false);
|
||||
|
||||
$this->mockAuthorizationHeader($result->getJwt());
|
||||
|
||||
$session = $component->getActiveSession();
|
||||
$this->assertInstanceOf(AccountSession::class, $session);
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$this->assertEquals($session->id, $result->getSession()->id);
|
||||
}
|
||||
|
||||
public function testTerminateSessions() {
|
||||
/** @var AccountSession $session */
|
||||
$session = AccountSession::findOne($this->tester->grabFixture('sessions', 'admin2')['id']);
|
||||
|
||||
/** @var Component|\Mockery\MockInterface $component */
|
||||
$component = mock(Component::class . '[getActiveSession]', [$this->getComponentConfig()])->shouldDeferMissing();
|
||||
$component->shouldReceive('getActiveSession')->times(1)->andReturn($session);
|
||||
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
$component->createJwtAuthenticationToken($account, true);
|
||||
|
||||
$component->terminateSessions($account, Component::KEEP_MINECRAFT_SESSIONS | Component::KEEP_SITE_SESSIONS);
|
||||
$this->assertNotEmpty($account->getMinecraftAccessKeys()->all());
|
||||
$this->assertNotEmpty($account->getSessions()->all());
|
||||
|
||||
$component->terminateSessions($account, Component::KEEP_SITE_SESSIONS);
|
||||
$this->assertEmpty($account->getMinecraftAccessKeys()->all());
|
||||
$this->assertNotEmpty($account->getSessions()->all());
|
||||
|
||||
$component->terminateSessions($account, Component::KEEP_CURRENT_SESSION);
|
||||
$sessions = $account->getSessions()->all();
|
||||
$this->assertEquals(1, count($sessions));
|
||||
$this->assertTrue($sessions[0]->id === $session->id);
|
||||
|
||||
$component->terminateSessions($account);
|
||||
$this->assertEmpty($account->getSessions()->all());
|
||||
$this->assertEmpty($account->getMinecraftAccessKeys()->all());
|
||||
}
|
||||
|
||||
private function mockRequest($userIP = '127.0.0.1') {
|
||||
/** @var Request|\Mockery\MockInterface $request */
|
||||
$request = mock(Request::class . '[getHostInfo,getUserIP]')->shouldDeferMissing();
|
||||
$request->shouldReceive('getHostInfo')->andReturn('http://localhost');
|
||||
$request->shouldReceive('getUserIP')->andReturn($userIP);
|
||||
|
||||
Yii::$app->set('request', $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $bearerToken
|
||||
*/
|
||||
private function mockAuthorizationHeader($bearerToken = null) {
|
||||
if ($bearerToken !== null) {
|
||||
$bearerToken = 'Bearer ' . $bearerToken;
|
||||
}
|
||||
|
||||
Yii::$app->request->headers->set('Authorization', $bearerToken);
|
||||
}
|
||||
|
||||
private function getComponentConfig() {
|
||||
return [
|
||||
'identityClass' => Identity::class,
|
||||
'enableSession' => false,
|
||||
'loginUrl' => null,
|
||||
'secret' => 'secret',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace api\tests\unit\components\User;
|
||||
|
||||
use api\components\User\AuthenticationResult;
|
||||
use common\models\Account;
|
||||
use common\models\AccountSession;
|
||||
use Emarref\Jwt\Algorithm\Hs256;
|
||||
use Emarref\Jwt\Claim\Expiration;
|
||||
use Emarref\Jwt\Encryption\Factory as EncryptionFactory;
|
||||
use Emarref\Jwt\Jwt;
|
||||
use Emarref\Jwt\Token;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class JwtAuthenticationResultTest extends TestCase {
|
||||
|
||||
public function testGetAccount() {
|
||||
$account = new Account();
|
||||
$account->id = 123;
|
||||
$model = new AuthenticationResult($account, '', null);
|
||||
$this->assertEquals($account, $model->getAccount());
|
||||
}
|
||||
|
||||
public function testGetJwt() {
|
||||
$model = new AuthenticationResult(new Account(), 'mocked jwt', null);
|
||||
$this->assertEquals('mocked jwt', $model->getJwt());
|
||||
}
|
||||
|
||||
public function testGetSession() {
|
||||
$model = new AuthenticationResult(new Account(), '', null);
|
||||
$this->assertNull($model->getSession());
|
||||
|
||||
$session = new AccountSession();
|
||||
$session->id = 321;
|
||||
$model = new AuthenticationResult(new Account(), '', $session);
|
||||
$this->assertEquals($session, $model->getSession());
|
||||
}
|
||||
|
||||
public function testGetAsResponse() {
|
||||
$jwtToken = $this->createJwtToken(time() + 3600);
|
||||
$model = new AuthenticationResult(new Account(), $jwtToken, null);
|
||||
$result = $model->getAsResponse();
|
||||
$this->assertEquals($jwtToken, $result['access_token']);
|
||||
$this->assertSame(3600, $result['expires_in']);
|
||||
|
||||
/** @noinspection SummerTimeUnsafeTimeManipulationInspection */
|
||||
$jwtToken = $this->createJwtToken(time() + 86400);
|
||||
$session = new AccountSession();
|
||||
$session->refresh_token = 'refresh token';
|
||||
$model = new AuthenticationResult(new Account(), $jwtToken, $session);
|
||||
$result = $model->getAsResponse();
|
||||
$this->assertEquals($jwtToken, $result['access_token']);
|
||||
$this->assertEquals('refresh token', $result['refresh_token']);
|
||||
$this->assertSame(86400, $result['expires_in']);
|
||||
}
|
||||
|
||||
private function createJwtToken(int $expires): string {
|
||||
$token = new Token();
|
||||
$token->addClaim(new Expiration($expires));
|
||||
|
||||
return (new Jwt())->serialize($token, EncryptionFactory::create(new Hs256('123')));
|
||||
}
|
||||
|
||||
}
|
57
api/tests/unit/filters/NginxCacheTest.php
Normal file
57
api/tests/unit/filters/NginxCacheTest.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace api\tests\unit\filters;
|
||||
|
||||
use api\filters\NginxCache;
|
||||
use api\tests\unit\TestCase;
|
||||
use Yii;
|
||||
use yii\base\Action;
|
||||
use yii\web\Controller;
|
||||
use yii\web\HeaderCollection;
|
||||
use yii\web\Request;
|
||||
|
||||
class NginxCacheTest extends TestCase {
|
||||
|
||||
public function testAfterAction() {
|
||||
$this->testAfterActionInternal(3600, 3600);
|
||||
$this->testAfterActionInternal('@' . (time() + 30), '@' . (time() + 30));
|
||||
$this->testAfterActionInternal(function() {
|
||||
return 3000;
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
private function testAfterActionInternal($ruleConfig, $expected) {
|
||||
/** @var HeaderCollection|\PHPUnit_Framework_MockObject_MockObject $headers */
|
||||
$headers = $this->getMockBuilder(HeaderCollection::class)
|
||||
->setMethods(['set'])
|
||||
->getMock();
|
||||
|
||||
$headers->expects($this->once())
|
||||
->method('set')
|
||||
->with('X-Accel-Expires', $expected);
|
||||
|
||||
/** @var Request|\PHPUnit_Framework_MockObject_MockObject $request */
|
||||
$request = $this->getMockBuilder(Request::class)
|
||||
->setMethods(['getHeaders'])
|
||||
->getMock();
|
||||
|
||||
$request->expects($this->any())
|
||||
->method('getHeaders')
|
||||
->willReturn($headers);
|
||||
|
||||
Yii::$app->set('response', $request);
|
||||
|
||||
/** @var Controller|\PHPUnit_Framework_MockObject_MockObject $controller */
|
||||
$controller = $this->getMockBuilder(Controller::class)
|
||||
->setConstructorArgs(['mock', Yii::$app])
|
||||
->getMock();
|
||||
|
||||
$component = new NginxCache([
|
||||
'rules' => [
|
||||
'index' => $ruleConfig,
|
||||
],
|
||||
]);
|
||||
|
||||
$component->afterAction(new Action('index', $controller), '');
|
||||
}
|
||||
|
||||
}
|
49
api/tests/unit/models/FeedbackFormTest.php
Normal file
49
api/tests/unit/models/FeedbackFormTest.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\models;
|
||||
|
||||
use api\models\FeedbackForm;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
use yii\swiftmailer\Message;
|
||||
|
||||
class FeedbackFormTest extends TestCase {
|
||||
|
||||
public function testSendMessage() {
|
||||
$model = new FeedbackForm([
|
||||
'subject' => 'Тема обращения',
|
||||
'email' => 'erickskrauch@ely.by',
|
||||
'message' => 'Привет мир!',
|
||||
]);
|
||||
$this->assertTrue($model->sendMessage());
|
||||
$this->tester->seeEmailIsSent(1, 'message file exists');
|
||||
}
|
||||
|
||||
public function testSendMessageWithEmail() {
|
||||
/** @var FeedbackForm|\PHPUnit_Framework_MockObject_MockObject $model */
|
||||
$model = $this->getMockBuilder(FeedbackForm::class)
|
||||
->setMethods(['getAccount'])
|
||||
->setConstructorArgs([[
|
||||
'subject' => 'Тема обращения',
|
||||
'email' => 'erickskrauch@ely.by',
|
||||
'message' => 'Привет мир!',
|
||||
]])
|
||||
->getMock();
|
||||
|
||||
$model
|
||||
->expects($this->any())
|
||||
->method('getAccount')
|
||||
->will($this->returnValue(new Account([
|
||||
'id' => '123',
|
||||
'username' => 'Erick',
|
||||
'email' => 'find-this@email.net',
|
||||
'created_at' => time() - 86400,
|
||||
])));
|
||||
$this->assertTrue($model->sendMessage());
|
||||
/** @var Message $message */
|
||||
$message = $this->tester->grabLastSentEmail();
|
||||
$this->assertInstanceOf(Message::class, $message);
|
||||
$data = (string)$message;
|
||||
$this->assertContains('find-this@email.net', $data);
|
||||
}
|
||||
|
||||
}
|
66
api/tests/unit/models/JwtIdentityTest.php
Normal file
66
api/tests/unit/models/JwtIdentityTest.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\models;
|
||||
|
||||
use api\components\User\IdentityInterface;
|
||||
use api\components\User\Jwt;
|
||||
use api\components\User\JwtIdentity;
|
||||
use Codeception\Specify;
|
||||
use Emarref\Jwt\Claim;
|
||||
use Emarref\Jwt\Encryption\Factory as EncryptionFactory;
|
||||
use Emarref\Jwt\Token;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\_support\ProtectedCaller;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use Yii;
|
||||
|
||||
class JwtIdentityTest extends TestCase {
|
||||
use Specify;
|
||||
use ProtectedCaller;
|
||||
|
||||
public function _fixtures(): array {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testFindIdentityByAccessToken() {
|
||||
$token = $this->generateToken();
|
||||
$identity = JwtIdentity::findIdentityByAccessToken($token);
|
||||
$this->assertInstanceOf(IdentityInterface::class, $identity);
|
||||
$this->assertEquals($token, $identity->getId());
|
||||
$this->assertEquals($this->tester->grabFixture('accounts', 'admin')['id'], $identity->getAccount()->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \yii\web\UnauthorizedHttpException
|
||||
* @expectedExceptionMessage Token expired
|
||||
*/
|
||||
public function testFindIdentityByAccessTokenWithExpiredToken() {
|
||||
$token = new Token();
|
||||
$token->addClaim(new Claim\IssuedAt(1464593193));
|
||||
$token->addClaim(new Claim\Expiration(1464596793));
|
||||
$token->addClaim(new Claim\Subject('ely|' . $this->tester->grabFixture('accounts', 'admin')['id']));
|
||||
$expiredToken = (new Jwt())->serialize($token, EncryptionFactory::create(Yii::$app->user->getAlgorithm()));
|
||||
|
||||
JwtIdentity::findIdentityByAccessToken($expiredToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \yii\web\UnauthorizedHttpException
|
||||
* @expectedExceptionMessage Incorrect token
|
||||
*/
|
||||
public function testFindIdentityByAccessTokenWithEmptyToken() {
|
||||
JwtIdentity::findIdentityByAccessToken('');
|
||||
}
|
||||
|
||||
protected function generateToken() {
|
||||
/** @var \api\components\User\Component $component */
|
||||
$component = Yii::$app->user;
|
||||
/** @var \common\models\Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
$token = $this->callProtected($component, 'createToken', $account);
|
||||
|
||||
return $this->callProtected($component, 'serializeToken', $token);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
namespace api\tests\_support\models\authentication;
|
||||
|
||||
use api\components\User\AuthenticationResult;
|
||||
use api\models\authentication\ConfirmEmailForm;
|
||||
use common\models\Account;
|
||||
use common\models\AccountSession;
|
||||
use common\models\EmailActivation;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
|
||||
class ConfirmEmailFormTest extends TestCase {
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'emailActivations' => EmailActivationFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testConfirm() {
|
||||
$fixture = $this->tester->grabFixture('emailActivations', 'freshRegistrationConfirmation');
|
||||
$model = $this->createModel($fixture['key']);
|
||||
$result = $model->confirm();
|
||||
$this->assertInstanceOf(AuthenticationResult::class, $result);
|
||||
$this->assertInstanceOf(AccountSession::class, $result->getSession(), 'session was generated');
|
||||
$activationExists = EmailActivation::find()->andWhere(['key' => $fixture['key']])->exists();
|
||||
$this->assertFalse($activationExists, 'email activation key is not exist');
|
||||
/** @var Account $account */
|
||||
$account = Account::findOne($fixture['account_id']);
|
||||
$this->assertEquals(Account::STATUS_ACTIVE, $account->status, 'user status changed to active');
|
||||
}
|
||||
|
||||
private function createModel($key) {
|
||||
return new ConfirmEmailForm([
|
||||
'key' => $key,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
134
api/tests/unit/models/authentication/ForgotPasswordFormTest.php
Normal file
134
api/tests/unit/models/authentication/ForgotPasswordFormTest.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\models\authentication;
|
||||
|
||||
use api\components\ReCaptcha\Validator as ReCaptchaValidator;
|
||||
use api\models\authentication\ForgotPasswordForm;
|
||||
use Codeception\Specify;
|
||||
use common\models\Account;
|
||||
use common\models\EmailActivation;
|
||||
use common\tasks\SendPasswordRecoveryEmail;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
use Yii;
|
||||
|
||||
class ForgotPasswordFormTest extends TestCase {
|
||||
use Specify;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
Yii::$container->set(ReCaptchaValidator::class, new class(mock(ClientInterface::class)) extends ReCaptchaValidator {
|
||||
public function validateValue($value) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'emailActivations' => EmailActivationFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testValidateLogin() {
|
||||
$model = new ForgotPasswordForm(['login' => 'unexist']);
|
||||
$model->validateLogin('login');
|
||||
$this->assertEquals(['error.login_not_exist'], $model->getErrors('login'), 'error.login_not_exist if login is invalid');
|
||||
|
||||
$model = new ForgotPasswordForm(['login' => $this->tester->grabFixture('accounts', 'admin')['username']]);
|
||||
$model->validateLogin('login');
|
||||
$this->assertEmpty($model->getErrors('login'), 'empty errors if login is exists');
|
||||
}
|
||||
|
||||
public function testValidateActivity() {
|
||||
$model = new ForgotPasswordForm([
|
||||
'login' => $this->tester->grabFixture('accounts', 'not-activated-account')['username'],
|
||||
]);
|
||||
$model->validateActivity('login');
|
||||
$this->assertEquals(['error.account_not_activated'], $model->getErrors('login'), 'expected error if account is not confirmed');
|
||||
|
||||
$model = new ForgotPasswordForm([
|
||||
'login' => $this->tester->grabFixture('accounts', 'admin')['username'],
|
||||
]);
|
||||
$model->validateLogin('login');
|
||||
$this->assertEmpty($model->getErrors('login'), 'empty errors if login is exists');
|
||||
}
|
||||
|
||||
public function testValidateFrequency() {
|
||||
$model = $this->createModel([
|
||||
'login' => $this->tester->grabFixture('accounts', 'admin')['username'],
|
||||
'key' => $this->tester->grabFixture('emailActivations', 'freshPasswordRecovery')['key'],
|
||||
]);
|
||||
$model->validateFrequency('login');
|
||||
$this->assertEquals(['error.recently_sent_message'], $model->getErrors('login'), 'error.account_not_activated if recently was message');
|
||||
|
||||
$model = $this->createModel([
|
||||
'login' => $this->tester->grabFixture('accounts', 'admin')['username'],
|
||||
'key' => $this->tester->grabFixture('emailActivations', 'oldPasswordRecovery')['key'],
|
||||
]);
|
||||
$model->validateFrequency('login');
|
||||
$this->assertEmpty($model->getErrors('login'), 'empty errors if email was sent a long time ago');
|
||||
|
||||
$model = $this->createModel([
|
||||
'login' => $this->tester->grabFixture('accounts', 'admin')['username'],
|
||||
'key' => 'invalid-key',
|
||||
]);
|
||||
$model->validateFrequency('login');
|
||||
$this->assertEmpty($model->getErrors('login'), 'empty errors if previous confirmation model not founded');
|
||||
}
|
||||
|
||||
public function testForgotPassword() {
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
$model = new ForgotPasswordForm(['login' => $account->username]);
|
||||
$this->assertTrue($model->forgotPassword(), 'form should be successfully processed');
|
||||
$activation = $model->getEmailActivation();
|
||||
$this->assertInstanceOf(EmailActivation::class, $activation, 'getEmailActivation should return valid object instance');
|
||||
|
||||
$this->assertTaskCreated($this->tester->grabLastQueuedJob(), $account, $activation);
|
||||
}
|
||||
|
||||
public function testForgotPasswordResend() {
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'account-with-expired-forgot-password-message');
|
||||
$model = new ForgotPasswordForm(['login' => $account->username]);
|
||||
$callTime = time();
|
||||
$this->assertTrue($model->forgotPassword(), 'form should be successfully processed');
|
||||
$emailActivation = $model->getEmailActivation();
|
||||
$this->assertInstanceOf(EmailActivation::class, $emailActivation);
|
||||
$this->assertGreaterThanOrEqual($callTime, $emailActivation->created_at);
|
||||
|
||||
$this->assertTaskCreated($this->tester->grabLastQueuedJob(), $account, $emailActivation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SendPasswordRecoveryEmail $job
|
||||
* @param Account $account
|
||||
* @param EmailActivation $activation
|
||||
*/
|
||||
private function assertTaskCreated($job, Account $account, EmailActivation $activation) {
|
||||
$this->assertInstanceOf(SendPasswordRecoveryEmail::class, $job);
|
||||
$this->assertSame($account->username, $job->username);
|
||||
$this->assertSame($account->email, $job->email);
|
||||
$this->assertSame($account->lang, $job->locale);
|
||||
$this->assertSame($activation->key, $job->code);
|
||||
$this->assertSame('http://localhost/recover-password/' . $activation->key, $job->link);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @return ForgotPasswordForm
|
||||
*/
|
||||
private function createModel(array $params = []) {
|
||||
return new class($params) extends ForgotPasswordForm {
|
||||
public $key;
|
||||
|
||||
public function getEmailActivation() {
|
||||
return EmailActivation::findOne($this->key);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
174
api/tests/unit/models/authentication/LoginFormTest.php
Normal file
174
api/tests/unit/models/authentication/LoginFormTest.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
namespace api\tests\_support\models\authentication;
|
||||
|
||||
use api\components\User\AuthenticationResult;
|
||||
use api\models\authentication\LoginForm;
|
||||
use Codeception\Specify;
|
||||
use common\models\Account;
|
||||
use OTPHP\TOTP;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
|
||||
class LoginFormTest extends TestCase {
|
||||
use Specify;
|
||||
|
||||
private $originalRemoteAddr;
|
||||
|
||||
public function setUp() {
|
||||
$this->originalRemoteAddr = $_SERVER['REMOTE_ADDR'] ?? null;
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
$_SERVER['REMOTE_ADDR'] = $this->originalRemoteAddr;
|
||||
}
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testValidateLogin() {
|
||||
$this->specify('error.login_not_exist if login not exists', function() {
|
||||
$model = $this->createModel([
|
||||
'login' => 'mr-test',
|
||||
'account' => null,
|
||||
]);
|
||||
$model->validateLogin('login');
|
||||
$this->assertEquals(['error.login_not_exist'], $model->getErrors('login'));
|
||||
});
|
||||
|
||||
$this->specify('no errors if login exists', function() {
|
||||
$model = $this->createModel([
|
||||
'login' => 'mr-test',
|
||||
'account' => new Account(),
|
||||
]);
|
||||
$model->validateLogin('login');
|
||||
$this->assertEmpty($model->getErrors('login'));
|
||||
});
|
||||
}
|
||||
|
||||
public function testValidatePassword() {
|
||||
$this->specify('error.password_incorrect if password invalid', function() {
|
||||
$model = $this->createModel([
|
||||
'password' => '87654321',
|
||||
'account' => new Account(['password' => '12345678']),
|
||||
]);
|
||||
$model->validatePassword('password');
|
||||
$this->assertEquals(['error.password_incorrect'], $model->getErrors('password'));
|
||||
});
|
||||
|
||||
$this->specify('no errors if password valid', function() {
|
||||
$model = $this->createModel([
|
||||
'password' => '12345678',
|
||||
'account' => new Account(['password' => '12345678']),
|
||||
]);
|
||||
$model->validatePassword('password');
|
||||
$this->assertEmpty($model->getErrors('password'));
|
||||
});
|
||||
}
|
||||
|
||||
public function testValidateTotp() {
|
||||
$account = new Account(['password' => '12345678']);
|
||||
$account->password = '12345678';
|
||||
$account->is_otp_enabled = true;
|
||||
$account->otp_secret = 'AAAA';
|
||||
|
||||
$this->specify('error.totp_incorrect if totp invalid', function() use ($account) {
|
||||
$model = $this->createModel([
|
||||
'password' => '12345678',
|
||||
'totp' => '321123',
|
||||
'account' => $account,
|
||||
]);
|
||||
$model->validateTotp('totp');
|
||||
$this->assertEquals(['error.totp_incorrect'], $model->getErrors('totp'));
|
||||
});
|
||||
|
||||
$totp = TOTP::create($account->otp_secret);
|
||||
$this->specify('no errors if password valid', function() use ($account, $totp) {
|
||||
$model = $this->createModel([
|
||||
'password' => '12345678',
|
||||
'totp' => $totp->now(),
|
||||
'account' => $account,
|
||||
]);
|
||||
$model->validateTotp('totp');
|
||||
$this->assertEmpty($model->getErrors('totp'));
|
||||
});
|
||||
}
|
||||
|
||||
public function testValidateActivity() {
|
||||
$this->specify('error.account_not_activated if account in not activated state', function() {
|
||||
$model = $this->createModel([
|
||||
'account' => new Account(['status' => Account::STATUS_REGISTERED]),
|
||||
]);
|
||||
$model->validateActivity('login');
|
||||
$this->assertEquals(['error.account_not_activated'], $model->getErrors('login'));
|
||||
});
|
||||
|
||||
$this->specify('error.account_banned if account has banned status', function() {
|
||||
$model = $this->createModel([
|
||||
'account' => new Account(['status' => Account::STATUS_BANNED]),
|
||||
]);
|
||||
$model->validateActivity('login');
|
||||
$this->assertEquals(['error.account_banned'], $model->getErrors('login'));
|
||||
});
|
||||
|
||||
$this->specify('no errors if account active', function() {
|
||||
$model = $this->createModel([
|
||||
'account' => new Account(['status' => Account::STATUS_ACTIVE]),
|
||||
]);
|
||||
$model->validateActivity('login');
|
||||
$this->assertEmpty($model->getErrors('login'));
|
||||
});
|
||||
}
|
||||
|
||||
public function testLogin() {
|
||||
$model = $this->createModel([
|
||||
'login' => 'erickskrauch',
|
||||
'password' => '12345678',
|
||||
'account' => new Account([
|
||||
'username' => 'erickskrauch',
|
||||
'password' => '12345678',
|
||||
'status' => Account::STATUS_ACTIVE,
|
||||
]),
|
||||
]);
|
||||
$this->assertInstanceOf(AuthenticationResult::class, $model->login(), 'model should login user');
|
||||
$this->assertEmpty($model->getErrors(), 'error message should not be set');
|
||||
}
|
||||
|
||||
public function testLoginWithRehashing() {
|
||||
$model = new LoginForm([
|
||||
'login' => $this->tester->grabFixture('accounts', 'user-with-old-password-type')['username'],
|
||||
'password' => '12345678',
|
||||
]);
|
||||
$this->assertInstanceOf(AuthenticationResult::class, $model->login());
|
||||
$this->assertEmpty($model->getErrors());
|
||||
$this->assertEquals(
|
||||
Account::PASS_HASH_STRATEGY_YII2,
|
||||
$model->getAccount()->password_hash_strategy,
|
||||
'user, that login using account with old pass hash strategy should update it automatically'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @return LoginForm
|
||||
*/
|
||||
private function createModel(array $params = []) {
|
||||
return new class($params) extends LoginForm {
|
||||
private $_account;
|
||||
|
||||
public function setAccount($value) {
|
||||
$this->_account = $value;
|
||||
}
|
||||
|
||||
public function getAccount(): ?Account {
|
||||
return $this->_account;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
69
api/tests/unit/models/authentication/LogoutFormTest.php
Normal file
69
api/tests/unit/models/authentication/LogoutFormTest.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
namespace api\tests\_support\models\authentication;
|
||||
|
||||
use api\components\User\Component;
|
||||
use api\components\User\Identity;
|
||||
use api\models\authentication\LogoutForm;
|
||||
use Codeception\Specify;
|
||||
use common\models\AccountSession;
|
||||
use api\tests\unit\TestCase;
|
||||
use Yii;
|
||||
|
||||
class LogoutFormTest extends TestCase {
|
||||
use Specify;
|
||||
|
||||
public function testValidateLogout() {
|
||||
$this->specify('No actions if active session is not exists', function() {
|
||||
$userComp = $this
|
||||
->getMockBuilder(Component::class)
|
||||
->setConstructorArgs([$this->getComponentArgs()])
|
||||
->setMethods(['getActiveSession'])
|
||||
->getMock();
|
||||
$userComp
|
||||
->expects($this->any())
|
||||
->method('getActiveSession')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
Yii::$app->set('user', $userComp);
|
||||
|
||||
$model = new LogoutForm();
|
||||
expect($model->logout())->true();
|
||||
});
|
||||
|
||||
$this->specify('if active session is presented, then delete should be called', function() {
|
||||
$session = $this
|
||||
->getMockBuilder(AccountSession::class)
|
||||
->setMethods(['delete'])
|
||||
->getMock();
|
||||
$session
|
||||
->expects($this->once())
|
||||
->method('delete')
|
||||
->willReturn(true);
|
||||
|
||||
$userComp = $this
|
||||
->getMockBuilder(Component::class)
|
||||
->setConstructorArgs([$this->getComponentArgs()])
|
||||
->setMethods(['getActiveSession'])
|
||||
->getMock();
|
||||
$userComp
|
||||
->expects($this->any())
|
||||
->method('getActiveSession')
|
||||
->will($this->returnValue($session));
|
||||
|
||||
Yii::$app->set('user', $userComp);
|
||||
|
||||
$model = new LogoutForm();
|
||||
$model->logout();
|
||||
});
|
||||
}
|
||||
|
||||
private function getComponentArgs() {
|
||||
return [
|
||||
'identityClass' => Identity::class,
|
||||
'enableSession' => false,
|
||||
'loginUrl' => null,
|
||||
'secret' => 'secret',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace api\tests\_support\models\authentication;
|
||||
|
||||
use api\components\User\AuthenticationResult;
|
||||
use api\models\authentication\RecoverPasswordForm;
|
||||
use Codeception\Specify;
|
||||
use common\models\Account;
|
||||
use common\models\EmailActivation;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
|
||||
class RecoverPasswordFormTest extends TestCase {
|
||||
use Specify;
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'emailActivations' => EmailActivationFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testRecoverPassword() {
|
||||
$fixture = $this->tester->grabFixture('emailActivations', 'freshPasswordRecovery');
|
||||
$model = new RecoverPasswordForm([
|
||||
'key' => $fixture['key'],
|
||||
'newPassword' => '12345678',
|
||||
'newRePassword' => '12345678',
|
||||
]);
|
||||
$result = $model->recoverPassword();
|
||||
$this->assertInstanceOf(AuthenticationResult::class, $result);
|
||||
$this->assertNull($result->getSession(), 'session was not generated');
|
||||
$this->assertFalse(EmailActivation::find()->andWhere(['key' => $fixture['key']])->exists());
|
||||
/** @var Account $account */
|
||||
$account = Account::findOne($fixture['account_id']);
|
||||
$this->assertTrue($account->validatePassword('12345678'));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\models\authentication;
|
||||
|
||||
use api\components\User\AuthenticationResult;
|
||||
use api\models\authentication\RefreshTokenForm;
|
||||
use Codeception\Specify;
|
||||
use common\models\AccountSession;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountSessionFixture;
|
||||
|
||||
class RefreshTokenFormTest extends TestCase {
|
||||
use Specify;
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'sessions' => AccountSessionFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testValidateRefreshToken() {
|
||||
$this->specify('error.refresh_token_not_exist if passed token not exists', function() {
|
||||
/** @var RefreshTokenForm $model */
|
||||
$model = new class extends RefreshTokenForm {
|
||||
public function getSession() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
$model->validateRefreshToken();
|
||||
$this->assertEquals(['error.refresh_token_not_exist'], $model->getErrors('refresh_token'));
|
||||
});
|
||||
|
||||
$this->specify('no errors if token exists', function() {
|
||||
/** @var RefreshTokenForm $model */
|
||||
$model = new class extends RefreshTokenForm {
|
||||
public function getSession() {
|
||||
return new AccountSession();
|
||||
}
|
||||
};
|
||||
$model->validateRefreshToken();
|
||||
$this->assertEmpty($model->getErrors('refresh_token'));
|
||||
});
|
||||
}
|
||||
|
||||
public function testRenew() {
|
||||
$model = new RefreshTokenForm();
|
||||
$model->refresh_token = $this->tester->grabFixture('sessions', 'admin')['refresh_token'];
|
||||
$this->assertInstanceOf(AuthenticationResult::class, $model->renew());
|
||||
}
|
||||
|
||||
}
|
141
api/tests/unit/models/authentication/RegistrationFormTest.php
Normal file
141
api/tests/unit/models/authentication/RegistrationFormTest.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
namespace api\tests\_support\models\authentication;
|
||||
|
||||
use api\components\ReCaptcha\Validator as ReCaptchaValidator;
|
||||
use api\models\authentication\RegistrationForm;
|
||||
use common\models\Account;
|
||||
use common\models\EmailActivation;
|
||||
use common\models\UsernameHistory;
|
||||
use common\tasks\SendRegistrationEmail;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
use common\tests\fixtures\UsernameHistoryFixture;
|
||||
use common\tests\helpers\Mock;
|
||||
use Yii;
|
||||
use yii\validators\EmailValidator;
|
||||
use yii\web\Request;
|
||||
use const common\LATEST_RULES_VERSION;
|
||||
|
||||
class RegistrationFormTest extends TestCase {
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->mockRequest();
|
||||
Yii::$container->set(ReCaptchaValidator::class, new class(mock(ClientInterface::class)) extends ReCaptchaValidator {
|
||||
public function validateValue($value) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'emailActivations' => EmailActivationFixture::class,
|
||||
'usernameHistory' => UsernameHistoryFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testValidatePasswordAndRePasswordMatch() {
|
||||
$model = new RegistrationForm([
|
||||
'password' => 'enough-length',
|
||||
'rePassword' => 'but-mismatch',
|
||||
]);
|
||||
$this->assertFalse($model->validate(['rePassword']));
|
||||
$this->assertSame(['error.rePassword_does_not_match'], $model->getErrors('rePassword'));
|
||||
|
||||
$model = new RegistrationForm([
|
||||
'password' => 'enough-length',
|
||||
'rePassword' => 'enough-length',
|
||||
]);
|
||||
$this->assertTrue($model->validate(['rePassword']));
|
||||
$this->assertEmpty($model->getErrors('rePassword'));
|
||||
}
|
||||
|
||||
public function testSignup() {
|
||||
Mock::func(EmailValidator::class, 'checkdnsrr')->andReturnTrue();
|
||||
$model = new RegistrationForm([
|
||||
'username' => 'some_username',
|
||||
'email' => 'some_email@example.com',
|
||||
'password' => 'some_password',
|
||||
'rePassword' => 'some_password',
|
||||
'rulesAgreement' => true,
|
||||
'lang' => 'ru',
|
||||
]);
|
||||
|
||||
$account = $model->signup();
|
||||
|
||||
$this->expectSuccessRegistration($account);
|
||||
$this->assertEquals('ru', $account->lang, 'lang is set');
|
||||
}
|
||||
|
||||
public function testSignupWithDefaultLanguage() {
|
||||
Mock::func(EmailValidator::class, 'checkdnsrr')->andReturnTrue();
|
||||
$model = new RegistrationForm([
|
||||
'username' => 'some_username',
|
||||
'email' => 'some_email@example.com',
|
||||
'password' => 'some_password',
|
||||
'rePassword' => 'some_password',
|
||||
'rulesAgreement' => true,
|
||||
]);
|
||||
|
||||
$account = $model->signup();
|
||||
|
||||
$this->expectSuccessRegistration($account);
|
||||
$this->assertEquals('en', $account->lang, 'lang is set');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account|null $account
|
||||
*/
|
||||
private function expectSuccessRegistration($account) {
|
||||
$this->assertInstanceOf(Account::class, $account, 'user should be valid');
|
||||
$this->assertTrue($account->validatePassword('some_password'), 'password should be correct');
|
||||
$this->assertNotEmpty($account->uuid, 'uuid is set');
|
||||
$this->assertNotNull($account->registration_ip, 'registration_ip is set');
|
||||
$this->assertEquals(LATEST_RULES_VERSION, $account->rules_agreement_version, 'actual rules version is set');
|
||||
$this->assertTrue(Account::find()->andWhere([
|
||||
'username' => 'some_username',
|
||||
'email' => 'some_email@example.com',
|
||||
])->exists(), 'user model exists in database');
|
||||
/** @var EmailActivation $activation */
|
||||
$activation = EmailActivation::find()
|
||||
->andWhere([
|
||||
'account_id' => $account->id,
|
||||
'type' => EmailActivation::TYPE_REGISTRATION_EMAIL_CONFIRMATION,
|
||||
])
|
||||
->one();
|
||||
$this->assertInstanceOf(EmailActivation::class, $activation, 'email activation code exists in database');
|
||||
$this->assertTrue(UsernameHistory::find()->andWhere([
|
||||
'username' => $account->username,
|
||||
'account_id' => $account->id,
|
||||
'applied_in' => $account->created_at,
|
||||
])->exists(), 'username history record exists in database');
|
||||
|
||||
/** @var SendRegistrationEmail $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(SendRegistrationEmail::class, $job);
|
||||
$this->assertSame($account->username, $job->username);
|
||||
$this->assertSame($account->email, $job->email);
|
||||
$this->assertSame($account->lang, $job->locale);
|
||||
$this->assertSame($activation->key, $job->code);
|
||||
$this->assertSame('http://localhost/activation/' . $activation->key, $job->link);
|
||||
}
|
||||
|
||||
private function mockRequest($ip = '88.225.20.236') {
|
||||
$request = $this->getMockBuilder(Request::class)
|
||||
->setMethods(['getUserIP'])
|
||||
->getMock();
|
||||
|
||||
$request
|
||||
->method('getUserIP')
|
||||
->willReturn($ip);
|
||||
|
||||
Yii::$app->set('request', $request);
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
namespace api\tests\_support\models\authentication;
|
||||
|
||||
use api\components\ReCaptcha\Validator as ReCaptchaValidator;
|
||||
use api\models\authentication\RepeatAccountActivationForm;
|
||||
use Codeception\Specify;
|
||||
use common\models\EmailActivation;
|
||||
use common\tasks\SendRegistrationEmail;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
use Yii;
|
||||
|
||||
class RepeatAccountActivationFormTest extends TestCase {
|
||||
use Specify;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
Yii::$container->set(ReCaptchaValidator::class, new class(mock(ClientInterface::class)) extends ReCaptchaValidator {
|
||||
public function validateValue($value) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'activations' => EmailActivationFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testValidateEmailForAccount() {
|
||||
$this->specify('error.email_not_found if passed valid email, but it don\'t exists in database', function() {
|
||||
$model = new RepeatAccountActivationForm(['email' => 'me-is-not@exists.net']);
|
||||
$model->validateEmailForAccount('email');
|
||||
expect($model->getErrors('email'))->equals(['error.email_not_found']);
|
||||
});
|
||||
|
||||
$this->specify('error.account_already_activated if passed valid email, but account already activated', function() {
|
||||
$fixture = $this->tester->grabFixture('accounts', 'admin');
|
||||
$model = new RepeatAccountActivationForm(['email' => $fixture['email']]);
|
||||
$model->validateEmailForAccount('email');
|
||||
expect($model->getErrors('email'))->equals(['error.account_already_activated']);
|
||||
});
|
||||
|
||||
$this->specify('no errors if passed valid email for not activated account', function() {
|
||||
$fixture = $this->tester->grabFixture('accounts', 'not-activated-account');
|
||||
$model = new RepeatAccountActivationForm(['email' => $fixture['email']]);
|
||||
$model->validateEmailForAccount('email');
|
||||
expect($model->getErrors('email'))->isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
public function testValidateExistsActivation() {
|
||||
$this->specify('error.recently_sent_message if passed email has recently sent message', function() {
|
||||
$fixture = $this->tester->grabFixture('activations', 'freshRegistrationConfirmation');
|
||||
$model = $this->createModel(['emailKey' => $fixture['key']]);
|
||||
$model->validateExistsActivation('email');
|
||||
expect($model->getErrors('email'))->equals(['error.recently_sent_message']);
|
||||
});
|
||||
|
||||
$this->specify('no errors if passed email has expired activation message', function() {
|
||||
$fixture = $this->tester->grabFixture('activations', 'oldRegistrationConfirmation');
|
||||
$model = $this->createModel(['emailKey' => $fixture['key']]);
|
||||
$model->validateExistsActivation('email');
|
||||
expect($model->getErrors('email'))->isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
public function testSendRepeatMessage() {
|
||||
$model = new RepeatAccountActivationForm();
|
||||
$this->assertFalse($model->sendRepeatMessage(), 'no magic if we don\'t pass validation');
|
||||
$this->assertEmpty($this->tester->grabQueueJobs());
|
||||
|
||||
/** @var \common\models\Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'not-activated-account-with-expired-message');
|
||||
$model = new RepeatAccountActivationForm(['email' => $account->email]);
|
||||
$this->assertTrue($model->sendRepeatMessage());
|
||||
$activation = $model->getActivation();
|
||||
$this->assertNotNull($activation);
|
||||
/** @var SendRegistrationEmail $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(SendRegistrationEmail::class, $job);
|
||||
$this->assertSame($account->username, $job->username);
|
||||
$this->assertSame($account->email, $job->email);
|
||||
$this->assertSame($account->lang, $job->locale);
|
||||
$this->assertSame($activation->key, $job->code);
|
||||
$this->assertSame('http://localhost/activation/' . $activation->key, $job->link);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @return RepeatAccountActivationForm
|
||||
*/
|
||||
private function createModel(array $params = []) {
|
||||
return new class($params) extends RepeatAccountActivationForm {
|
||||
public $emailKey;
|
||||
|
||||
public function getActivation() {
|
||||
return EmailActivation::findOne($this->emailKey);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
27
api/tests/unit/models/base/ApiFormTest.php
Normal file
27
api/tests/unit/models/base/ApiFormTest.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace api\tests\_support\models\base;
|
||||
|
||||
use api\models\base\ApiForm;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class ApiFormTest extends TestCase {
|
||||
|
||||
public function testLoad() {
|
||||
$model = new DummyApiForm();
|
||||
$this->assertTrue($model->load(['field' => 'test-data']), 'model successful load data without prefix');
|
||||
$this->assertEquals('test-data', $model->field, 'field is set as passed data');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DummyApiForm extends ApiForm {
|
||||
|
||||
public $field;
|
||||
|
||||
public function rules() {
|
||||
return [
|
||||
['field', 'safe'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\modules\accounts\models\AcceptRulesForm;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
use const common\LATEST_RULES_VERSION;
|
||||
|
||||
class AcceptRulesFormTest extends TestCase {
|
||||
|
||||
public function testAgreeWithLatestRules() {
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class . '[save]');
|
||||
$account->shouldReceive('save')->andReturn(true);
|
||||
$account->rules_agreement_version = LATEST_RULES_VERSION - 1;
|
||||
|
||||
$model = new AcceptRulesForm($account);
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertEquals(LATEST_RULES_VERSION, $account->rules_agreement_version);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\modules\accounts\models\ChangeEmailForm;
|
||||
use common\models\Account;
|
||||
use common\models\EmailActivation;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
|
||||
class ChangeEmailFormTest extends TestCase {
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'emailActivations' => EmailActivationFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testChangeEmail() {
|
||||
/** @var Account $account */
|
||||
$account = Account::findOne($this->getAccountId());
|
||||
$newEmailConfirmationFixture = $this->tester->grabFixture('emailActivations', 'newEmailConfirmation');
|
||||
$model = new ChangeEmailForm($account, [
|
||||
'key' => $newEmailConfirmationFixture['key'],
|
||||
]);
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertNull(EmailActivation::findOne([
|
||||
'account_id' => $account->id,
|
||||
'type' => EmailActivation::TYPE_NEW_EMAIL_CONFIRMATION,
|
||||
]));
|
||||
/** @noinspection UnserializeExploitsInspection */
|
||||
$data = unserialize($newEmailConfirmationFixture['_data']);
|
||||
$this->assertEquals($data['newEmail'], $account->email);
|
||||
}
|
||||
|
||||
private function getAccountId() {
|
||||
return $this->tester->grabFixture('accounts', 'account-with-change-email-finish-state')['id'];
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\modules\accounts\models\ChangeLanguageForm;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class ChangeLanguageFormTest extends TestCase {
|
||||
|
||||
public function testApplyLanguage() {
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class . '[save]');
|
||||
$account->shouldReceive('save')->andReturn(true);
|
||||
|
||||
$model = new ChangeLanguageForm($account);
|
||||
$model->lang = 'ru';
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertEquals('ru', $account->lang);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\components\User\Component;
|
||||
use api\components\User\Identity;
|
||||
use api\modules\accounts\models\ChangePasswordForm;
|
||||
use common\components\UserPass;
|
||||
use common\helpers\Error as E;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
use Yii;
|
||||
use yii\db\Transaction;
|
||||
|
||||
class ChangePasswordFormTest extends TestCase {
|
||||
|
||||
public function testValidatePasswordAndRePasswordMatch() {
|
||||
$account = new Account();
|
||||
$account->setPassword('12345678');
|
||||
$model = new ChangePasswordForm($account, [
|
||||
'password' => '12345678',
|
||||
'newPassword' => 'my-new-password',
|
||||
'newRePassword' => 'another-password',
|
||||
]);
|
||||
$model->validatePasswordAndRePasswordMatch('newRePassword');
|
||||
$this->assertEquals(
|
||||
[E::NEW_RE_PASSWORD_DOES_NOT_MATCH],
|
||||
$model->getErrors('newRePassword'),
|
||||
'error.rePassword_does_not_match expected if passwords not match'
|
||||
);
|
||||
|
||||
$account = new Account();
|
||||
$account->setPassword('12345678');
|
||||
$model = new ChangePasswordForm($account, [
|
||||
'password' => '12345678',
|
||||
'newPassword' => 'my-new-password',
|
||||
'newRePassword' => 'my-new-password',
|
||||
]);
|
||||
$model->validatePasswordAndRePasswordMatch('newRePassword');
|
||||
$this->assertEmpty($model->getErrors('newRePassword'), 'no errors expected if passwords are valid');
|
||||
|
||||
// this is very important, because password change flow may be combined of two steps
|
||||
// therefore we need to validate password sameness before we will validate current account password
|
||||
$account = new Account();
|
||||
$account->setPassword('12345678');
|
||||
$model = new ChangePasswordForm($account, [
|
||||
'newPassword' => 'my-new-password',
|
||||
'newRePassword' => 'another-password',
|
||||
]);
|
||||
$model->validate();
|
||||
$this->assertEquals(
|
||||
[E::NEW_RE_PASSWORD_DOES_NOT_MATCH],
|
||||
$model->getErrors('newRePassword'),
|
||||
'error.rePassword_does_not_match expected even if there are errors on other attributes'
|
||||
);
|
||||
$this->assertEmpty($model->getErrors('password'));
|
||||
}
|
||||
|
||||
public function testPerformAction() {
|
||||
$component = mock(Component::class . '[terminateSessions]', [[
|
||||
'identityClass' => Identity::class,
|
||||
'enableSession' => false,
|
||||
'loginUrl' => null,
|
||||
'secret' => 'secret',
|
||||
]]);
|
||||
$component->shouldNotReceive('terminateSessions');
|
||||
|
||||
Yii::$app->set('user', $component);
|
||||
|
||||
$transaction = mock(Transaction::class . '[commit]');
|
||||
$transaction->shouldReceive('commit');
|
||||
$connection = mock(Yii::$app->db);
|
||||
$connection->shouldReceive('beginTransaction')->andReturn($transaction);
|
||||
|
||||
Yii::$app->set('db', $connection);
|
||||
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class . '[save]');
|
||||
$account->shouldReceive('save')->andReturn(true);
|
||||
$account->setPassword('password_0');
|
||||
|
||||
$model = new ChangePasswordForm($account, [
|
||||
'password' => 'password_0',
|
||||
'newPassword' => 'my-new-password',
|
||||
'newRePassword' => 'my-new-password',
|
||||
]);
|
||||
|
||||
$callTime = time();
|
||||
$this->assertTrue($model->performAction(), 'successfully change password with modern hash strategy');
|
||||
$this->assertTrue($account->validatePassword('my-new-password'), 'new password should be successfully stored into account');
|
||||
$this->assertGreaterThanOrEqual($callTime, $account->password_changed_at, 'password change time updated');
|
||||
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class . '[save]');
|
||||
$account->shouldReceive('save')->andReturn(true);
|
||||
$account->email = 'mock@ely.by';
|
||||
$account->password_hash_strategy = Account::PASS_HASH_STRATEGY_OLD_ELY;
|
||||
$account->password_hash = UserPass::make($account->email, '12345678');
|
||||
|
||||
$model = new ChangePasswordForm($account, [
|
||||
'password' => '12345678',
|
||||
'newPassword' => 'my-new-password',
|
||||
'newRePassword' => 'my-new-password',
|
||||
]);
|
||||
|
||||
$callTime = time();
|
||||
$this->assertTrue($model->performAction(), 'successfully change password with legacy hash strategy');
|
||||
$this->assertTrue($account->validatePassword('my-new-password'));
|
||||
$this->assertGreaterThanOrEqual($callTime, $account->password_changed_at);
|
||||
$this->assertEquals(Account::PASS_HASH_STRATEGY_YII2, $account->password_hash_strategy);
|
||||
}
|
||||
|
||||
public function testPerformActionWithLogout() {
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class . '[save]');
|
||||
$account->shouldReceive('save')->andReturn(true);
|
||||
$account->setPassword('password_0');
|
||||
|
||||
/** @var Component|\Mockery\MockInterface $component */
|
||||
$component = mock(Component::class . '[terminateSessions]', [[
|
||||
'identityClass' => Identity::class,
|
||||
'enableSession' => false,
|
||||
'loginUrl' => null,
|
||||
'secret' => 'secret',
|
||||
]]);
|
||||
$component->shouldReceive('terminateSessions')->once()->withArgs([$account, Component::KEEP_CURRENT_SESSION]);
|
||||
|
||||
Yii::$app->set('user', $component);
|
||||
|
||||
$model = new ChangePasswordForm($account, [
|
||||
'password' => 'password_0',
|
||||
'newPassword' => 'my-new-password',
|
||||
'newRePassword' => 'my-new-password',
|
||||
'logoutAll' => true,
|
||||
]);
|
||||
|
||||
$this->assertTrue($model->performAction());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\modules\accounts\models\ChangeUsernameForm;
|
||||
use common\models\Account;
|
||||
use common\models\UsernameHistory;
|
||||
use common\tasks\PullMojangUsername;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\UsernameHistoryFixture;
|
||||
|
||||
class ChangeUsernameFormTest extends TestCase {
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'history' => UsernameHistoryFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testPerformAction() {
|
||||
$model = new ChangeUsernameForm($this->getAccount(), [
|
||||
'password' => 'password_0',
|
||||
'username' => 'my_new_nickname',
|
||||
]);
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertEquals('my_new_nickname', Account::findOne($this->getAccountId())->username);
|
||||
$this->assertInstanceOf(UsernameHistory::class, UsernameHistory::findOne(['username' => 'my_new_nickname']));
|
||||
/** @var PullMojangUsername $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(PullMojangUsername::class, $job);
|
||||
$this->assertSame($job->username, 'my_new_nickname');
|
||||
}
|
||||
|
||||
public function testPerformActionWithTheSameUsername() {
|
||||
$account = $this->getAccount();
|
||||
$username = $account->username;
|
||||
$model = new ChangeUsernameForm($account, [
|
||||
'password' => 'password_0',
|
||||
'username' => $username,
|
||||
]);
|
||||
$callTime = time();
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertNull(UsernameHistory::findOne([
|
||||
'AND',
|
||||
'username' => $username,
|
||||
['>=', 'applied_in', $callTime],
|
||||
]), 'no new UsernameHistory record, if we don\'t change username');
|
||||
$this->assertNull($this->tester->grabLastQueuedJob());
|
||||
}
|
||||
|
||||
public function testPerformActionWithChangeCase() {
|
||||
$newUsername = mb_strtoupper($this->tester->grabFixture('accounts', 'admin')['username']);
|
||||
$model = new ChangeUsernameForm($this->getAccount(), [
|
||||
'password' => 'password_0',
|
||||
'username' => $newUsername,
|
||||
]);
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertEquals($newUsername, Account::findOne($this->getAccountId())->username);
|
||||
$this->assertInstanceOf(
|
||||
UsernameHistory::class,
|
||||
UsernameHistory::findOne(['username' => $newUsername]),
|
||||
'username should change, if we change case of some letters'
|
||||
);
|
||||
/** @var PullMojangUsername $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(PullMojangUsername::class, $job);
|
||||
$this->assertSame($job->username, $newUsername);
|
||||
}
|
||||
|
||||
private function getAccount(): Account {
|
||||
return $this->tester->grabFixture('accounts', 'admin');
|
||||
}
|
||||
|
||||
private function getAccountId() {
|
||||
return $this->getAccount()->id;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\modules\accounts\models\DisableTwoFactorAuthForm;
|
||||
use common\helpers\Error as E;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class DisableTwoFactorAuthFormTest extends TestCase {
|
||||
|
||||
public function testPerformAction() {
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class)->makePartial();
|
||||
$account->shouldReceive('save')->once()->andReturn(true);
|
||||
|
||||
$account->is_otp_enabled = true;
|
||||
$account->otp_secret = 'mock secret';
|
||||
|
||||
/** @var DisableTwoFactorAuthForm|\Mockery\MockInterface $model */
|
||||
$model = mock(DisableTwoFactorAuthForm::class . '[validate]', [$account]);
|
||||
$model->shouldReceive('validate')->once()->andReturn(true);
|
||||
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertNull($account->otp_secret);
|
||||
$this->assertFalse($account->is_otp_enabled);
|
||||
}
|
||||
|
||||
public function testValidateOtpEnabled() {
|
||||
$account = new Account();
|
||||
$account->is_otp_enabled = false;
|
||||
$model = new DisableTwoFactorAuthForm($account);
|
||||
$model->validateOtpEnabled('account');
|
||||
$this->assertEquals([E::OTP_NOT_ENABLED], $model->getErrors('account'));
|
||||
|
||||
$account = new Account();
|
||||
$account->is_otp_enabled = true;
|
||||
$model = new DisableTwoFactorAuthForm($account);
|
||||
$model->validateOtpEnabled('account');
|
||||
$this->assertEmpty($model->getErrors('account'));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\components\User\Component;
|
||||
use api\components\User\Identity;
|
||||
use api\modules\accounts\models\EnableTwoFactorAuthForm;
|
||||
use common\helpers\Error as E;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
use Yii;
|
||||
|
||||
class EnableTwoFactorAuthFormTest extends TestCase {
|
||||
|
||||
public function testPerformAction() {
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class . '[save]');
|
||||
$account->shouldReceive('save')->andReturn(true);
|
||||
$account->is_otp_enabled = false;
|
||||
$account->otp_secret = 'mock secret';
|
||||
|
||||
/** @var Component|\Mockery\MockInterface $component */
|
||||
$component = mock(Component::class . '[terminateSessions]', [[
|
||||
'identityClass' => Identity::class,
|
||||
'enableSession' => false,
|
||||
'loginUrl' => null,
|
||||
'secret' => 'secret',
|
||||
]]);
|
||||
$component->shouldReceive('terminateSessions')->withArgs([$account, Component::KEEP_CURRENT_SESSION]);
|
||||
|
||||
Yii::$app->set('user', $component);
|
||||
|
||||
/** @var EnableTwoFactorAuthForm|\Mockery\MockInterface $model */
|
||||
$model = mock(EnableTwoFactorAuthForm::class . '[validate]', [$account]);
|
||||
$model->shouldReceive('validate')->andReturn(true);
|
||||
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertTrue($account->is_otp_enabled);
|
||||
}
|
||||
|
||||
public function testValidateOtpDisabled() {
|
||||
$account = new Account();
|
||||
$account->is_otp_enabled = true;
|
||||
$model = new EnableTwoFactorAuthForm($account);
|
||||
$model->validateOtpDisabled('account');
|
||||
$this->assertEquals([E::OTP_ALREADY_ENABLED], $model->getErrors('account'));
|
||||
|
||||
$account = new Account();
|
||||
$account->is_otp_enabled = false;
|
||||
$model = new EnableTwoFactorAuthForm($account);
|
||||
$model->validateOtpDisabled('account');
|
||||
$this->assertEmpty($model->getErrors('account'));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\modules\accounts\models\SendEmailVerificationForm;
|
||||
use common\models\Account;
|
||||
use common\models\confirmations\CurrentEmailConfirmation;
|
||||
use common\models\EmailActivation;
|
||||
use common\tasks\SendCurrentEmailConfirmation;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
|
||||
class SendEmailVerificationFormTest extends TestCase {
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'emailActivations' => EmailActivationFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testCreateCode() {
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
$model = new SendEmailVerificationForm($account);
|
||||
$activationModel = $model->createCode();
|
||||
$this->assertInstanceOf(CurrentEmailConfirmation::class, $activationModel);
|
||||
$this->assertEquals($account->id, $activationModel->account_id);
|
||||
$this->assertNotNull(EmailActivation::findOne($activationModel->key));
|
||||
}
|
||||
|
||||
public function testSendCurrentEmailConfirmation() {
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
$model = new SendEmailVerificationForm($account, [
|
||||
'password' => 'password_0',
|
||||
]);
|
||||
$this->assertTrue($model->performAction());
|
||||
/** @var EmailActivation $activation */
|
||||
$activation = EmailActivation::findOne([
|
||||
'account_id' => $account->id,
|
||||
'type' => EmailActivation::TYPE_CURRENT_EMAIL_CONFIRMATION,
|
||||
]);
|
||||
$this->assertInstanceOf(EmailActivation::class, $activation);
|
||||
|
||||
/** @var SendCurrentEmailConfirmation $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(SendCurrentEmailConfirmation::class, $job);
|
||||
$this->assertSame($account->username, $job->username);
|
||||
$this->assertSame($account->email, $job->email);
|
||||
$this->assertSame($activation->key, $job->code);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\modules\accounts\models\SendNewEmailVerificationForm;
|
||||
use common\models\Account;
|
||||
use common\models\confirmations\NewEmailConfirmation;
|
||||
use common\models\EmailActivation;
|
||||
use common\tasks\SendNewEmailConfirmation;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
use common\tests\helpers\Mock;
|
||||
use yii\validators\EmailValidator;
|
||||
|
||||
class SendNewEmailVerificationFormTest extends TestCase {
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'emailActivations' => EmailActivationFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testCreateCode() {
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
$model = new SendNewEmailVerificationForm($account);
|
||||
$model->email = 'my-new-email@ely.by';
|
||||
$activationModel = $model->createCode();
|
||||
$this->assertInstanceOf(NewEmailConfirmation::class, $activationModel);
|
||||
$this->assertEquals($account->id, $activationModel->account_id);
|
||||
$this->assertEquals($model->email, $activationModel->newEmail);
|
||||
$this->assertNotNull(EmailActivation::findOne($activationModel->key));
|
||||
}
|
||||
|
||||
public function testSendNewEmailConfirmation() {
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'account-with-change-email-init-state');
|
||||
/** @var SendNewEmailVerificationForm $model */
|
||||
$key = $this->tester->grabFixture('emailActivations', 'currentChangeEmailConfirmation')['key'];
|
||||
$model = new SendNewEmailVerificationForm($account, [
|
||||
'key' => $key,
|
||||
'email' => 'my-new-email@ely.by',
|
||||
]);
|
||||
Mock::func(EmailValidator::class, 'checkdnsrr')->andReturn(true);
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertNull(EmailActivation::findOne($key));
|
||||
/** @var EmailActivation $activation */
|
||||
$activation = EmailActivation::findOne([
|
||||
'account_id' => $account->id,
|
||||
'type' => EmailActivation::TYPE_NEW_EMAIL_CONFIRMATION,
|
||||
]);
|
||||
$this->assertNotNull(EmailActivation::class, $activation);
|
||||
|
||||
/** @var SendNewEmailConfirmation $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(SendNewEmailConfirmation::class, $job);
|
||||
$this->assertSame($account->username, $job->username);
|
||||
$this->assertSame('my-new-email@ely.by', $job->email);
|
||||
$this->assertSame($activation->key, $job->code);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\accounts\models;
|
||||
|
||||
use api\modules\accounts\models\TwoFactorAuthInfo;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class TwoFactorAuthInfoTest extends TestCase {
|
||||
|
||||
public function testGetCredentials() {
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class . '[save]');
|
||||
$account->shouldReceive('save')->andReturn(true);
|
||||
|
||||
$account->email = 'mock@email.com';
|
||||
$account->otp_secret = null;
|
||||
|
||||
$model = new TwoFactorAuthInfo($account);
|
||||
|
||||
$result = $model->getCredentials();
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertArrayHasKey('qr', $result);
|
||||
$this->assertArrayHasKey('uri', $result);
|
||||
$this->assertArrayHasKey('secret', $result);
|
||||
$this->assertSame($account->otp_secret, $result['secret']);
|
||||
$this->assertSame(strtoupper($account->otp_secret), $account->otp_secret);
|
||||
$this->assertStringStartsWith('data:image/svg+xml,<?xml', $result['qr']);
|
||||
|
||||
$previous = libxml_use_internal_errors(true);
|
||||
simplexml_load_string(base64_decode($result['qr']));
|
||||
libxml_use_internal_errors($previous);
|
||||
$this->assertEmpty(libxml_get_errors());
|
||||
|
||||
/** @var Account|\Mockery\MockInterface $account */
|
||||
$account = mock(Account::class . '[save]');
|
||||
$account->shouldReceive('save')->andReturn(true);
|
||||
|
||||
$account->email = 'mock@email.com';
|
||||
$account->otp_secret = 'AAAA';
|
||||
|
||||
$model = new TwoFactorAuthInfo($account);
|
||||
|
||||
$result = $model->getCredentials();
|
||||
$this->assertEquals('AAAA', $result['secret']);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\modules\authserver\models;
|
||||
|
||||
use api\models\authentication\LoginForm;
|
||||
use api\modules\authserver\models\AuthenticateData;
|
||||
use api\modules\authserver\models\AuthenticationForm;
|
||||
use common\models\Account;
|
||||
use common\models\MinecraftAccessKey;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\_support\ProtectedCaller;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
use common\tests\fixtures\MinecraftAccessKeyFixture;
|
||||
|
||||
class AuthenticationFormTest extends TestCase {
|
||||
use ProtectedCaller;
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
'minecraftAccessKeys' => MinecraftAccessKeyFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \api\modules\authserver\exceptions\ForbiddenOperationException
|
||||
* @expectedExceptionMessage Invalid credentials. Invalid nickname or password.
|
||||
*/
|
||||
public function testAuthenticateByWrongNicknamePass() {
|
||||
$authForm = $this->createAuthForm();
|
||||
|
||||
$authForm->username = 'wrong-username';
|
||||
$authForm->password = 'wrong-password';
|
||||
$authForm->clientToken = Uuid::uuid4();
|
||||
|
||||
$authForm->authenticate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \api\modules\authserver\exceptions\ForbiddenOperationException
|
||||
* @expectedExceptionMessage Invalid credentials. Invalid email or password.
|
||||
*/
|
||||
public function testAuthenticateByWrongEmailPass() {
|
||||
$authForm = $this->createAuthForm();
|
||||
|
||||
$authForm->username = 'wrong-email@ely.by';
|
||||
$authForm->password = 'wrong-password';
|
||||
$authForm->clientToken = Uuid::uuid4();
|
||||
|
||||
$authForm->authenticate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \api\modules\authserver\exceptions\ForbiddenOperationException
|
||||
* @expectedExceptionMessage This account has been suspended.
|
||||
*/
|
||||
public function testAuthenticateByValidCredentialsIntoBlockedAccount() {
|
||||
$authForm = $this->createAuthForm(Account::STATUS_BANNED);
|
||||
|
||||
$authForm->username = 'dummy';
|
||||
$authForm->password = 'password_0';
|
||||
$authForm->clientToken = Uuid::uuid4();
|
||||
|
||||
$authForm->authenticate();
|
||||
}
|
||||
|
||||
public function testAuthenticateByValidCredentials() {
|
||||
$authForm = $this->createAuthForm();
|
||||
|
||||
$minecraftAccessKey = new MinecraftAccessKey();
|
||||
$minecraftAccessKey->access_token = Uuid::uuid4();
|
||||
$authForm->expects($this->once())
|
||||
->method('createMinecraftAccessToken')
|
||||
->will($this->returnValue($minecraftAccessKey));
|
||||
|
||||
$authForm->username = 'dummy';
|
||||
$authForm->password = 'password_0';
|
||||
$authForm->clientToken = Uuid::uuid4();
|
||||
|
||||
$result = $authForm->authenticate();
|
||||
$this->assertInstanceOf(AuthenticateData::class, $result);
|
||||
$this->assertEquals($minecraftAccessKey->access_token, $result->getMinecraftAccessKey()->access_token);
|
||||
}
|
||||
|
||||
public function testCreateMinecraftAccessToken() {
|
||||
$authForm = new AuthenticationForm();
|
||||
$authForm->clientToken = Uuid::uuid4();
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
/** @var MinecraftAccessKey $result */
|
||||
$result = $this->callProtected($authForm, 'createMinecraftAccessToken', $account);
|
||||
$this->assertInstanceOf(MinecraftAccessKey::class, $result);
|
||||
$this->assertEquals($account->id, $result->account_id);
|
||||
$this->assertEquals($authForm->clientToken, $result->client_token);
|
||||
$this->assertInstanceOf(MinecraftAccessKey::class, MinecraftAccessKey::findOne($result->access_token));
|
||||
}
|
||||
|
||||
public function testCreateMinecraftAccessTokenWithExistsClientId() {
|
||||
$authForm = new AuthenticationForm();
|
||||
$minecraftFixture = $this->tester->grabFixture('minecraftAccessKeys', 'admin-token');
|
||||
$authForm->clientToken = $minecraftFixture['client_token'];
|
||||
/** @var Account $account */
|
||||
$account = $this->tester->grabFixture('accounts', 'admin');
|
||||
/** @var MinecraftAccessKey $result */
|
||||
$result = $this->callProtected($authForm, 'createMinecraftAccessToken', $account);
|
||||
$this->assertInstanceOf(MinecraftAccessKey::class, $result);
|
||||
$this->assertEquals($account->id, $result->account_id);
|
||||
$this->assertEquals($authForm->clientToken, $result->client_token);
|
||||
$this->assertNull(MinecraftAccessKey::findOne($minecraftFixture['access_token']));
|
||||
$this->assertInstanceOf(MinecraftAccessKey::class, MinecraftAccessKey::findOne($result->access_token));
|
||||
}
|
||||
|
||||
private function createAuthForm($status = Account::STATUS_ACTIVE) {
|
||||
/** @var LoginForm|\PHPUnit_Framework_MockObject_MockObject $loginForm */
|
||||
$loginForm = $this->getMockBuilder(LoginForm::class)
|
||||
->setMethods(['getAccount'])
|
||||
->getMock();
|
||||
|
||||
$account = new Account();
|
||||
$account->username = 'dummy';
|
||||
$account->email = 'dummy@ely.by';
|
||||
$account->status = $status;
|
||||
$account->setPassword('password_0');
|
||||
|
||||
$loginForm->expects($this->any())
|
||||
->method('getAccount')
|
||||
->will($this->returnValue($account));
|
||||
|
||||
/** @var AuthenticationForm|\PHPUnit_Framework_MockObject_MockObject $authForm */
|
||||
$authForm = $this->getMockBuilder(AuthenticationForm::class)
|
||||
->setMethods(['createLoginForm', 'createMinecraftAccessToken'])
|
||||
->getMock();
|
||||
|
||||
$authForm->expects($this->any())
|
||||
->method('createLoginForm')
|
||||
->will($this->returnValue($loginForm));
|
||||
|
||||
return $authForm;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\modules\authserver\validators;
|
||||
|
||||
use api\modules\authserver\validators\RequiredValidator;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\_support\ProtectedCaller;
|
||||
|
||||
class RequiredValidatorTest extends TestCase {
|
||||
use ProtectedCaller;
|
||||
|
||||
public function testValidateValueNormal() {
|
||||
$validator = new RequiredValidator();
|
||||
$this->assertNull($this->callProtected($validator, 'validateValue', 'dummy'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \api\modules\authserver\exceptions\IllegalArgumentException
|
||||
*/
|
||||
public function testValidateValueEmpty() {
|
||||
$validator = new RequiredValidator();
|
||||
$this->assertNull($this->callProtected($validator, 'validateValue', ''));
|
||||
}
|
||||
|
||||
}
|
45
api/tests/unit/modules/internal/models/BanFormTest.php
Normal file
45
api/tests/unit/modules/internal/models/BanFormTest.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\internal\models;
|
||||
|
||||
use api\modules\accounts\models\BanAccountForm;
|
||||
use api\modules\internal\helpers\Error as E;
|
||||
use common\models\Account;
|
||||
use common\tasks\ClearAccountSessions;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class BanFormTest extends TestCase {
|
||||
|
||||
public function testValidateAccountActivity() {
|
||||
$account = new Account();
|
||||
$account->status = Account::STATUS_ACTIVE;
|
||||
$form = new BanAccountForm($account);
|
||||
$form->validateAccountActivity();
|
||||
$this->assertEmpty($form->getErrors('account'));
|
||||
|
||||
$account = new Account();
|
||||
$account->status = Account::STATUS_BANNED;
|
||||
$form = new BanAccountForm($account);
|
||||
$form->validateAccountActivity();
|
||||
$this->assertEquals([E::ACCOUNT_ALREADY_BANNED], $form->getErrors('account'));
|
||||
}
|
||||
|
||||
public function testBan() {
|
||||
/** @var Account|\PHPUnit_Framework_MockObject_MockObject $account */
|
||||
$account = $this->getMockBuilder(Account::class)
|
||||
->setMethods(['save'])
|
||||
->getMock();
|
||||
|
||||
$account->expects($this->once())
|
||||
->method('save')
|
||||
->willReturn(true);
|
||||
|
||||
$model = new BanAccountForm($account);
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertEquals(Account::STATUS_BANNED, $account->status);
|
||||
/** @var ClearAccountSessions $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(ClearAccountSessions::class, $job);
|
||||
$this->assertSame($job->accountId, $account->id);
|
||||
}
|
||||
|
||||
}
|
41
api/tests/unit/modules/internal/models/PardonFormTest.php
Normal file
41
api/tests/unit/modules/internal/models/PardonFormTest.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\internal\models;
|
||||
|
||||
use api\modules\accounts\models\PardonAccountForm;
|
||||
use api\modules\internal\helpers\Error as E;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class PardonFormTest extends TestCase {
|
||||
|
||||
public function testValidateAccountBanned() {
|
||||
$account = new Account();
|
||||
$account->status = Account::STATUS_BANNED;
|
||||
$form = new PardonAccountForm($account);
|
||||
$form->validateAccountBanned();
|
||||
$this->assertEmpty($form->getErrors('account'));
|
||||
|
||||
$account = new Account();
|
||||
$account->status = Account::STATUS_ACTIVE;
|
||||
$form = new PardonAccountForm($account);
|
||||
$form->validateAccountBanned();
|
||||
$this->assertEquals([E::ACCOUNT_NOT_BANNED], $form->getErrors('account'));
|
||||
}
|
||||
|
||||
public function testPardon() {
|
||||
/** @var Account|\PHPUnit_Framework_MockObject_MockObject $account */
|
||||
$account = $this->getMockBuilder(Account::class)
|
||||
->setMethods(['save'])
|
||||
->getMock();
|
||||
|
||||
$account->expects($this->once())
|
||||
->method('save')
|
||||
->willReturn(true);
|
||||
|
||||
$account->status = Account::STATUS_BANNED;
|
||||
$model = new PardonAccountForm($account);
|
||||
$this->assertTrue($model->performAction());
|
||||
$this->assertEquals(Account::STATUS_ACTIVE, $account->status);
|
||||
}
|
||||
|
||||
}
|
27
api/tests/unit/modules/oauth/models/ApplicationTypeTest.php
Normal file
27
api/tests/unit/modules/oauth/models/ApplicationTypeTest.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\oauth\models;
|
||||
|
||||
use api\modules\oauth\models\ApplicationType;
|
||||
use common\models\OauthClient;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class ApplicationTypeTest extends TestCase {
|
||||
|
||||
public function testApplyToClient(): void {
|
||||
$model = new ApplicationType();
|
||||
$model->name = 'Application name';
|
||||
$model->websiteUrl = 'http://example.com';
|
||||
$model->redirectUri = 'http://example.com/oauth/ely';
|
||||
$model->description = 'Application description.';
|
||||
|
||||
$client = new OauthClient();
|
||||
|
||||
$model->applyToClient($client);
|
||||
|
||||
$this->assertSame('Application name', $client->name);
|
||||
$this->assertSame('Application description.', $client->description);
|
||||
$this->assertSame('http://example.com/oauth/ely', $client->redirect_uri);
|
||||
$this->assertSame('http://example.com', $client->website_url);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\oauth\models;
|
||||
|
||||
use api\modules\oauth\models\BaseOauthClientType;
|
||||
use common\models\OauthClient;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class BaseOauthClientTypeTest extends TestCase {
|
||||
|
||||
public function testApplyTyClient(): void {
|
||||
$client = new OauthClient();
|
||||
|
||||
/** @var BaseOauthClientType|\Mockery\MockInterface $form */
|
||||
$form = mock(BaseOauthClientType::class);
|
||||
$form->makePartial();
|
||||
$form->name = 'Application name';
|
||||
$form->websiteUrl = 'http://example.com';
|
||||
|
||||
$form->applyToClient($client);
|
||||
$this->assertSame('Application name', $client->name);
|
||||
$this->assertSame('http://example.com', $client->website_url);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\oauth\models;
|
||||
|
||||
use api\modules\oauth\models\MinecraftServerType;
|
||||
use common\models\OauthClient;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class MinecraftServerTypeTest extends TestCase {
|
||||
|
||||
public function testApplyToClient(): void {
|
||||
$model = new MinecraftServerType();
|
||||
$model->name = 'Server name';
|
||||
$model->websiteUrl = 'http://example.com';
|
||||
$model->minecraftServerIp = 'localhost:12345';
|
||||
|
||||
$client = new OauthClient();
|
||||
|
||||
$model->applyToClient($client);
|
||||
|
||||
$this->assertSame('Server name', $client->name);
|
||||
$this->assertSame('http://example.com', $client->website_url);
|
||||
$this->assertSame('localhost:12345', $client->minecraft_server_ip);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\oauth\models;
|
||||
|
||||
use api\modules\oauth\models\ApplicationType;
|
||||
use api\modules\oauth\models\MinecraftServerType;
|
||||
use api\modules\oauth\models\OauthClientFormFactory;
|
||||
use common\models\OauthClient;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class OauthClientFormFactoryTest extends TestCase {
|
||||
|
||||
public function testCreate() {
|
||||
$client = new OauthClient();
|
||||
$client->type = OauthClient::TYPE_APPLICATION;
|
||||
$client->name = 'Application name';
|
||||
$client->description = 'Application description.';
|
||||
$client->website_url = 'http://example.com';
|
||||
$client->redirect_uri = 'http://example.com/oauth/ely';
|
||||
/** @var ApplicationType $requestForm */
|
||||
$requestForm = OauthClientFormFactory::create($client);
|
||||
$this->assertInstanceOf(ApplicationType::class, $requestForm);
|
||||
$this->assertSame('Application name', $requestForm->name);
|
||||
$this->assertSame('Application description.', $requestForm->description);
|
||||
$this->assertSame('http://example.com', $requestForm->websiteUrl);
|
||||
$this->assertSame('http://example.com/oauth/ely', $requestForm->redirectUri);
|
||||
|
||||
$client = new OauthClient();
|
||||
$client->type = OauthClient::TYPE_MINECRAFT_SERVER;
|
||||
$client->name = 'Server name';
|
||||
$client->website_url = 'http://example.com';
|
||||
$client->minecraft_server_ip = 'localhost:12345';
|
||||
/** @var MinecraftServerType $requestForm */
|
||||
$requestForm = OauthClientFormFactory::create($client);
|
||||
$this->assertInstanceOf(MinecraftServerType::class, $requestForm);
|
||||
$this->assertSame('Server name', $requestForm->name);
|
||||
$this->assertSame('http://example.com', $requestForm->websiteUrl);
|
||||
$this->assertSame('localhost:12345', $requestForm->minecraftServerIp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \api\modules\oauth\exceptions\UnsupportedOauthClientType
|
||||
*/
|
||||
public function testCreateUnknownType() {
|
||||
$client = new OauthClient();
|
||||
$client->type = 'unknown-type';
|
||||
OauthClientFormFactory::create($client);
|
||||
}
|
||||
|
||||
}
|
138
api/tests/unit/modules/oauth/models/OauthClientFormTest.php
Normal file
138
api/tests/unit/modules/oauth/models/OauthClientFormTest.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
namespace api\tests\unit\modules\oauth\models;
|
||||
|
||||
use api\modules\oauth\models\OauthClientForm;
|
||||
use api\modules\oauth\models\OauthClientTypeForm;
|
||||
use common\models\OauthClient;
|
||||
use common\tasks\ClearOauthSessions;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class OauthClientFormTest extends TestCase {
|
||||
|
||||
public function testSave() {
|
||||
/** @var OauthClient|\Mockery\MockInterface $client */
|
||||
$client = mock(OauthClient::class . '[save]');
|
||||
$client->shouldReceive('save')->andReturn(true);
|
||||
$client->account_id = 1;
|
||||
$client->type = OauthClient::TYPE_APPLICATION;
|
||||
$client->name = 'Test application';
|
||||
|
||||
/** @var OauthClientForm|\Mockery\MockInterface $form */
|
||||
$form = mock(OauthClientForm::class . '[isClientExists]', [$client]);
|
||||
$form->shouldAllowMockingProtectedMethods();
|
||||
$form->shouldReceive('isClientExists')
|
||||
->times(3)
|
||||
->andReturnValues([true, true, false]);
|
||||
|
||||
/** @var OauthClientTypeForm|\Mockery\MockInterface $requestType */
|
||||
$requestType = mock(OauthClientTypeForm::class);
|
||||
$requestType->shouldReceive('validate')->once()->andReturn(true);
|
||||
$requestType->shouldReceive('applyToClient')->once()->withArgs([$client]);
|
||||
|
||||
$this->assertTrue($form->save($requestType));
|
||||
$this->assertSame('test-application2', $client->id);
|
||||
$this->assertNotNull($client->secret);
|
||||
$this->assertSame(64, mb_strlen($client->secret));
|
||||
}
|
||||
|
||||
public function testSaveUpdateExistsModel() {
|
||||
/** @var OauthClient|\Mockery\MockInterface $client */
|
||||
$client = mock(OauthClient::class . '[save]');
|
||||
$client->shouldReceive('save')->andReturn(true);
|
||||
$client->setIsNewRecord(false);
|
||||
$client->id = 'application-id';
|
||||
$client->secret = 'application_secret';
|
||||
$client->account_id = 1;
|
||||
$client->type = OauthClient::TYPE_APPLICATION;
|
||||
$client->name = 'Application name';
|
||||
$client->description = 'Application description';
|
||||
$client->redirect_uri = 'http://example.com/oauth/ely';
|
||||
$client->website_url = 'http://example.com';
|
||||
|
||||
/** @var OauthClientForm|\Mockery\MockInterface $form */
|
||||
$form = mock(OauthClientForm::class . '[isClientExists]', [$client]);
|
||||
$form->shouldAllowMockingProtectedMethods();
|
||||
$form->shouldReceive('isClientExists')->andReturn(false);
|
||||
|
||||
$request = new class implements OauthClientTypeForm {
|
||||
public function load($data): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getValidationErrors(): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
public function applyToClient(OauthClient $client): void {
|
||||
$client->name = 'New name';
|
||||
$client->description = 'New description.';
|
||||
}
|
||||
};
|
||||
|
||||
$this->assertTrue($form->save($request));
|
||||
$this->assertSame('application-id', $client->id);
|
||||
$this->assertSame('application_secret', $client->secret);
|
||||
$this->assertSame('New name', $client->name);
|
||||
$this->assertSame('New description.', $client->description);
|
||||
$this->assertSame('http://example.com/oauth/ely', $client->redirect_uri);
|
||||
$this->assertSame('http://example.com', $client->website_url);
|
||||
}
|
||||
|
||||
public function testDelete() {
|
||||
/** @var OauthClient|\Mockery\MockInterface $client */
|
||||
$client = mock(OauthClient::class . '[save]');
|
||||
$client->id = 'mocked-id';
|
||||
$client->type = OauthClient::TYPE_APPLICATION;
|
||||
$client->shouldReceive('save')->andReturn(true);
|
||||
|
||||
$form = new OauthClientForm($client);
|
||||
$this->assertTrue($form->delete());
|
||||
$this->assertTrue($form->getClient()->is_deleted);
|
||||
/** @var ClearOauthSessions $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(ClearOauthSessions::class, $job);
|
||||
$this->assertSame('mocked-id', $job->clientId);
|
||||
$this->assertNull($job->notSince);
|
||||
}
|
||||
|
||||
public function testReset() {
|
||||
/** @var OauthClient|\Mockery\MockInterface $client */
|
||||
$client = mock(OauthClient::class . '[save]');
|
||||
$client->id = 'mocked-id';
|
||||
$client->secret = 'initial_secret';
|
||||
$client->type = OauthClient::TYPE_APPLICATION;
|
||||
$client->shouldReceive('save')->andReturn(true);
|
||||
|
||||
$form = new OauthClientForm($client);
|
||||
$this->assertTrue($form->reset());
|
||||
$this->assertSame('initial_secret', $form->getClient()->secret);
|
||||
/** @var ClearOauthSessions $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(ClearOauthSessions::class, $job);
|
||||
$this->assertSame('mocked-id', $job->clientId);
|
||||
$this->assertEquals(time(), $job->notSince, '', 2);
|
||||
}
|
||||
|
||||
public function testResetWithSecret() {
|
||||
/** @var OauthClient|\Mockery\MockInterface $client */
|
||||
$client = mock(OauthClient::class . '[save]');
|
||||
$client->id = 'mocked-id';
|
||||
$client->secret = 'initial_secret';
|
||||
$client->type = OauthClient::TYPE_APPLICATION;
|
||||
$client->shouldReceive('save')->andReturn(true);
|
||||
|
||||
$form = new OauthClientForm($client);
|
||||
$this->assertTrue($form->reset(true));
|
||||
$this->assertNotSame('initial_secret', $form->getClient()->secret);
|
||||
/** @var ClearOauthSessions $job */
|
||||
$job = $this->tester->grabLastQueuedJob();
|
||||
$this->assertInstanceOf(ClearOauthSessions::class, $job);
|
||||
$this->assertSame('mocked-id', $job->clientId);
|
||||
$this->assertEquals(time(), $job->notSince, '', 2);
|
||||
}
|
||||
|
||||
}
|
106
api/tests/unit/modules/session/filters/RateLimiterTest.php
Normal file
106
api/tests/unit/modules/session/filters/RateLimiterTest.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace api\tests\unit\modules\session\filters;
|
||||
|
||||
use api\modules\session\filters\RateLimiter;
|
||||
use common\models\OauthClient;
|
||||
use Faker\Provider\Internet;
|
||||
use api\tests\unit\TestCase;
|
||||
use Yii;
|
||||
use yii\redis\Connection;
|
||||
use yii\web\Request;
|
||||
|
||||
class RateLimiterTest extends TestCase {
|
||||
|
||||
public function testCheckRateLimiterWithOldAuthserver() {
|
||||
/** @var Connection|\PHPUnit\Framework\MockObject\MockObject $redis */
|
||||
$redis = $this->getMockBuilder(Connection::class)
|
||||
->setMethods(['executeCommand'])
|
||||
->getMock();
|
||||
|
||||
$redis->expects($this->never())
|
||||
->method('executeCommand');
|
||||
|
||||
Yii::$app->set('redis', $redis);
|
||||
|
||||
/** @var RateLimiter|\PHPUnit\Framework\MockObject\MockObject $filter */
|
||||
$filter = $this->getMockBuilder(RateLimiter::class)
|
||||
->setConstructorArgs([[
|
||||
'authserverDomain' => 'authserver.ely.by',
|
||||
]])
|
||||
->setMethods(['getServer'])
|
||||
->getMock();
|
||||
|
||||
$filter->method('getServer')
|
||||
->willReturn(new OauthClient());
|
||||
|
||||
$filter->checkRateLimit(null, new Request(), null, null);
|
||||
}
|
||||
|
||||
public function testCheckRateLimiterWithValidServerId() {
|
||||
/** @var Connection|\PHPUnit\Framework\MockObject\MockObject $redis */
|
||||
$redis = $this->getMockBuilder(Connection::class)
|
||||
->setMethods(['executeCommand'])
|
||||
->getMock();
|
||||
|
||||
$redis->expects($this->never())
|
||||
->method('executeCommand');
|
||||
|
||||
Yii::$app->set('redis', $redis);
|
||||
|
||||
/** @var Request|\PHPUnit\Framework\MockObject\MockObject $request */
|
||||
$request = $this->getMockBuilder(Request::class)
|
||||
->setMethods(['getHostInfo'])
|
||||
->getMock();
|
||||
|
||||
$request->method('getHostInfo')
|
||||
->willReturn('http://authserver.ely.by');
|
||||
|
||||
$filter = new RateLimiter([
|
||||
'authserverDomain' => 'authserver.ely.by',
|
||||
]);
|
||||
$filter->checkRateLimit(null, $request, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \yii\web\TooManyRequestsHttpException
|
||||
*/
|
||||
public function testCheckRateLimiter() {
|
||||
/** @var Connection|\PHPUnit\Framework\MockObject\MockObject $redis */
|
||||
$redis = $this->getMockBuilder(Connection::class)
|
||||
->setMethods(['executeCommand'])
|
||||
->getMock();
|
||||
|
||||
$redis->expects($this->exactly(5))
|
||||
->method('executeCommand')
|
||||
->will($this->onConsecutiveCalls('1', '1', '2', '3', '4'));
|
||||
|
||||
Yii::$app->set('redis', $redis);
|
||||
|
||||
/** @var Request|\PHPUnit\Framework\MockObject\MockObject $request */
|
||||
$request = $this->getMockBuilder(Request::class)
|
||||
->setMethods(['getUserIP'])
|
||||
->getMock();
|
||||
|
||||
$request->method('getUserIp')
|
||||
->willReturn(Internet::localIpv4());
|
||||
|
||||
/** @var RateLimiter|\PHPUnit\Framework\MockObject\MockObject $filter */
|
||||
$filter = $this->getMockBuilder(RateLimiter::class)
|
||||
->setConstructorArgs([[
|
||||
'limit' => 3,
|
||||
'authserverDomain' => 'authserver.ely.by',
|
||||
]])
|
||||
->setMethods(['getServer'])
|
||||
->getMock();
|
||||
|
||||
$filter->method('getServer')
|
||||
->willReturn(null);
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$filter->checkRateLimit(null, $request, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
20
api/tests/unit/request/RequestParserTest.php
Normal file
20
api/tests/unit/request/RequestParserTest.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace api\tests\unit\request;
|
||||
|
||||
use api\request\RequestParser;
|
||||
use api\tests\unit\TestCase;
|
||||
|
||||
class RequestParserTest extends TestCase {
|
||||
|
||||
public function testParse() {
|
||||
$parser = new RequestParser();
|
||||
$_POST = ['from' => 'post'];
|
||||
$this->assertEquals(['from' => 'post'], $parser->parse('from=post', ''));
|
||||
$this->assertEquals(['from' => 'post'], $parser->parse('', ''));
|
||||
$_POST = [];
|
||||
$this->assertEquals(['from' => 'json'], $parser->parse('{"from":"json"}', ''));
|
||||
$this->assertEquals(['from' => 'body'], $parser->parse('from=body', ''));
|
||||
$this->assertEquals(['onlykey' => ''], $parser->parse('onlykey', ''));
|
||||
}
|
||||
|
||||
}
|
54
api/tests/unit/traits/AccountFinderTest.php
Normal file
54
api/tests/unit/traits/AccountFinderTest.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace api\tests\_support\traits;
|
||||
|
||||
use api\traits\AccountFinder;
|
||||
use Codeception\Specify;
|
||||
use common\models\Account;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\fixtures\AccountFixture;
|
||||
|
||||
class AccountFinderTest extends TestCase {
|
||||
use Specify;
|
||||
|
||||
public function _fixtures() {
|
||||
return [
|
||||
'accounts' => AccountFixture::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function testGetAccount() {
|
||||
$model = new AccountFinderTestTestClass();
|
||||
/** @var Account $account */
|
||||
$accountFixture = $this->tester->grabFixture('accounts', 'admin');
|
||||
$model->login = $accountFixture->email;
|
||||
$account = $model->getAccount();
|
||||
$this->assertInstanceOf(Account::class, $account);
|
||||
$this->assertSame($accountFixture->id, $account->id, 'founded account for passed login data');
|
||||
|
||||
$model = new AccountFinderTestTestClass();
|
||||
$model->login = 'unexpected';
|
||||
$this->assertNull($account = $model->getAccount(), 'null, if account can\'t be found');
|
||||
}
|
||||
|
||||
public function testGetLoginAttribute() {
|
||||
$model = new AccountFinderTestTestClass();
|
||||
$model->login = 'erickskrauch@ely.by';
|
||||
$this->assertEquals('email', $model->getLoginAttribute(), 'if login look like email value, then \'email\'');
|
||||
|
||||
$model = new AccountFinderTestTestClass();
|
||||
$model->login = 'erickskrauch';
|
||||
$this->assertEquals('username', $model->getLoginAttribute(), 'username in any other case');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AccountFinderTestTestClass {
|
||||
use AccountFinder;
|
||||
|
||||
public $login;
|
||||
|
||||
public function getLogin(): string {
|
||||
return $this->login;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\validators;
|
||||
|
||||
use api\validators\EmailActivationKeyValidator;
|
||||
use Codeception\Specify;
|
||||
use common\helpers\Error as E;
|
||||
use common\models\confirmations\ForgotPassword;
|
||||
use common\models\EmailActivation;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\_support\ProtectedCaller;
|
||||
use common\tests\fixtures\EmailActivationFixture;
|
||||
use yii\base\Model;
|
||||
|
||||
class EmailActivationKeyValidatorTest extends TestCase {
|
||||
use Specify;
|
||||
use ProtectedCaller;
|
||||
|
||||
public function testValidateAttribute() {
|
||||
/** @var Model $model */
|
||||
$model = new class extends Model {
|
||||
public $key;
|
||||
};
|
||||
|
||||
/** @var EmailActivationKeyValidator|\PHPUnit_Framework_MockObject_MockObject $validator */
|
||||
$validator = $this->getMockBuilder(EmailActivationKeyValidator::class)
|
||||
->setMethods(['findEmailActivationModel'])
|
||||
->getMock();
|
||||
|
||||
$expiredActivation = new ForgotPassword();
|
||||
$expiredActivation->created_at = time() - $expiredActivation->expirationTimeout - 10;
|
||||
|
||||
$validActivation = new EmailActivation();
|
||||
|
||||
$validator->expects($this->exactly(3))
|
||||
->method('findEmailActivationModel')
|
||||
->willReturnOnConsecutiveCalls(null, $expiredActivation, $validActivation);
|
||||
|
||||
$validator->validateAttribute($model, 'key');
|
||||
$this->assertEquals([E::KEY_REQUIRED], $model->getErrors('key'));
|
||||
$this->assertNull($model->key);
|
||||
|
||||
$model->clearErrors();
|
||||
$model->key = 'original value';
|
||||
$validator->validateAttribute($model, 'key');
|
||||
$this->assertEquals([E::KEY_NOT_EXISTS], $model->getErrors('key'));
|
||||
$this->assertEquals('original value', $model->key);
|
||||
|
||||
$model->clearErrors();
|
||||
$validator->validateAttribute($model, 'key');
|
||||
$this->assertEquals([E::KEY_EXPIRE], $model->getErrors('key'));
|
||||
$this->assertEquals('original value', $model->key);
|
||||
|
||||
$model->clearErrors();
|
||||
$validator->validateAttribute($model, 'key');
|
||||
$this->assertEmpty($model->getErrors('key'));
|
||||
$this->assertEquals($validActivation, $model->key);
|
||||
}
|
||||
|
||||
public function testFindEmailActivationModel() {
|
||||
$this->tester->haveFixtures(['emailActivations' => EmailActivationFixture::class]);
|
||||
|
||||
$key = $this->tester->grabFixture('emailActivations', 'freshRegistrationConfirmation')['key'];
|
||||
$model = new EmailActivationKeyValidator();
|
||||
/** @var EmailActivation $result */
|
||||
$result = $this->callProtected($model, 'findEmailActivationModel', $key);
|
||||
$this->assertInstanceOf(EmailActivation::class, $result, 'valid key without specifying type must return model');
|
||||
$this->assertEquals($key, $result->key);
|
||||
|
||||
/** @var EmailActivation $result */
|
||||
$result = $this->callProtected($model, 'findEmailActivationModel', $key, 0);
|
||||
$this->assertInstanceOf(EmailActivation::class, $result, 'valid key with valid type must return model');
|
||||
|
||||
/** @var EmailActivation $result */
|
||||
$result = $this->callProtected($model, 'findEmailActivationModel', $key, 1);
|
||||
$this->assertNull($result, 'valid key, but invalid type must return null');
|
||||
|
||||
$model = new EmailActivationKeyValidator();
|
||||
$result = $this->callProtected($model, 'findEmailActivationModel', 'invalid-key');
|
||||
$this->assertNull($result, 'invalid key must return null');
|
||||
}
|
||||
|
||||
}
|
36
api/tests/unit/validators/PasswordRequiredValidatorTest.php
Normal file
36
api/tests/unit/validators/PasswordRequiredValidatorTest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace codeception\api\unit\validators;
|
||||
|
||||
use api\validators\PasswordRequiredValidator;
|
||||
use common\helpers\Error as E;
|
||||
use common\models\Account;
|
||||
use common\rbac\Permissions as P;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\_support\ProtectedCaller;
|
||||
use yii\web\User;
|
||||
|
||||
class PasswordRequiredValidatorTest extends TestCase {
|
||||
use ProtectedCaller;
|
||||
|
||||
public function testValidateValue() {
|
||||
$account = new Account(['password' => '12345678']);
|
||||
$model = new PasswordRequiredValidator(['account' => $account]);
|
||||
|
||||
// Get error.password_required if password is empty
|
||||
$this->assertEquals([E::PASSWORD_REQUIRED, []], $this->callProtected($model, 'validateValue', ''));
|
||||
|
||||
// Get error.password_incorrect if password is incorrect
|
||||
$this->assertEquals([E::PASSWORD_INCORRECT, []], $this->callProtected($model, 'validateValue', '87654321'));
|
||||
|
||||
// No errors, if password is correct for provided account
|
||||
$this->assertNull($this->callProtected($model, 'validateValue', '12345678'));
|
||||
|
||||
// Skip validation if user can skip identity verification
|
||||
/** @var User|\Mockery\MockInterface $component */
|
||||
$component = mock(User::class . '[can]', [['identityClass' => '']]);
|
||||
$component->shouldReceive('can')->withArgs([P::ESCAPE_IDENTITY_VERIFICATION])->andReturn(true);
|
||||
$model->user = $component;
|
||||
$this->assertNull($this->callProtected($model, 'validateValue', ''));
|
||||
}
|
||||
|
||||
}
|
57
api/tests/unit/validators/TotpValidatorTest.php
Normal file
57
api/tests/unit/validators/TotpValidatorTest.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace api\tests\unit\validators;
|
||||
|
||||
use api\validators\TotpValidator;
|
||||
use common\helpers\Error as E;
|
||||
use common\models\Account;
|
||||
use OTPHP\TOTP;
|
||||
use api\tests\unit\TestCase;
|
||||
use common\tests\_support\ProtectedCaller;
|
||||
|
||||
class TotpValidatorTest extends TestCase {
|
||||
use ProtectedCaller;
|
||||
|
||||
public function testValidateValue() {
|
||||
$account = new Account();
|
||||
$account->otp_secret = 'AAAA';
|
||||
$controlTotp = TOTP::create($account->otp_secret);
|
||||
|
||||
$validator = new TotpValidator(['account' => $account]);
|
||||
|
||||
$result = $this->callProtected($validator, 'validateValue', 123456);
|
||||
$this->assertEquals([E::TOTP_INCORRECT, []], $result);
|
||||
|
||||
$result = $this->callProtected($validator, 'validateValue', $controlTotp->now());
|
||||
$this->assertNull($result);
|
||||
|
||||
$result = $this->callProtected($validator, 'validateValue', $controlTotp->at(time() - 31));
|
||||
$this->assertEquals([E::TOTP_INCORRECT, []], $result);
|
||||
|
||||
$validator->window = 2;
|
||||
$result = $this->callProtected($validator, 'validateValue', $controlTotp->at(time() - 31));
|
||||
$this->assertNull($result);
|
||||
|
||||
$at = time() - 400;
|
||||
$validator->timestamp = $at;
|
||||
$result = $this->callProtected($validator, 'validateValue', $controlTotp->now());
|
||||
$this->assertEquals([E::TOTP_INCORRECT, []], $result);
|
||||
|
||||
$result = $this->callProtected($validator, 'validateValue', $controlTotp->at($at));
|
||||
$this->assertNull($result);
|
||||
|
||||
$at = function() {
|
||||
return null;
|
||||
};
|
||||
$validator->timestamp = $at;
|
||||
$result = $this->callProtected($validator, 'validateValue', $controlTotp->now());
|
||||
$this->assertNull($result);
|
||||
|
||||
$at = function() {
|
||||
return time() - 700;
|
||||
};
|
||||
$validator->timestamp = $at;
|
||||
$result = $this->callProtected($validator, 'validateValue', $controlTotp->at($at()));
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user