diff --git a/api/models/authentication/LogoutForm.php b/api/models/authentication/LogoutForm.php index 6f05ac0..9097190 100644 --- a/api/models/authentication/LogoutForm.php +++ b/api/models/authentication/LogoutForm.php @@ -1,4 +1,6 @@ scenario); $accessToken = $oauthSteps->getAccessToken([P::MINECRAFT_SERVER_SESSION]); $route = new SessionServerRoute($this); - $serverId = Uuid::uuid(); + $serverId = uuid(); $username = 'Admin'; if ($byLegacy) { diff --git a/api/tests/functional/mojang/UuidToUsernamesHistoryCest.php b/api/tests/functional/mojang/UuidToUsernamesHistoryCest.php index 6459176..c7f5ab2 100644 --- a/api/tests/functional/mojang/UuidToUsernamesHistoryCest.php +++ b/api/tests/functional/mojang/UuidToUsernamesHistoryCest.php @@ -3,7 +3,7 @@ namespace api\tests\functional\authserver; use api\tests\_pages\MojangApiRoute; use api\tests\FunctionalTester; -use Faker\Provider\Uuid; +use function Ramsey\Uuid\v4 as uuid; class UuidToUsernamesHistoryCest { @@ -50,7 +50,7 @@ class UuidToUsernamesHistoryCest { public function passWrongUuid(FunctionalTester $I) { $I->wantTo('get user username by some wrong uuid'); - $this->route->usernamesByUuid(Uuid::uuid()); + $this->route->usernamesByUuid(uuid()); $I->canSeeResponseCodeIs(204); $I->canSeeResponseEquals(''); } diff --git a/api/tests/functional/sessionserver/HasJoinedCest.php b/api/tests/functional/sessionserver/HasJoinedCest.php index adfe620..845915c 100644 --- a/api/tests/functional/sessionserver/HasJoinedCest.php +++ b/api/tests/functional/sessionserver/HasJoinedCest.php @@ -4,7 +4,7 @@ namespace api\tests\functional\sessionserver; use api\tests\_pages\SessionServerRoute; use api\tests\functional\_steps\SessionServerSteps; use api\tests\FunctionalTester; -use Faker\Provider\Uuid; +use function Ramsey\Uuid\v4 as uuid; class HasJoinedCest { @@ -46,7 +46,7 @@ class HasJoinedCest { $I->wantTo('hasJoined to some server without join call'); $this->route->hasJoined([ 'username' => 'some-username', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->seeResponseCodeIs(401); $I->seeResponseIsJson(); diff --git a/api/tests/functional/sessionserver/HasJoinedLegacyCest.php b/api/tests/functional/sessionserver/HasJoinedLegacyCest.php index de0a852..3ba6d03 100644 --- a/api/tests/functional/sessionserver/HasJoinedLegacyCest.php +++ b/api/tests/functional/sessionserver/HasJoinedLegacyCest.php @@ -4,7 +4,7 @@ namespace api\tests\functional\sessionserver; use api\tests\_pages\SessionServerRoute; use api\tests\functional\_steps\SessionServerSteps; use api\tests\FunctionalTester; -use Faker\Provider\Uuid; +use function Ramsey\Uuid\v4 as uuid; class HasJoinedLegacyCest { @@ -42,7 +42,7 @@ class HasJoinedLegacyCest { $I->wantTo('hasJoined by legacy version to some server without join call'); $this->route->hasJoinedLegacy([ 'user' => 'random-username', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->seeResponseCodeIs(200); $I->canSeeResponseEquals('NO'); diff --git a/api/tests/functional/sessionserver/JoinCest.php b/api/tests/functional/sessionserver/JoinCest.php index a4aabd2..5219187 100644 --- a/api/tests/functional/sessionserver/JoinCest.php +++ b/api/tests/functional/sessionserver/JoinCest.php @@ -6,7 +6,7 @@ use api\tests\_pages\SessionServerRoute; use api\tests\functional\_steps\AuthserverSteps; use api\tests\functional\_steps\OauthSteps; use api\tests\FunctionalTester; -use Faker\Provider\Uuid; +use function Ramsey\Uuid\v4 as uuid; class JoinCest { @@ -25,7 +25,7 @@ class JoinCest { $this->route->join([ 'accessToken' => $accessToken, 'selectedProfile' => 'df936908-b2e1-544d-96f8-2977ec213022', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $this->expectSuccessResponse($I); } @@ -36,7 +36,7 @@ class JoinCest { $this->route->join(json_encode([ 'accessToken' => $accessToken, 'selectedProfile' => 'df936908-b2e1-544d-96f8-2977ec213022', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ])); $this->expectSuccessResponse($I); } @@ -47,7 +47,7 @@ class JoinCest { $this->route->join([ 'accessToken' => $accessToken, 'selectedProfile' => 'df936908-b2e1-544d-96f8-2977ec213022', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $this->expectSuccessResponse($I); } @@ -58,7 +58,7 @@ class JoinCest { $this->route->join([ 'accessToken' => $accessToken, 'selectedProfile' => 'df936908b2e1544d96f82977ec213022', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $this->expectSuccessResponse($I); } @@ -69,7 +69,7 @@ class JoinCest { $this->route->join([ 'accessToken' => $accessToken, 'selectedProfile' => 'df936908-b2e1-544d-96f8-2977ec213022', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->seeResponseCodeIs(401); $I->seeResponseIsJson(); @@ -84,7 +84,7 @@ class JoinCest { $this->route->join([ 'accessToken' => '6042634a-a1e2-4aed-866c-c661fe4e63e2', 'selectedProfile' => 'df936908-b2e1-544d-96f8-2977ec213022', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->seeResponseCodeIs(401); $I->seeResponseIsJson(); @@ -110,9 +110,9 @@ class JoinCest { public function joinWithWrongAccessToken(FunctionalTester $I) { $I->wantTo('join to some server with wrong accessToken'); $this->route->join([ - 'accessToken' => Uuid::uuid(), + 'accessToken' => uuid(), 'selectedProfile' => 'df936908-b2e1-544d-96f8-2977ec213022', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->seeResponseCodeIs(401); $I->seeResponseIsJson(); @@ -127,7 +127,7 @@ class JoinCest { $this->route->join([ 'accessToken' => '00000000-0000-0000-0000-000000000000', 'selectedProfile' => 'df936908-b2e1-544d-96f8-2977ec213022', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->canSeeResponseCodeIs(400); $I->canSeeResponseIsJson(); diff --git a/api/tests/functional/sessionserver/JoinLegacyCest.php b/api/tests/functional/sessionserver/JoinLegacyCest.php index accc5a7..17dfeba 100644 --- a/api/tests/functional/sessionserver/JoinLegacyCest.php +++ b/api/tests/functional/sessionserver/JoinLegacyCest.php @@ -6,7 +6,7 @@ use api\tests\_pages\SessionServerRoute; use api\tests\functional\_steps\AuthserverSteps; use api\tests\functional\_steps\OauthSteps; use api\tests\FunctionalTester; -use Faker\Provider\Uuid; +use function Ramsey\Uuid\v4 as uuid; class JoinLegacyCest { @@ -25,7 +25,7 @@ class JoinLegacyCest { $this->route->joinLegacy([ 'sessionId' => $accessToken, 'user' => 'Admin', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $this->expectSuccessResponse($I); } @@ -36,7 +36,7 @@ class JoinLegacyCest { $this->route->joinLegacy([ 'sessionId' => $accessToken, 'user' => 'admin', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $this->expectSuccessResponse($I); } @@ -47,7 +47,7 @@ class JoinLegacyCest { $this->route->joinLegacy([ 'sessionId' => 'token:' . $accessToken . ':' . 'df936908-b2e1-544d-96f8-2977ec213022', 'user' => 'Admin', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $this->expectSuccessResponse($I); } @@ -58,7 +58,7 @@ class JoinLegacyCest { $this->route->joinLegacy([ 'sessionId' => 'token:' . $accessToken . ':' . 'df936908-b2e1-544d-96f8-2977ec213022', 'user' => 'Admin', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $this->expectSuccessResponse($I); } @@ -75,9 +75,9 @@ class JoinLegacyCest { public function joinWithWrongAccessToken(FunctionalTester $I) { $I->wantTo('join to some server with wrong accessToken'); $this->route->joinLegacy([ - 'sessionId' => 'token:' . Uuid::uuid() . ':' . Uuid::uuid(), + 'sessionId' => 'token:' . uuid() . ':' . uuid(), 'user' => 'random-username', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->seeResponseCodeIs(401); $I->canSeeResponseContains('Ely.by authorization required'); @@ -89,7 +89,7 @@ class JoinLegacyCest { $this->route->joinLegacy([ 'sessionId' => 'token:' . $accessToken . ':' . 'df936908-b2e1-544d-96f8-2977ec213022', 'user' => 'Admin', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->seeResponseCodeIs(401); $I->canSeeResponseContains('Ely.by authorization required'); @@ -100,7 +100,7 @@ class JoinLegacyCest { $this->route->joinLegacy([ 'sessionId' => 'token:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000', 'user' => 'SomeUser', - 'serverId' => Uuid::uuid(), + 'serverId' => uuid(), ]); $I->canSeeResponseCodeIs(400); $I->canSeeResponseContains('credentials can not be null.'); diff --git a/api/tests/functional/sessionserver/ProfileCest.php b/api/tests/functional/sessionserver/ProfileCest.php index 8d7bd1a..e197351 100644 --- a/api/tests/functional/sessionserver/ProfileCest.php +++ b/api/tests/functional/sessionserver/ProfileCest.php @@ -4,7 +4,7 @@ namespace api\tests\functional\sessionserver; use api\tests\_pages\SessionServerRoute; use api\tests\functional\_steps\SessionServerSteps; use api\tests\FunctionalTester; -use Faker\Provider\Uuid; +use function Ramsey\Uuid\v4; class ProfileCest { @@ -48,7 +48,7 @@ class ProfileCest { public function getProfileWithNonexistentUuid(FunctionalTester $I) { $I->wantTo('get info about nonexistent uuid'); - $this->route->profile(Uuid::uuid()); + $this->route->profile(v4()); $I->canSeeResponseCodeIs(401); $I->canSeeResponseIsJson(); $I->seeResponseIsJson(); diff --git a/api/tests/unit/models/authentication/LoginFormTest.php b/api/tests/unit/models/authentication/LoginFormTest.php index f299e40..f7325e1 100644 --- a/api/tests/unit/models/authentication/LoginFormTest.php +++ b/api/tests/unit/models/authentication/LoginFormTest.php @@ -5,26 +5,11 @@ namespace api\tests\_support\models\authentication; use api\models\authentication\LoginForm; use api\tests\unit\TestCase; -use Codeception\Specify; use common\models\Account; use common\tests\fixtures\AccountFixture; use OTPHP\TOTP; class LoginFormTest extends TestCase { - use Specify; - - private $originalRemoteAddr; - - protected function setUp(): void { - $this->originalRemoteAddr = $_SERVER['REMOTE_ADDR'] ?? null; - $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; - parent::setUp(); - } - - protected function tearDown(): void { - parent::tearDown(); - $_SERVER['REMOTE_ADDR'] = $this->originalRemoteAddr; - } public function _fixtures(): array { return [ @@ -33,43 +18,31 @@ class LoginFormTest extends TestCase { } 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->assertSame(['error.login_not_exist'], $model->getErrors('login')); - }); + $model = $this->createWithAccount(null); + $model->login = 'mock-login'; + $model->validateLogin('login'); + $this->assertSame(['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')); - }); + $model = $this->createWithAccount(new Account()); + $model->login = 'mock-login'; + $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->assertSame(['error.password_incorrect'], $model->getErrors('password')); - }); + $account = new Account(); + $account->password_hash = '$2y$04$N0q8DaHzlYILCnLYrpZfEeWKEqkPZzbawiS07GbSr/.xbRNweSLU6'; // 12345678 + $account->password_hash_strategy = Account::PASS_HASH_STRATEGY_YII2; - $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')); - }); + $model = $this->createWithAccount($account); + $model->password = '87654321'; + $model->validatePassword('password'); + $this->assertSame(['error.password_incorrect'], $model->getErrors('password')); + + $model = $this->createWithAccount($account); + $model->password = '12345678'; + $model->validatePassword('password'); + $this->assertEmpty($model->getErrors('password')); } public function testValidateTotp() { @@ -78,99 +51,72 @@ class LoginFormTest extends TestCase { $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->assertSame(['error.totp_incorrect'], $model->getErrors('totp')); - }); + $model = $this->createWithAccount($account); + $model->password = '12345678'; + $model->totp = '321123'; + $model->validateTotp('totp'); + $this->assertSame(['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')); - }); + $model = $this->createWithAccount($account); + $model->password = '12345678'; + $model->totp = $totp->now(); + $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->assertSame(['error.account_not_activated'], $model->getErrors('login')); - }); + $account = new Account(); + $account->status = Account::STATUS_REGISTERED; + $model = $this->createWithAccount($account); + $model->validateActivity('login'); + $this->assertSame(['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->assertSame(['error.account_banned'], $model->getErrors('login')); - }); + $account = new Account(); + $account->status = Account::STATUS_BANNED; + $model = $this->createWithAccount($account); + $model->validateActivity('login'); + $this->assertSame(['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')); - }); + $account = new Account(); + $account->status = Account::STATUS_ACTIVE; + $model = $this->createWithAccount($account); + $model->validateActivity('login'); + $this->assertEmpty($model->getErrors('login')); } public function testLogin() { - $model = $this->createModel([ - 'login' => 'erickskrauch', - 'password' => '12345678', - 'account' => new Account([ - 'id' => 1, - 'username' => 'erickskrauch', - 'password' => '12345678', - 'status' => Account::STATUS_ACTIVE, - ]), - ]); + $account = new Account(); + $account->id = 1; + $account->username = 'erickskrauch'; + $account->password_hash = '$2y$04$N0q8DaHzlYILCnLYrpZfEeWKEqkPZzbawiS07GbSr/.xbRNweSLU6'; // 12345678 + $account->password_hash_strategy = Account::PASS_HASH_STRATEGY_YII2; + $account->status = Account::STATUS_ACTIVE; + + $model = $this->createWithAccount($account); + $model->login = 'erickskrauch'; + $model->password = '12345678'; + $this->assertNotNull($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', - ]); + /** @var Account $account */ + $account = $this->tester->grabFixture('accounts', 'user-with-old-password-type'); + $model = $this->createWithAccount($account); + $model->login = $account->username; + $model->password = '12345678'; + $this->assertNotNull($model->login()); - $this->assertEmpty($model->getErrors()); - $this->assertSame( - Account::PASS_HASH_STRATEGY_YII2, - $model->getAccount()->password_hash_strategy, - 'user, that login using account with old pass hash strategy should update it automatically' - ); + $this->assertSame(Account::PASS_HASH_STRATEGY_YII2, $account->password_hash_strategy); + $this->assertNotSame('133c00c463cbd3e491c28cb653ce4718', $account->password_hash); } - /** - * @param array $params - * @return LoginForm - */ - private function createModel(array $params = []) { - return new class($params) extends LoginForm { - private $_account; + private function createWithAccount(?Account $account): LoginForm { + $model = $this->createPartialMock(LoginForm::class, ['getAccount']); + $model->method('getAccount')->willReturn($account); - public function setAccount($value) { - $this->_account = $value; - } - - public function getAccount(): ?Account { - return $this->_account; - } - }; + return $model; } } diff --git a/api/tests/unit/models/authentication/LogoutFormTest.php b/api/tests/unit/models/authentication/LogoutFormTest.php index 9608b52..cc9b562 100644 --- a/api/tests/unit/models/authentication/LogoutFormTest.php +++ b/api/tests/unit/models/authentication/LogoutFormTest.php @@ -6,54 +6,32 @@ namespace api\tests\_support\models\authentication; use api\components\User\Component; use api\models\authentication\LogoutForm; use api\tests\unit\TestCase; -use Codeception\Specify; use common\models\AccountSession; 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) - ->setMethods(['getActiveSession']) - ->getMock(); - $userComp - ->expects($this->any()) - ->method('getActiveSession') - ->will($this->returnValue(null)); + public function testNoActionWhenThereIsNoActiveSession() { + $userComp = $this->createPartialMock(Component::class, ['getActiveSession']); + $userComp->method('getActiveSession')->willReturn(null); - Yii::$app->set('user', $userComp); + Yii::$app->set('user', $userComp); - $model = new LogoutForm(); - $this->assertTrue($model->logout()); - }); + $model = new LogoutForm(); + $this->assertTrue($model->logout()); + } - $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); + public function testActiveSessionShouldBeDeleted() { + $session = $this->createPartialMock(AccountSession::class, ['delete']); + $session->expects($this->once())->method('delete')->willReturn(true); - $userComp = $this - ->getMockBuilder(Component::class) - ->setMethods(['getActiveSession']) - ->getMock(); - $userComp - ->expects($this->any()) - ->method('getActiveSession') - ->will($this->returnValue($session)); + $userComp = $this->createPartialMock(Component::class, ['getActiveSession']); + $userComp->method('getActiveSession')->willReturn($session); - Yii::$app->set('user', $userComp); + Yii::$app->set('user', $userComp); - $model = new LogoutForm(); - $model->logout(); - }); + $model = new LogoutForm(); + $model->logout(); } } diff --git a/api/tests/unit/models/authentication/RepeatAccountActivationFormTest.php b/api/tests/unit/models/authentication/RepeatAccountActivationFormTest.php index 5feb06d..1f0d823 100644 --- a/api/tests/unit/models/authentication/RepeatAccountActivationFormTest.php +++ b/api/tests/unit/models/authentication/RepeatAccountActivationFormTest.php @@ -6,9 +6,8 @@ namespace api\tests\_support\models\authentication; use api\components\ReCaptcha\Validator as ReCaptchaValidator; use api\models\authentication\RepeatAccountActivationForm; use api\tests\unit\TestCase; -use Codeception\Specify; +use common\models\Account; use common\models\confirmations\RegistrationConfirmation; -use common\models\EmailActivation; use common\tasks\SendRegistrationEmail; use common\tests\fixtures\AccountFixture; use common\tests\fixtures\EmailActivationFixture; @@ -16,7 +15,6 @@ use GuzzleHttp\ClientInterface; use Yii; class RepeatAccountActivationFormTest extends TestCase { - use Specify; protected function setUp(): void { parent::setUp(); @@ -35,41 +33,35 @@ class RepeatAccountActivationFormTest extends TestCase { } 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'); - $this->assertSame(['error.email_not_found'], $model->getErrors('email')); - }); + $model = $this->createWithAccount(null); + $model->validateEmailForAccount('email'); + $this->assertSame(['error.email_not_found'], $model->getErrors('email')); - $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'); - $this->assertSame(['error.account_already_activated'], $model->getErrors('email')); - }); + $account = new Account(); + $account->status = Account::STATUS_ACTIVE; + $model = $this->createWithAccount($account); + $model->validateEmailForAccount('email'); + $this->assertSame(['error.account_already_activated'], $model->getErrors('email')); - $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'); - $this->assertEmpty($model->getErrors('email')); - }); + $account = new Account(); + $account->status = Account::STATUS_REGISTERED; + $model = $this->createWithAccount($account); + $model->validateEmailForAccount('email'); + $this->assertEmpty($model->getErrors('email')); } 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'); - $this->assertSame(['error.recently_sent_message'], $model->getErrors('email')); - }); + $activation = new RegistrationConfirmation(); + $activation->created_at = time() - 10; + $model = $this->createWithActivation($activation); + $model->validateExistsActivation('email'); + $this->assertSame(['error.recently_sent_message'], $model->getErrors('email')); - $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'); - $this->assertEmpty($model->getErrors('email')); - }); + $activation = new RegistrationConfirmation(); + $activation->created_at = time() - 60 * 60 * 24; + $model = $this->createWithActivation($activation); + $model->validateExistsActivation('email'); + $this->assertEmpty($model->getErrors('email')); } public function testSendRepeatMessage() { @@ -93,18 +85,18 @@ class RepeatAccountActivationFormTest extends TestCase { $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; + private function createWithAccount(?Account $account): RepeatAccountActivationForm { + $model = $this->createPartialMock(RepeatAccountActivationForm::class, ['getAccount']); + $model->method('getAccount')->willReturn($account); - public function getActivation(): ?RegistrationConfirmation { - return EmailActivation::findOne($this->emailKey); - } - }; + return $model; + } + + private function createWithActivation(?RegistrationConfirmation $activation): RepeatAccountActivationForm { + $model = $this->createPartialMock(RepeatAccountActivationForm::class, ['getActivation']); + $model->method('getActivation')->willReturn($activation); + + return $model; } } diff --git a/api/tests/unit/modules/session/filters/RateLimiterTest.php b/api/tests/unit/modules/session/filters/RateLimiterTest.php index 94ff1de..7f1cdca 100644 --- a/api/tests/unit/modules/session/filters/RateLimiterTest.php +++ b/api/tests/unit/modules/session/filters/RateLimiterTest.php @@ -6,7 +6,6 @@ namespace api\tests\unit\modules\session\filters; use api\modules\session\filters\RateLimiter; use api\tests\unit\TestCase; use common\models\OauthClient; -use Faker\Provider\Internet; use Yii; use yii\redis\Connection; use yii\web\Request; @@ -84,7 +83,7 @@ class RateLimiterTest extends TestCase { ->getMock(); $request->method('getUserIp') - ->willReturn(Internet::localIpv4()); + ->willReturn('10.1.1.17'); /** @var RateLimiter|\PHPUnit\Framework\MockObject\MockObject $filter */ $filter = $this->getMockBuilder(RateLimiter::class) diff --git a/common/tests/templates/fixtures/account.php b/common/tests/templates/fixtures/account.php deleted file mode 100644 index 202cd42..0000000 --- a/common/tests/templates/fixtures/account.php +++ /dev/null @@ -1,20 +0,0 @@ -getSecurity(); - -return [ - 'uuid' => $faker->uuid, - 'username' => $faker->userName, - 'email' => $faker->email, - 'password_hash' => $security->generatePasswordHash('password_' . $index), - 'password_hash_strategy' => \common\models\Account::PASS_HASH_STRATEGY_YII2, - 'lang' => 'en', - 'auth_key' => $security->generateRandomString(), - 'status' => \common\models\Account::STATUS_ACTIVE, - 'created_at' => time(), - 'updated_at' => time(), -]; diff --git a/common/tests/unit/behaviors/PrimaryKeyValueBehaviorTest.php b/common/tests/unit/behaviors/PrimaryKeyValueBehaviorTest.php index 1fcfc38..09702f9 100644 --- a/common/tests/unit/behaviors/PrimaryKeyValueBehaviorTest.php +++ b/common/tests/unit/behaviors/PrimaryKeyValueBehaviorTest.php @@ -1,70 +1,46 @@ specify('method should generate value for primary key field on call', function() { - $model = new DummyModel(); - /** @var PrimaryKeyValueBehavior|\PHPUnit\Framework\MockObject\MockObject $behavior */ - $behavior = $this->getMockBuilder(PrimaryKeyValueBehavior::class) - ->setMethods(['isValueExists']) - ->setConstructorArgs([[ - 'value' => function() { - return 'mock'; - }, - ]]) - ->getMock(); + public function testGenerateValueForThePrimaryKey() { + $model = $this->createDummyModel(); + $behavior = $this->createPartialMock(PrimaryKeyValueBehavior::class, ['isValueExists']); + $behavior->method('isValueExists')->willReturn(false); + $behavior->value = function() { + return 'mock'; + }; - $behavior->expects($this->once()) - ->method('isValueExists') - ->will($this->returnValue(false)); + $model->attachBehavior('primary-key-value-behavior', $behavior); + $behavior->setPrimaryKeyValue(); + $this->assertSame('mock', $model->id); + } - $model->attachBehavior('primary-key-value-behavior', $behavior); - $behavior->setPrimaryKeyValue(); - $this->assertSame('mock', $model->id); - }); + public function testShouldRegenerateValueWhenGeneratedAlreadyExists() { + $model = $this->createDummyModel(); + $behavior = $this->createPartialMock(PrimaryKeyValueBehavior::class, ['isValueExists', 'generateValue']); + $behavior->expects($this->exactly(3))->method('generateValue')->willReturnOnConsecutiveCalls('1', '2', '3'); + $behavior->expects($this->exactly(3))->method('isValueExists')->willReturnOnConsecutiveCalls(true, true, false); - $this->specify('method should repeat value generation if generated value duplicate with exists', function() { - $model = new DummyModel(); - /** @var PrimaryKeyValueBehavior|\PHPUnit\Framework\MockObject\MockObject $behavior */ - $behavior = $this->getMockBuilder(PrimaryKeyValueBehavior::class) - ->setMethods(['isValueExists', 'generateValue']) - ->setConstructorArgs([[ - 'value' => function() { - return 'this was mocked, but let be passed'; - }, - ]]) - ->getMock(); + $model->attachBehavior('primary-key-value-behavior', $behavior); + $behavior->setPrimaryKeyValue(); + $this->assertSame('3', $model->id); + } - $behavior->expects($this->exactly(3)) - ->method('generateValue') - ->will($this->onConsecutiveCalls('1', '2', '3')); + private function createDummyModel() { + return new class extends ActiveRecord { + public $id; - $behavior->expects($this->exactly(3)) - ->method('isValueExists') - ->will($this->onConsecutiveCalls(true, true, false)); - - $model->attachBehavior('primary-key-value-behavior', $behavior); - $behavior->setPrimaryKeyValue(); - $this->assertSame('3', $model->id); - }); - } - -} - -class DummyModel extends ActiveRecord { - - public $id; - - public static function primaryKey() { - return ['id']; + public static function primaryKey() { + return ['id']; + } + }; } } diff --git a/common/tests/unit/models/AccountTest.php b/common/tests/unit/models/AccountTest.php index f126849..4144b42 100644 --- a/common/tests/unit/models/AccountTest.php +++ b/common/tests/unit/models/AccountTest.php @@ -3,20 +3,16 @@ declare(strict_types=1); namespace common\tests\unit\models; -use Codeception\Specify; -use common\components\UserPass; use common\models\Account; use common\tasks\CreateWebHooksDeliveries; use common\tests\fixtures\MojangUsernameFixture; use common\tests\unit\TestCase; -use Yii; use const common\LATEST_RULES_VERSION; /** * @covers \common\models\Account */ class AccountTest extends TestCase { - use Specify; public function testSetPassword() { $model = new Account(); @@ -27,57 +23,47 @@ class AccountTest extends TestCase { } public function testValidatePassword() { - $this->specify('old Ely password should work', function() { - $model = new Account([ - 'email' => 'erick@skrauch.net', - 'password_hash' => UserPass::make('erick@skrauch.net', '12345678'), - ]); - $this->assertTrue($model->validatePassword('12345678', Account::PASS_HASH_STRATEGY_OLD_ELY), 'valid password should pass'); - $this->assertFalse($model->validatePassword('87654321', Account::PASS_HASH_STRATEGY_OLD_ELY), 'invalid password should fail'); - }); + // Use old hashing algorithm + $model = new Account(); + $model->email = 'erick@skrauch.net'; + $model->password_hash = '2cfdb29eb354af970865a923335d17d9'; // 12345678 + $model->password_hash_strategy = null; // To be sure it's not set + $this->assertTrue($model->validatePassword('12345678', Account::PASS_HASH_STRATEGY_OLD_ELY), 'valid password should pass'); + $this->assertFalse($model->validatePassword('87654321', Account::PASS_HASH_STRATEGY_OLD_ELY), 'invalid password should fail'); - $this->specify('modern hash algorithm should work', function() { - $model = new Account([ - 'password_hash' => Yii::$app->security->generatePasswordHash('12345678'), - ]); - $this->assertTrue($model->validatePassword('12345678', Account::PASS_HASH_STRATEGY_YII2), 'valid password should pass'); - $this->assertFalse($model->validatePassword('87654321', Account::PASS_HASH_STRATEGY_YII2), 'invalid password should fail'); - }); + // Modern hash algorithm should also work + $model = new Account(); + $model->password_hash = '$2y$04$N0q8DaHzlYILCnLYrpZfEeWKEqkPZzbawiS07GbSr/.xbRNweSLU6'; // 12345678 + $model->password_hash_strategy = null; // To be sure it's not set + $this->assertTrue($model->validatePassword('12345678', Account::PASS_HASH_STRATEGY_YII2), 'valid password should pass'); + $this->assertFalse($model->validatePassword('87654321', Account::PASS_HASH_STRATEGY_YII2), 'invalid password should fail'); - $this->specify('if second argument is not pass model value should be used', function() { - $model = new Account([ - 'email' => 'erick@skrauch.net', - 'password_hash_strategy' => Account::PASS_HASH_STRATEGY_OLD_ELY, - 'password_hash' => UserPass::make('erick@skrauch.net', '12345678'), - ]); - $this->assertTrue($model->validatePassword('12345678'), 'valid password should pass'); - $this->assertFalse($model->validatePassword('87654321'), 'invalid password should fail'); + // If the second arg isn't passed model's value should be used + $model = new Account(); + $model->email = 'erick@skrauch.net'; + $model->password_hash = '2cfdb29eb354af970865a923335d17d9'; // 12345678 + $model->password_hash_strategy = Account::PASS_HASH_STRATEGY_OLD_ELY; + $this->assertTrue($model->validatePassword('12345678'), 'valid password should pass'); + $this->assertFalse($model->validatePassword('87654321'), 'invalid password should fail'); - $model = new Account([ - 'password_hash_strategy' => Account::PASS_HASH_STRATEGY_YII2, - 'password_hash' => Yii::$app->security->generatePasswordHash('12345678'), - ]); - $this->assertTrue($model->validatePassword('12345678'), 'valid password should pass'); - $this->assertFalse($model->validatePassword('87654321'), 'invalid password should fail'); - }); + // The same case for modern algorithm + $model = new Account(); + $model->password_hash = '$2y$04$N0q8DaHzlYILCnLYrpZfEeWKEqkPZzbawiS07GbSr/.xbRNweSLU6'; // 12345678 + $model->password_hash_strategy = Account::PASS_HASH_STRATEGY_YII2; + $this->assertTrue($model->validatePassword('12345678'), 'valid password should pass'); + $this->assertFalse($model->validatePassword('87654321'), 'invalid password should fail'); } public function testHasMojangUsernameCollision() { + $model = new Account(); + $model->username = 'ErickSkrauch'; + $this->assertFalse($model->hasMojangUsernameCollision()); + $this->tester->haveFixtures([ 'mojangUsernames' => MojangUsernameFixture::class, ]); - $this->specify('Expect true if collision with current username', function() { - $model = new Account(); - $model->username = 'ErickSkrauch'; - $this->assertTrue($model->hasMojangUsernameCollision()); - }); - - $this->specify('Expect false if some rare username without any collision on Mojang', function() { - $model = new Account(); - $model->username = 'rare-username'; - $this->assertFalse($model->hasMojangUsernameCollision()); - }); + $this->assertTrue($model->hasMojangUsernameCollision()); } public function testGetProfileLink() { @@ -87,22 +73,14 @@ class AccountTest extends TestCase { } public function testIsAgreedWithActualRules() { - $this->specify('get false, if rules field set in null', function() { - $model = new Account(); - $this->assertFalse($model->isAgreedWithActualRules()); - }); + $model = new Account(); + $this->assertFalse($model->isAgreedWithActualRules(), 'field is null'); - $this->specify('get false, if rules field have version less, then actual', function() { - $model = new Account(); - $model->rules_agreement_version = 0; - $this->assertFalse($model->isAgreedWithActualRules()); - }); + $model->rules_agreement_version = 0; + $this->assertFalse($model->isAgreedWithActualRules(), 'actual version is greater than zero'); - $this->specify('get true, if rules field have equals rules version', function() { - $model = new Account(); - $model->rules_agreement_version = LATEST_RULES_VERSION; - $this->assertTrue($model->isAgreedWithActualRules()); - }); + $model->rules_agreement_version = LATEST_RULES_VERSION; + $this->assertTrue($model->isAgreedWithActualRules()); } public function testSetRegistrationIp() { diff --git a/common/tests/unit/validators/UuidValidatorTest.php b/common/tests/unit/validators/UuidValidatorTest.php deleted file mode 100644 index 191af72..0000000 --- a/common/tests/unit/validators/UuidValidatorTest.php +++ /dev/null @@ -1,77 +0,0 @@ -specify('expected error if passed empty value', function() { - $validator = new UuidValidator(); - $model = $this->createModel(); - $validator->validateAttribute($model, 'attribute'); - $this->assertTrue($model->hasErrors()); - $this->assertSame(['Attribute must be valid uuid'], $model->getErrors('attribute')); - }); - - $this->specify('expected error if passed invalid string', function() { - $validator = new UuidValidator(); - $model = $this->createModel(); - $model->attribute = '123456789'; - $validator->validateAttribute($model, 'attribute'); - $this->assertTrue($model->hasErrors()); - $this->assertSame(['Attribute must be valid uuid'], $model->getErrors('attribute')); - }); - - $this->specify('no errors if passed nil uuid and allowNil is set to true', function() { - $validator = new UuidValidator(); - $model = $this->createModel(); - $model->attribute = '00000000-0000-0000-0000-000000000000'; - $validator->validateAttribute($model, 'attribute'); - $this->assertFalse($model->hasErrors()); - }); - - $this->specify('no errors if passed nil uuid and allowNil is set to false', function() { - $validator = new UuidValidator(); - $validator->allowNil = false; - $model = $this->createModel(); - $model->attribute = '00000000-0000-0000-0000-000000000000'; - $validator->validateAttribute($model, 'attribute'); - $this->assertTrue($model->hasErrors()); - $this->assertSame(['Attribute must be valid uuid'], $model->getErrors('attribute')); - }); - - $this->specify('no errors if passed valid uuid', function() { - $validator = new UuidValidator(); - $model = $this->createModel(); - $model->attribute = Uuid::uuid(); - $validator->validateAttribute($model, 'attribute'); - $this->assertFalse($model->hasErrors()); - }); - - $this->specify('no errors if passed uuid string without dashes and converted to standart value', function() { - $validator = new UuidValidator(); - $model = $this->createModel(); - $originalUuid = Uuid::uuid(); - $model->attribute = str_replace('-', '', $originalUuid); - $validator->validateAttribute($model, 'attribute'); - $this->assertFalse($model->hasErrors()); - $this->assertSame($originalUuid, $model->attribute); - }); - } - - /** - * @return Model - */ - public function createModel() { - return new class extends Model { - public $attribute; - }; - } - -} diff --git a/common/validators/UuidValidator.php b/common/validators/UuidValidator.php deleted file mode 100644 index 1103bf7..0000000 --- a/common/validators/UuidValidator.php +++ /dev/null @@ -1,29 +0,0 @@ -$attribute)->toString(); - $model->$attribute = $uuid; - } catch (InvalidArgumentException $e) { - $this->addError($model, $attribute, $this->message, []); - } - - if (isset($uuid) && $this->allowNil === false && $uuid === Uuid::NIL) { - $this->addError($model, $attribute, $this->message, []); - } - } - -} diff --git a/composer.json b/composer.json index 8101f44..93e02de 100644 --- a/composer.json +++ b/composer.json @@ -41,13 +41,10 @@ "codeception/module-asserts": "^1.1.0", "codeception/module-rest": "^1.0.0", "codeception/module-yii2": "^1.0.0", - "codeception/specify": "^1.0.0", "cweagans/composer-patches": "^1.6", "ely/php-code-style": "^0.3.0", "flow/jsonpath": "^0.4.0", - "fzaninotto/faker": "^1.8", "php-mock/php-mock-phpunit": "^2.5", - "predis/predis": "^1.1", "roave/security-advisories": "dev-master" }, "replace": { diff --git a/composer.lock b/composer.lock index 060aa54..0d6dc34 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "aece49d205676d4b8150cf622fc5aed8", + "content-hash": "0f0f24789cae6267d69fd317a338d634", "packages": [ { "name": "bacon/bacon-qr-code", @@ -3343,44 +3343,6 @@ "description": "PHPUnit classes used by Codeception", "time": "2019-11-24T15:30:35+00:00" }, - { - "name": "codeception/specify", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/Codeception/Specify.git", - "reference": "e3fefa22f2304170024b9242b2bd8b01cf5a2ac0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Codeception/Specify/zipball/e3fefa22f2304170024b9242b2bd8b01cf5a2ac0", - "reference": "e3fefa22f2304170024b9242b2bd8b01cf5a2ac0", - "shasum": "" - }, - "require": { - "myclabs/deep-copy": "~1.1", - "php": ">=7.1.0", - "phpunit/phpunit": ">=7.0 <9.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Codeception\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Bodnarchuk", - "email": "davert@codeception.com" - } - ], - "description": "BDD code blocks for PHPUnit and Codeception", - "time": "2019-08-01T20:09:26+00:00" - }, { "name": "codeception/stub", "version": "3.6.0", @@ -3795,56 +3757,6 @@ "description": "A tool to automatically fix PHP code style", "time": "2019-02-17T17:44:13+00:00" }, - { - "name": "fzaninotto/faker", - "version": "v1.9.1", - "source": { - "type": "git", - "url": "https://github.com/fzaninotto/Faker.git", - "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/fc10d778e4b84d5bd315dad194661e091d307c6f", - "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "ext-intl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7", - "squizlabs/php_codesniffer": "^2.9.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "Faker\\": "src/Faker/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "François Zaninotto" - } - ], - "description": "Faker is a PHP library that generates fake data for you.", - "keywords": [ - "data", - "faker", - "fixtures" - ], - "time": "2019-12-12T13:22:17+00:00" - }, { "name": "myclabs/deep-copy", "version": "1.9.4", @@ -4762,56 +4674,6 @@ ], "time": "2019-12-06T05:41:38+00:00" }, - { - "name": "predis/predis", - "version": "v1.1.1", - "source": { - "type": "git", - "url": "https://github.com/nrk/predis.git", - "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", - "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" - }, - "suggest": { - "ext-curl": "Allows access to Webdis when paired with phpiredis", - "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" - }, - "type": "library", - "autoload": { - "psr-4": { - "Predis\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniele Alessandri", - "email": "suppakilla@gmail.com", - "homepage": "http://clorophilla.net" - } - ], - "description": "Flexible and feature-complete Redis client for PHP and HHVM", - "homepage": "http://github.com/nrk/predis", - "keywords": [ - "nosql", - "predis", - "redis" - ], - "time": "2016-06-16T16:22:20+00:00" - }, { "name": "psr/container", "version": "1.0.0",