diff --git a/api/models/profile/ChangeUsernameForm.php b/api/models/profile/ChangeUsernameForm.php index fb0a931..9e7dd53 100644 --- a/api/models/profile/ChangeUsernameForm.php +++ b/api/models/profile/ChangeUsernameForm.php @@ -28,15 +28,19 @@ class ChangeUsernameForm extends ApiForm { ]; } - public function change() { + public function change() : bool { if (!$this->validate()) { return false; } - $transaction = Yii::$app->db->beginTransaction(); $account = $this->getAccount(); - $oldNickname = $account->username; + if ($this->username === $account->username) { + return true; + } + + $transaction = Yii::$app->db->beginTransaction(); try { + $oldNickname = $account->username; $account->username = $this->username; if (!$account->save()) { throw new ErrorException('Cannot save account model with new username'); diff --git a/tests/codeception/api/codeception.yml b/tests/codeception/api/codeception.yml index 4318152..92cfc34 100644 --- a/tests/codeception/api/codeception.yml +++ b/tests/codeception/api/codeception.yml @@ -1,5 +1,6 @@ namespace: tests\codeception\api actor: Tester +params: [env] paths: tests: . log: _output diff --git a/tests/codeception/api/functional.suite.yml b/tests/codeception/api/functional.suite.yml index 01d3dc2..713312d 100644 --- a/tests/codeception/api/functional.suite.yml +++ b/tests/codeception/api/functional.suite.yml @@ -4,6 +4,7 @@ modules: - Filesystem - Yii2 - tests\codeception\common\_support\FixtureHelper + - tests\codeception\common\_support\amqp\Helper - Redis - Asserts - REST: @@ -11,8 +12,8 @@ modules: config: Yii2: configFile: '../config/api/functional.php' - cleanup: true + cleanup: false Redis: - host: testredis + host: "%REDIS_HOST%" port: 6379 database: 0 diff --git a/tests/codeception/api/unit.suite.yml b/tests/codeception/api/unit.suite.yml index 8ce2d31..3d31363 100644 --- a/tests/codeception/api/unit.suite.yml +++ b/tests/codeception/api/unit.suite.yml @@ -3,6 +3,8 @@ modules: enabled: - Yii2: part: [orm, email, fixtures] + - tests\codeception\common\_support\amqp\Helper config: Yii2: configFile: '../config/api/unit.php' + cleanup: false diff --git a/tests/codeception/api/unit/models/authentication/ConfirmEmailFormTest.php b/tests/codeception/api/unit/models/authentication/ConfirmEmailFormTest.php index 1fd318b..2bbd5d7 100644 --- a/tests/codeception/api/unit/models/authentication/ConfirmEmailFormTest.php +++ b/tests/codeception/api/unit/models/authentication/ConfirmEmailFormTest.php @@ -25,9 +25,15 @@ class ConfirmEmailFormTest extends TestCase { $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 $user */ - $user = Account::findOne($fixture['account_id']); - $this->assertEquals(Account::STATUS_ACTIVE, $user->status, 'user status changed to active'); + /** @var Account $account */ + $account = Account::findOne($fixture['account_id']); + $this->assertEquals(Account::STATUS_ACTIVE, $account->status, 'user status changed to active'); + + $message = $this->tester->grabLastSentAmqpMessage('events'); + $body = json_decode($message->getBody(), true); + $this->assertEquals($account->id, $body['accountId']); + $this->assertEquals($account->username, $body['newUsername']); + $this->assertNull($body['oldUsername']); } private function createModel($key) { diff --git a/tests/codeception/api/unit/models/profile/ChangeEmail/ConfirmNewEmailFormTest.php b/tests/codeception/api/unit/models/profile/ChangeEmail/ConfirmNewEmailFormTest.php index 68ab6c4..3ac9e26 100644 --- a/tests/codeception/api/unit/models/profile/ChangeEmail/ConfirmNewEmailFormTest.php +++ b/tests/codeception/api/unit/models/profile/ChangeEmail/ConfirmNewEmailFormTest.php @@ -18,9 +18,8 @@ class ConfirmNewEmailFormTest extends TestCase { } public function testChangeEmail() { - $accountId = $this->tester->grabFixture('accounts', 'account-with-change-email-finish-state')['id']; /** @var Account $account */ - $account = Account::findOne($accountId); + $account = Account::findOne($this->getAccountId()); $newEmailConfirmationFixture = $this->tester->grabFixture('emailActivations', 'newEmailConfirmation'); $model = new ConfirmNewEmailForm($account, [ 'key' => $newEmailConfirmationFixture['key'], @@ -32,6 +31,23 @@ class ConfirmNewEmailFormTest extends TestCase { ])); $data = unserialize($newEmailConfirmationFixture['_data']); $this->assertEquals($data['newEmail'], $account->email); + $this->tester->canSeeAmqpMessageIsCreated('events'); + } + + public function testCreateTask() { + /** @var Account $account */ + $account = Account::findOne($this->getAccountId()); + $model = new ConfirmNewEmailForm($account); + $model->createTask(1, 'test1@ely.by', 'test@ely.by'); + $message = $this->tester->grabLastSentAmqpMessage('events'); + $body = json_decode($message->getBody(), true); + $this->assertEquals(1, $body['accountId']); + $this->assertEquals('test1@ely.by', $body['newEmail']); + $this->assertEquals('test@ely.by', $body['oldEmail']); + } + + private function getAccountId() { + return $this->tester->grabFixture('accounts', 'account-with-change-email-finish-state')['id']; } } diff --git a/tests/codeception/api/unit/models/profile/ChangeUsernameFormTest.php b/tests/codeception/api/unit/models/profile/ChangeUsernameFormTest.php index a41dd75..158b17e 100644 --- a/tests/codeception/api/unit/models/profile/ChangeUsernameFormTest.php +++ b/tests/codeception/api/unit/models/profile/ChangeUsernameFormTest.php @@ -35,6 +35,7 @@ class ChangeUsernameFormTest extends TestCase { $this->assertTrue($model->change()); $this->assertEquals('my_new_nickname', Account::findOne($this->getAccountId())->username); $this->assertInstanceOf(UsernameHistory::class, UsernameHistory::findOne(['username' => 'my_new_nickname'])); + $this->tester->canSeeAmqpMessageIsCreated('events'); } public function testChangeWithoutChange() { @@ -49,7 +50,8 @@ class ChangeUsernameFormTest extends TestCase { 'AND', 'username' => $username, ['>=', 'applied_in', $callTime], - ]), 'no new UsernameHistory record, if we don\'t change nickname'); + ]), 'no new UsernameHistory record, if we don\'t change username'); + $this->tester->cantSeeAmqpMessageIsCreated('events'); } public function testChangeCase() { @@ -65,13 +67,17 @@ class ChangeUsernameFormTest extends TestCase { UsernameHistory::findOne(['username' => $newUsername]), 'username should change, if we change case of some letters' ); + $this->tester->canSeeAmqpMessageIsCreated('events'); } public function testCreateTask() { $model = new ChangeUsernameForm(); - $model->createEventTask('1', 'test1', 'test'); - // TODO: у меня пока нет идей о том, чтобы это как-то успешно протестировать, увы - // но по крайней мере можно убедиться, что оно не падает где-то на этом шаге + $model->createEventTask(1, 'test1', 'test'); + $message = $this->tester->grabLastSentAmqpMessage('events'); + $body = json_decode($message->getBody(), true); + $this->assertEquals(1, $body['accountId']); + $this->assertEquals('test1', $body['newUsername']); + $this->assertEquals('test', $body['oldUsername']); } private function getAccountId() { diff --git a/tests/codeception/common/_support/amqp/Helper.php b/tests/codeception/common/_support/amqp/Helper.php new file mode 100644 index 0000000..bea9e03 --- /dev/null +++ b/tests/codeception/common/_support/amqp/Helper.php @@ -0,0 +1,106 @@ +getYii2()->client; + $app = $connector->getApplication(); + $app->set('amqp', [ + 'class' => TestComponent::class, + ]); + + parent::_before($test); + } + + /** + * Checks that message is created. + * + * ```php + * seeAmqpMessageIsCreated(); + * + * // check that only 3 messages were created + * $I->seeAmqpMessageIsCreated(3); + * ``` + * + * @param string|null $exchange + * @param int|null $num + */ + public function seeAmqpMessageIsCreated($exchange = null, $num = null) { + if ($num === null) { + $this->assertNotEmpty($this->grabSentAmqpMessages($exchange), 'message were created'); + return; + } + + // TODO: заменить на assertCount() после релиза Codeception 2.2.7 + // https://github.com/Codeception/Codeception/pull/3802 + /** @noinspection PhpUnitTestsInspection */ + $this->assertEquals( + $num, + count($this->grabSentAmqpMessages($exchange)), + 'number of created messages is equal to ' . $num + ); + } + + /** + * Checks that no messages was created + * + * @param string|null $exchange + */ + public function dontSeeAmqpMessageIsCreated($exchange = null) { + $this->seeAmqpMessageIsCreated($exchange, 0); + } + + /** + * Returns last sent message + * + * @param string|null $exchange + * @return \PhpAmqpLib\Message\AMQPMessage + */ + public function grabLastSentAmqpMessage($exchange = null) { + $this->seeAmqpMessageIsCreated(); + $messages = $this->grabSentAmqpMessages($exchange); + + return end($messages); + } + + /** + * Returns array of all sent amqp messages. + * Each message is `\PhpAmqpLib\Message\AMQPMessage` instance. + * Useful to perform additional checks using `Asserts` module. + * + * @param string|null $exchange + * @return \PhpAmqpLib\Message\AMQPMessage[] + * @throws ModuleException + */ + public function grabSentAmqpMessages($exchange = null) { + $amqp = $this->grabComponent('amqp'); + if (!$amqp instanceof TestComponent) { + throw new ModuleException($this, 'AMQP module is not mocked, can\'t test messages'); + } + + return $amqp->getSentMessages($exchange); + } + + private function grabComponent(string $component) { + return $this->getYii2()->grabComponent($component); + } + + private function getYii2() : Yii2 { + $yii2 = $this->getModule('Yii2'); + if (!$yii2 instanceof Yii2) { + throw new ModuleException($this, 'Yii2 module must be configured'); + } + + return $yii2; + } + +} diff --git a/tests/codeception/common/_support/RabbitMQComponent.php b/tests/codeception/common/_support/amqp/TestComponent.php similarity index 50% rename from tests/codeception/common/_support/RabbitMQComponent.php rename to tests/codeception/common/_support/amqp/TestComponent.php index 4c8fc3a..9b8e159 100644 --- a/tests/codeception/common/_support/RabbitMQComponent.php +++ b/tests/codeception/common/_support/amqp/TestComponent.php @@ -1,10 +1,16 @@ sentMessages[$exchangeName][] = $this->prepareMessage($message); + } + + /** + * @param string|null $exchangeName + * @return \PhpAmqpLib\Message\AMQPMessage[] + */ + public function getSentMessages(string $exchangeName = null) : array { + if ($exchangeName !== null) { + return $this->sentMessages[$exchangeName] ?? []; + } else { + $messages = []; + foreach($this->sentMessages as $exchangeGroup) { + foreach ($exchangeGroup as $message) { + $messages[] = $message; + } + } + + return $messages; + } } } diff --git a/tests/codeception/common/codeception.yml b/tests/codeception/common/codeception.yml index f81585b..ff6249c 100644 --- a/tests/codeception/common/codeception.yml +++ b/tests/codeception/common/codeception.yml @@ -1,5 +1,6 @@ namespace: tests\codeception\common actor: Tester +params: [env] paths: tests: . log: _output diff --git a/tests/codeception/common/unit.suite.yml b/tests/codeception/common/unit.suite.yml index d072b09..98fb59d 100644 --- a/tests/codeception/common/unit.suite.yml +++ b/tests/codeception/common/unit.suite.yml @@ -6,3 +6,4 @@ modules: config: Yii2: configFile: '../config/common/unit.php' + cleanup: false diff --git a/tests/codeception/config/config.php b/tests/codeception/config/config.php index fe8a64c..2904804 100644 --- a/tests/codeception/config/config.php +++ b/tests/codeception/config/config.php @@ -17,8 +17,5 @@ return [ // Для тестов нам не сильно важна безопасность, а вот время прохождения тестов значительно сокращается 'passwordHashCost' => 4, ], - 'amqp' => [ - 'class' => tests\codeception\common\_support\RabbitMQComponent::class, - ], ], ]; diff --git a/tests/codeception/console/codeception.yml b/tests/codeception/console/codeception.yml index 14c972e..57e8496 100644 --- a/tests/codeception/console/codeception.yml +++ b/tests/codeception/console/codeception.yml @@ -1,5 +1,6 @@ namespace: tests\codeception\console actor: Tester +params: [env] paths: tests: . log: _output diff --git a/tests/codeception/console/unit.suite.yml b/tests/codeception/console/unit.suite.yml index 3ac6f10..bdcb10b 100644 --- a/tests/codeception/console/unit.suite.yml +++ b/tests/codeception/console/unit.suite.yml @@ -6,3 +6,4 @@ modules: config: Yii2: configFile: '../config/console/unit.php' + cleanup: false