diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index 1fe49971..0c24bcfa 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -95,11 +95,16 @@ class UserController extends Controller
]);
}
- public function sign()
+ public function sign(Dispatcher $dispatcher, Filter $filter)
{
/** @var User */
$user = Auth::user();
+ $can = $filter->apply('can_sign', true);
+ if ($can instanceof Rejection) {
+ return json($can->getReason(), 2);
+ }
+
$lastSignTime = Carbon::parse($user->last_sign_at);
$remainingTime = option('sign_after_zero')
? Carbon::now()->diffInSeconds(
@@ -114,10 +119,16 @@ class UserController extends Controller
if ($remainingTime <= 0) {
[$min, $max] = explode(',', option('sign_score'));
$acquiredScore = rand((int) $min, (int) $max);
+ $acquiredScore = $filter->apply('sign_score', $acquiredScore);
+
+ $dispatcher->dispatch('user.sign.before', [$acquiredScore]);
+
$user->score += $acquiredScore;
$user->last_sign_at = Carbon::now();
$user->save();
+ $dispatcher->dispatch('user.sign.after', [$acquiredScore]);
+
return json(trans('user.sign-success', ['score' => $acquiredScore]), 0, [
'score' => $user->score,
]);
diff --git a/resources/assets/src/views/user/Dashboard/index.tsx b/resources/assets/src/views/user/Dashboard/index.tsx
index 11d8f2bb..9ecaa903 100644
--- a/resources/assets/src/views/user/Dashboard/index.tsx
+++ b/resources/assets/src/views/user/Dashboard/index.tsx
@@ -82,13 +82,15 @@ const Dashboard: React.FC = () => {
setLastSign(new Date())
setTweenedScore(data.score)
setScore(data.score)
- } else {
+ } else if (code === 1) {
const remainingTime = scoreUtils.remainingTime(
lastSign,
signGap,
canSignAfterZero,
)
toast.warning(scoreUtils.remainingTimeText(remainingTime))
+ } else {
+ toast.error(message)
}
setLoading(false)
}, [])
diff --git a/resources/assets/tests/views/user/Dashboard.test.tsx b/resources/assets/tests/views/user/Dashboard.test.tsx
index 202bf3af..50952204 100644
--- a/resources/assets/tests/views/user/Dashboard.test.tsx
+++ b/resources/assets/tests/views/user/Dashboard.test.tsx
@@ -87,7 +87,7 @@ describe('sign', () => {
expect(queryByText(/905/)).toBeInTheDocument()
})
- it('failed', async () => {
+ it('cannot sign', async () => {
fetch.post.mockResolvedValue({ code: 1, message: '' })
const { getByRole, getByText } = render()
@@ -102,6 +102,19 @@ describe('sign', () => {
).toBeInTheDocument()
expect(getByRole('alert')).toHaveClass('alert-warning')
})
+
+ it('failed', async () => {
+ fetch.post.mockResolvedValue({ code: 2, message: 'f' })
+
+ const { getByRole, getByText } = render()
+ await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
+
+ fireEvent.click(getByRole('button'))
+ await waitFor(() => expect(fetch.post).toBeCalledWith(urls.user.sign()))
+
+ expect(getByText('f')).toBeInTheDocument()
+ expect(getByRole('alert')).toHaveClass('alert-danger')
+ })
})
describe('sign button', () => {
diff --git a/tests/HttpTest/ControllersTest/UserControllerTest.php b/tests/HttpTest/ControllersTest/UserControllerTest.php
index fed56e96..4e077df5 100644
--- a/tests/HttpTest/ControllersTest/UserControllerTest.php
+++ b/tests/HttpTest/ControllersTest/UserControllerTest.php
@@ -79,6 +79,8 @@ class UserControllerTest extends TestCase
public function testSign()
{
+ Event::fake();
+ $filter = Fakes\Filter::fake();
option(['sign_score' => '50,50']);
$user = factory(User::class)->create();
@@ -92,25 +94,59 @@ class UserControllerTest extends TestCase
'score' => option('user_initial_score') + 50,
],
]);
+ $filter->assertApplied('sign_score', function ($score) {
+ $this->assertEquals(50, $score);
+
+ return true;
+ });
+ Event::assertDispatched('user.sign.before', function ($eventName, $payload) {
+ $this->assertEquals(50, $payload[0]);
+
+ return true;
+ });
+ Event::assertDispatched('user.sign.after', function ($eventName, $payload) {
+ $this->assertEquals(50, $payload[0]);
+
+ return true;
+ });
// remaining time is greater than 0
+ Event::fake();
$user = factory(User::class)->create(['last_sign_at' => Carbon::now()]);
option(['sign_gap_time' => 2]);
$this->actingAs($user)
->postJson('/user/sign')
->assertJson(['code' => 1]);
+ Event::assertNotDispatched('user.sign.before');
+ Event::assertNotDispatched('user.sign.after');
// can sign after 0 o'clock
+ Event::fake();
option(['sign_after_zero' => true]);
$user = factory(User::class)->create(['last_sign_at' => Carbon::now()]);
$this->actingAs($user)
->postJson('/user/sign')
->assertJson(['code' => 1]);
+ Event::assertNotDispatched('user.sign.before');
+ Event::assertNotDispatched('user.sign.after');
$user = factory(User::class)->create([
'last_sign_at' => Carbon::today(),
]);
- $this->actingAs($user)->postJson('/user/sign')->assertJson(['code' => 0]);
+ $this->actingAs($user)
+ ->postJson('/user/sign')
+ ->assertJson(['code' => 0]);
+
+ // rejected
+ Event::fake();
+ $filter->add('can_sign', function () {
+ return new Rejection('rejected');
+ });
+ $this
+ ->postJson('/user/sign')
+ ->assertJson(['code' => 2, 'message' => 'rejected']);
+ Event::assertNotDispatched('user.sign.before');
+ Event::assertNotDispatched('user.sign.after');
}
public function testSendVerificationEmail()