From a8c7118e38116b5ec89e2d843124446c78d9af70 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Sun, 4 Dec 2016 19:56:49 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20Helper=20=D0=B4=D0=BB=D1=8F=20AMQP,=20=D0=BA=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D1=8B=D0=B9=20=D1=81=D0=BE=D0=B1=D0=B8=D1=80?= =?UTF-8?q?=D0=B0=D0=B5=D1=82=20=D0=B2=D1=81=D0=B5=20=D0=BF=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D1=83=D0=BF=D0=B0=D1=8E=D1=89=D0=B8=D0=B5=20=D1=81=D0=BE?= =?UTF-8?q?=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D1=8F?= =?UTF-8?q?=D0=B5=D1=82=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=98?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B1=D0=B0?= =?UTF-8?q?=D0=B3=20=D0=B2=20=D1=84=D0=BE=D1=80=D0=BC=D0=B5=20ChangeUserna?= =?UTF-8?q?meForm=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=20=D0=B1=D0=B0=D0=B3=20=D1=81=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8?= =?UTF-8?q?=D0=B3=D1=83=D1=80=D0=B0=D1=86=D0=B8=D0=B5=D0=B9=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=B2,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BD=D0=B5=20=D0=BF=D0=BE=D0=B7=D0=B2=D0=BE?= =?UTF-8?q?=D0=BB=D1=8F=D0=BB=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B4=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=81=D1=83=D1=89=D0=B5=D1=81=D1=82=D0=B2=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5\=D0=BD=D0=B5=D1=81=D1=83=D1=89?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B2=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B5=D0=B9=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=BA=D0=B0=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B0=D1=87=D0=B8=20=D1=85=D0=BE=D1=81=D1=82=D0=B0=20Redis=20?= =?UTF-8?q?=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20env=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=B2=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/models/profile/ChangeUsernameForm.php | 10 +- tests/codeception/api/codeception.yml | 1 + tests/codeception/api/functional.suite.yml | 5 +- tests/codeception/api/unit.suite.yml | 2 + .../authentication/ConfirmEmailFormTest.php | 12 +- .../ChangeEmail/ConfirmNewEmailFormTest.php | 20 +++- .../models/profile/ChangeUsernameFormTest.php | 14 ++- .../common/_support/amqp/Helper.php | 106 ++++++++++++++++++ .../TestComponent.php} | 31 ++++- tests/codeception/common/codeception.yml | 1 + tests/codeception/common/unit.suite.yml | 1 + tests/codeception/config/config.php | 3 - tests/codeception/console/codeception.yml | 1 + tests/codeception/console/unit.suite.yml | 1 + 14 files changed, 188 insertions(+), 20 deletions(-) create mode 100644 tests/codeception/common/_support/amqp/Helper.php rename tests/codeception/common/_support/{RabbitMQComponent.php => amqp/TestComponent.php} (50%) 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