Skip to content

Commit

Permalink
Add changeRate method to Reaction (#100)
Browse files Browse the repository at this point in the history
* Add Reaction::changeRate method

* Add RateInvalid exception
  • Loading branch information
antonkomarev committed Aug 2, 2019
1 parent 0cf9a8f commit 478c1fa
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Follow [upgrade instructions](UPGRADING.md#from-v7-to-v8) to migrate code & data
- ([#91]) Added `rate DECIMIAL(4, 2)` column to `love_reactions` db table
- ([#91]) Added ability to call `Reacter::reactTo` with already reacted reactant, same reaction type, but only `rate` differs
- ([#91]) Added `Cog\Contracts\Love\Reaction\Exceptions\RateOutOfRange` exception
- ([#100]) Added `Cog\Contracts\Love\Reaction\Exceptions\RateInvalid` exception
- ([#96]) Added progress bar to `love:recount` Artisan command

### Changed
Expand Down Expand Up @@ -396,3 +397,4 @@ Follow [upgrade instructions](UPGRADING.md#from-v5-to-v6) to migrate database to
[#91]: https://github.com/cybercog/laravel-love/pull/91
[#96]: https://github.com/cybercog/laravel-love/pull/96
[#99]: https://github.com/cybercog/laravel-love/pull/99
[#100]: https://github.com/cybercog/laravel-love/pull/100
29 changes: 29 additions & 0 deletions contracts/Reaction/Exceptions/RateInvalid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
* This file is part of PHP Contracts: Love.
*
* (c) Anton Komarev <anton@komarev.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Cog\Contracts\Love\Reaction\Exceptions;

use Cog\Contracts\Love\Exceptions\LoveThrowable;
use UnexpectedValueException;

final class RateInvalid extends UnexpectedValueException implements
LoveThrowable
{
public static function withSameValue(float $rate): self
{
return new self(sprintf(
'Invalid Reaction rate: `%s`. Can not change to same value.',
$rate
));
}
}
2 changes: 2 additions & 0 deletions contracts/Reaction/Models/Reaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ public function isNotToReactant(Reactant $reactant): bool;
public function isByReacter(Reacter $reacter): bool;

public function isNotByReacter(Reacter $reacter): bool;

public function changeRate(float $rate): void;
}
10 changes: 1 addition & 9 deletions src/Reacter/Models/Reacter.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,7 @@ public function reactTo(
);
}

if ($reaction->getRate() === $rate) {
throw new ReactionAlreadyExists(
sprintf('Reaction of type `%s` with `%s` rate already exists.', $reactionType->getName(), $rate)
);
}

$reaction->update([
'rate' => $rate,
]);
$reaction->changeRate($rate);
}

public function unreactTo(
Expand Down
12 changes: 12 additions & 0 deletions src/Reaction/Models/Reaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Cog\Contracts\Love\Reactant\Models\Reactant as ReactantContract;
use Cog\Contracts\Love\Reacter\Models\Reacter as ReacterContract;
use Cog\Contracts\Love\Reaction\Exceptions\RateOutOfRange;
use Cog\Contracts\Love\Reaction\Exceptions\RateInvalid;
use Cog\Contracts\Love\Reaction\Models\Reaction as ReactionContract;
use Cog\Contracts\Love\ReactionType\Models\ReactionType as ReactionTypeContract;
use Cog\Laravel\Love\Reactant\Models\Reactant;
Expand Down Expand Up @@ -140,4 +141,15 @@ public function isNotByReacter(
): bool {
return !$this->isByReacter($reacter);
}

public function changeRate(
float $rate
): void {
if ($this->getRate() === $rate) {
throw RateInvalid::withSameValue($rate);
}

$this->setAttribute('rate', $rate);
$this->save();
}
}
15 changes: 15 additions & 0 deletions tests/Unit/Reacter/Facades/ReacterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Cog\Tests\Laravel\Love\Unit\Reacter\Facades;

use Cog\Contracts\Love\Reactant\Exceptions\ReactantInvalid;
use Cog\Contracts\Love\Reaction\Exceptions\RateInvalid;
use Cog\Contracts\Love\Reaction\Exceptions\ReactionAlreadyExists;
use Cog\Contracts\Love\Reaction\Exceptions\ReactionNotExists;
use Cog\Contracts\Love\ReactionType\Exceptions\ReactionTypeInvalid;
Expand Down Expand Up @@ -105,6 +106,20 @@ public function it_can_change_reaction_rate_with_react_to_when_reaction_already_
$this->assertSame(2.0, $assertReaction->rate);
}

/** @test */
public function it_throws_rate_invalid_on_react_to_when_reaction_already_exists_with_same_rate(): void
{
$this->expectException(RateInvalid::class);

$reacter = factory(Reacter::class)->create();
$reacterFacade = new ReacterFacade($reacter);
$reactable = factory(User::class)->create();
$reactionType = factory(ReactionType::class)->create();

$reacterFacade->reactTo($reactable, $reactionType->getName(), 2.0);
$reacterFacade->reactTo($reactable, $reactionType->getName(), 2.0);
}

/** @test */
public function it_throws_reaction_type_invalid_on_react_to_when_reaction_type_not_exist(): void
{
Expand Down
14 changes: 14 additions & 0 deletions tests/Unit/Reacter/Models/ReacterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use Cog\Contracts\Love\Reactant\Exceptions\ReactantInvalid;
use Cog\Contracts\Love\Reacter\Exceptions\NotAssignedToReacterable;
use Cog\Contracts\Love\Reaction\Exceptions\RateInvalid;
use Cog\Contracts\Love\Reaction\Exceptions\ReactionAlreadyExists;
use Cog\Contracts\Love\Reaction\Exceptions\ReactionNotExists;
use Cog\Laravel\Love\Reactant\Models\NullReactant;
Expand Down Expand Up @@ -212,6 +213,19 @@ public function it_can_change_reaction_rate_with_react_to_when_reaction_already_
$this->assertSame(2.0, $assertReaction->rate);
}

/** @test */
public function it_throws_rate_invalid_on_react_to_when_reaction_already_exists_with_same_rate(): void
{
$this->expectException(RateInvalid::class);

$reactionType = factory(ReactionType::class)->create();
$reacter = factory(Reacter::class)->create();
$reactant = factory(Reactant::class)->create();

$reacter->reactTo($reactant, $reactionType, 2.0);
$reacter->reactTo($reactant, $reactionType, 2.0);
}

/** @test */
public function it_throws_reactant_invalid_on_react_to_when_reactant_is_null_object(): void
{
Expand Down
49 changes: 49 additions & 0 deletions tests/Unit/Reaction/Models/ReactionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Cog\Tests\Laravel\Love\Unit\Reaction\Models;

use Cog\Contracts\Love\Reaction\Exceptions\RateOutOfRange;
use Cog\Contracts\Love\Reaction\Exceptions\RateInvalid;
use Cog\Laravel\Love\Reactant\Models\NullReactant;
use Cog\Laravel\Love\Reactant\Models\Reactant;
use Cog\Laravel\Love\Reacter\Models\NullReacter;
Expand Down Expand Up @@ -444,4 +445,52 @@ public function it_can_check_if_reaction_is_not_by_reacter_when_reacter_is_null_

$this->assertTrue($true);
}

/** @test */
public function it_can_change_rate(): void
{
$reaction = factory(Reaction::class)->create([
'rate' => 1.0,
]);

$reaction->changeRate(2.0);

$this->assertSame(2.0, $reaction->rate);
}

/** @test */
public function it_throws_rate_out_of_range_on_change_rate_with_overflow_value(): void
{
$this->expectException(RateOutOfRange::class);

$reaction = factory(Reaction::class)->create([
'rate' => 1.0,
]);

$reaction->changeRate(Reaction::RATE_MAX + 0.01);
}

/** @test */
public function it_throws_rate_out_of_range_on_change_rate_with_underflow_value(): void
{
$this->expectException(RateOutOfRange::class);

$reaction = factory(Reaction::class)->create([
'rate' => 1.0,
]);

$reaction->changeRate(Reaction::RATE_MIN - 0.01);
}

/** @test */
public function it_throws_rate_invalid_on_change_rate_with_same_value(): void
{
$this->expectException(RateInvalid::class);

$reaction = factory(Reaction::class)->create([
'rate' => 1.0,
]);

$reaction->changeRate(1.0);
}
}

0 comments on commit 478c1fa

Please sign in to comment.