Skip to content

Commit ab8c8c4

Browse files
committed
feat: LAR-188 add unit for point
1 parent 14d266d commit ab8c8c4

File tree

7 files changed

+217
-9
lines changed

7 files changed

+217
-9
lines changed

app-modules/gamify/src/Exceptions/InvalidPayeeModelException.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66

77
final class InvalidPayeeModelException extends \Exception
88
{
9-
protected $message = 'payee() method must return a model which will get the points.';
9+
public function __construct()
10+
{
11+
parent::__construct('payee() method must return a model which will get the points.');
12+
}
1013
}

app-modules/gamify/src/Exceptions/PointSubjectNotSetException.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@
88

99
final class PointSubjectNotSetException extends Exception
1010
{
11-
protected string $message = 'Initialize $subject field in constructor.';
11+
public function __construct()
12+
{
13+
parent::__construct('Initialize $subject field in constructor.');
14+
}
1215
}

app-modules/gamify/src/Exceptions/PointsNotDefinedException.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@
88

99
final class PointsNotDefinedException extends Exception
1010
{
11-
protected string $message = 'You must define a $points field or a getPoints() method.';
11+
public function __construct()
12+
{
13+
parent::__construct('You must define a $points field or a getPoints() method.');
14+
}
1215
}

app-modules/gamify/src/PointType.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,14 @@ public function qualifier(): bool
3232
*
3333
*
3434
* @throws PointSubjectNotSetException
35-
* @throws InvalidPayeeModelException
3635
*/
37-
public function payee(): User
36+
public function payee(): ?User
3837
{
3938
if (property_exists($this, 'payee')) {
4039
return $this->getSubject()->{$this->payee};
4140
}
4241

43-
throw new InvalidPayeeModelException;
42+
return null;
4443
}
4544

