Remove usage of codeception/specify and fzaninotto/faker

This commit is contained in:
ErickSkrauch 2019-12-21 02:26:06 +03:00
parent 666213afc7
commit 43a4a58053
19 changed files with 217 additions and 613 deletions

View File

@ -1,4 +1,6 @@
<?php
declare(strict_types=1);
namespace api\models\authentication;
use api\aop\annotations\CollectModelMetrics;

View File

@ -4,7 +4,7 @@ namespace api\tests\functional\_steps;
use api\rbac\Permissions as P;
use api\tests\_pages\SessionServerRoute;
use api\tests\FunctionalTester;
use Faker\Provider\Uuid;
use function Ramsey\Uuid\v4 as uuid;
class SessionServerSteps extends FunctionalTester {
@ -12,7 +12,7 @@ class SessionServerSteps extends FunctionalTester {
$oauthSteps = new OauthSteps($this->scenario);
$accessToken = $oauthSteps->getAccessToken([P::MINECRAFT_SERVER_SESSION]);
$route = new SessionServerRoute($this);
$serverId = Uuid::uuid();
$serverId = uuid();
$username = 'Admin';
if ($byLegacy) {

View File

@ -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('');
}

View File

@ -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();

View File

@ -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');

View File

@ -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();

View File

@ -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.');

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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)

View File

@ -1,20 +0,0 @@
<?php
/**
* @var $faker \Faker\Generator
* @var $index integer
*/
$security = Yii::$app->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(),
];

View File

@ -1,70 +1,46 @@
<?php
declare(strict_types=1);
namespace common\tests\unit\behaviors;
use Codeception\Specify;
use common\behaviors\PrimaryKeyValueBehavior;
use common\tests\unit\TestCase;
use yii\db\ActiveRecord;
class PrimaryKeyValueBehaviorTest extends TestCase {
use Specify;
public function testRefreshPrimaryKeyValue() {
$this->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'];
}
};
}
}

View File

@ -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() {

View File

@ -1,77 +0,0 @@
<?php
namespace common\tests\unit\validators;
use Codeception\Specify;
use common\tests\unit\TestCase;
use common\validators\UuidValidator;
use Faker\Provider\Uuid;
use yii\base\Model;
class UuidValidatorTest extends TestCase {
use Specify;
public function testValidateAttribute() {
$this->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;
};
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace common\validators;
use InvalidArgumentException;
use Ramsey\Uuid\Uuid;
use yii\validators\Validator;
class UuidValidator extends Validator {
public $allowNil = true;
public $skipOnEmpty = false;
public $message = '{attribute} must be valid uuid';
public function validateAttribute($model, $attribute) {
try {
$uuid = Uuid::fromString($model->$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, []);
}
}
}

View File

@ -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": {

140
composer.lock generated
View File

@ -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",