4645
/**
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use App\Models\User;
6+
use Laravelcm\Gamify\Exceptions\InvalidPayeeModelException;
7+
use Laravelcm\Gamify\Exceptions\PointsNotDefinedException;
8+
use Laravelcm\Gamify\Exceptions\PointSubjectNotSetException;
9+
use Laravelcm\Gamify\PointType;
10+
11+
final class FakeCreatePostPoint extends PointType
12+
{
13+
public int $points = 10;
14+
15+
public ?User $author;
16+
17+
public function __construct(mixed $subject, ?User $author = null)
18+
{
19+
$this->subject = $subject;
20+
$this->author = $author;
21+
}
22+
23+
public function payee(): ?User
24+
{
25+
return $this->author;
26+
}
27+
}
28+
29+
final class FakeWelcomeUserWithNamePoint extends PointType
30+
{
31+
public int $points = 30;
32+
33+
public ?User $author;
34+
35+
public string $name = 'FakeName';
36+
37+
public function __construct(mixed $subject, ?User $author = null) {}
38+
39+
public function payee(): ?User
40+
{
41+
return $this->author;
42+
}
43+
}
44+
45+
final class FakePointTypeWithoutSubject extends PointType
46+
{
47+
protected $point = 12;
48+
49+
public function payee(): ?User
50+
{
51+
return new User;
52+
}
53+
}
54+
55+
final class FakePointTypeWithoutPayee extends PointType
56+
{
57+
protected $point = 24;
58+
}
59+
60+
final class FakePointWithoutPoint extends PointType
61+
{
62+
protected $payee = 'user';
63+
64+
public function __construct($subject)
65+
{
66+
$this->subject = $subject;
67+
}
68+
}
69+
70+
final class FakeWelcomeUserWithFalseQualifier extends PointType
71+
{
72+
protected $points = 10;
73+
74+
public function __construct($subject)
75+
{
76+
$this->subject = $subject;
77+
}
78+
79+
public function qualifier(): bool
80+
{
81+
return false;
82+
}
83+
84+
public function payee(): ?User
85+
{
86+
return $this->getSubject()->user;
87+
}
88+
}
89+
90+
final class FakePayeeFieldPoint extends PointType
91+
{
92+
protected $points = 10;
93+
94+
public function __construct($subject)
95+
{
96+
$this->subject = $subject;
97+
}
98+
99+
/** @var string payee model relation on subject */
100+
protected $payee = 'user';
101+
}
102+
103+
beforeEach(function (): void {
104+
$this->user = $this->createUser();
105+
});
106+
107+
describe(PointType::class, function (): void {
108+
it('sets point type name from class name', function (): void {
109+
$point = new FakeCreatePostPoint($this->user);
110+
111+
expect($point->getName())->toBe('FakeCreatePostPoint');
112+
});
113+
114+
it('uses name property for point name if provided', function (): void {
115+
$point = new FakeWelcomeUserWithNamePoint($this->user);
116+
117+
expect($point->getName())->toBe('FakeName');
118+
});
119+
120+
it('can get points for a point type', function (): void {
121+
$point = new FakeCreatePostPoint($this->user);
122+
123+
expect($point->getPoints())->toBe(10);
124+
});
125+
126+
it('gives point to a user', function (): void {
127+
$post = $this->createPost(['user_id' => $this->user->id]);
128+
129+
$this->user->givePoint(new FakeCreatePostPoint($post, $this->user));
130+
131+
expect($this->user->getPoints())->toBe(10);
132+
expect($this->user->reputations)->toHaveCount(1);
133+
});
134+
135+
it('can access a reputation payee and subject', function (): void {
136+
$post = $this->createPost(['user_id' => $this->user->id]);
137+
138+
$this->user->givePoint(new FakeCreatePostPoint($post, $this->user));
139+
140+
$point = $this->user->reputations()->first();
141+
142+
expect($point->payee)->toBeInstanceOf(User::class);
143+
expect($point->subject)->toBeInstanceOf($post::class);
144+
expect($point->name)->toBe('FakeCreatePostPoint');
145+
});
146+
147+
it('do not give point if qualifier returns false', function (): void {
148+
$post = $this->createPost(['user_id' => $this->user->id]);
149+
150+
$this->user->givePoint(new FakeWelcomeUserWithFalseQualifier($post->user));
151+
152+
expect($this->user->fresh()->getPoints())->toBe(0);
153+
});
154+
155+
it('throws exception if no payee is returned', function (): void {
156+
$this->user->givePoint(new FakePointTypeWithoutPayee);
157+
158+
expect($this->user->fresh()->getPoints())->toBe(0);
159+
})
160+
->throws(InvalidPayeeModelException::class);
161+
162+
it('throws exception if no subject is set', function (): void {
163+
$this->user->givePoint(new FakePointTypeWithoutSubject);
164+
165+
expect($this->user->getPoints())->toBe(0);
166+
expect($this->user->reputations)->toHaveCount(0);
167+
})
168+
->throws(PointSubjectNotSetException::class);
169+
170+
it('throws exception if no points field or method is defined', function (): void {
171+
$post = $this->createPost(['user_id' => $this->user->id]);
172+
173+
$this->user->givePoint(new FakePointWithoutPoint($post));
174+
175+
expect($this->user->getPoint())->toBe(0);
176+
})
177+
->throws(PointsNotDefinedException::class);
178+
179+
it('gives and undo point via helper functions', function (): void {
180+
$post = $this->createPost(['user_id' => $this->user->id]);
181+
182+
givePoint(new FakePayeeFieldPoint($post), $this->user);
183+
184+
expect($this->user->fresh()->getPoints())->toBe(10);
185+
186+
undoPoint(new FakePayeeFieldPoint($post), $this->user);
187+
188+
$user = $this->user->fresh();
189+
expect($this->user->fresh()->getPoints())->toBe(0);
190+
});
191+
});

app/Gamify/Points/ReplyCreated.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace App\Gamify\Points;
66

77
use App\Models\User;
8-
use Laravelcm\Gamify\Exceptions\InvalidPayeeModelException;
98
use Laravelcm\Gamify\PointType;
109

1110
final class ReplyCreated extends PointType
@@ -20,8 +19,8 @@ public function __construct(mixed $subject, ?User $author = null)
2019
$this->author = $author;
2120
}
2221

23-
public function payee(): User
22+
public function payee(): ?User
2423
{
25-
return $this->author ?? throw new InvalidPayeeModelException;
24+
return $this->author;
2625
}
2726
}

tests/CreatesUsers.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Tests;
66

7+
use App\Models\Article;
78
use App\Models\User;
89

910
trait CreatesUsers
@@ -31,4 +32,13 @@ public function createUser(array $attributes = []): User
3132
'password' => bcrypt('password'),
3233
], $attributes));
3334
}
35+
36+
public function createPost(array $attributes = []): Article
37+
{
38+
return Article::factory()->create(array_merge([
39+
'title' => 'Dummy post title',
40+
'body' => 'I am the content on dummy post',
41+
'user_id' => 1,
42+
], $attributes));
43+
}
3444
}

0 commit comments

Comments
 (0)