Add tests for UserController

This commit is contained in:
Pig Fang 2017-11-18 13:25:08 +08:00
parent 7d48c6a609
commit 99aee71cc8
3 changed files with 479 additions and 21 deletions

View File

@ -62,16 +62,16 @@ class UserController extends Controller
/** /**
* Handle user signing. * Handle user signing.
* *
* @return void * @return \Illuminate\Http\JsonResponse
*/ */
public function sign() public function sign()
{ {
if ($this->user->canSign()) { if ($this->user->canSign()) {
$acuiredScore = $this->user->sign(); $acquiredScore = $this->user->sign();
return json([ return json([
'errno' => 0, 'errno' => 0,
'msg' => trans('user.sign-success', ['score' => $acuiredScore]), 'msg' => trans('user.sign-success', ['score' => $acquiredScore]),
'score' => $this->user->getScore(), 'score' => $this->user->getScore(),
'storage' => $this->calculatePercentageUsed($this->user->getStorageUsed(), option('score_per_storage')), 'storage' => $this->calculatePercentageUsed($this->user->getStorageUsed(), option('score_per_storage')),
'remaining_time' => $this->getUserSignRemainingTimeWithPrecision() 'remaining_time' => $this->getUserSignRemainingTimeWithPrecision()
@ -79,7 +79,8 @@ class UserController extends Controller
} else { } else {
$remaining_time = $this->getUserSignRemainingTimeWithPrecision(); $remaining_time = $this->getUserSignRemainingTimeWithPrecision();
return json(trans('user.cant-sign-until', [ return json(trans('user.cant-sign-until', [
'time' => $remaining_time >= 1 ?: round($remaining_time * 60), 'time' => $remaining_time >= 1
? $remaining_time : round($remaining_time * 60),
'unit' => $remaining_time >= 1 'unit' => $remaining_time >= 1
? trans('user.time-unit-hour') : trans('user.time-unit-min') ? trans('user.time-unit-hour') : trans('user.time-unit-min')
]), 1); ]), 1);
@ -102,6 +103,7 @@ class UserController extends Controller
* Handle changing user profile. * Handle changing user profile.
* *
* @param Request $request * @param Request $request
* @param UserRepository $users
* @return mixed * @return mixed
*/ */
public function handleProfile(Request $request, UserRepository $users) public function handleProfile(Request $request, UserRepository $users)
@ -116,10 +118,12 @@ class UserController extends Controller
$nickname = $request->input('new_nickname'); $nickname = $request->input('new_nickname');
if ($this->user->setNickName($nickname)) if ($this->user->setNickName($nickname)) {
event(new UserProfileUpdated($action, $this->user));
return json(trans('user.profile.nickname.success', ['nickname' => $nickname]), 0); return json(trans('user.profile.nickname.success', ['nickname' => $nickname]), 0);
}
break; break; // @codeCoverageIgnore
case 'password': case 'password':
$this->validate($request, [ $this->validate($request, [
@ -130,10 +134,12 @@ class UserController extends Controller
if (!$this->user->verifyPassword($request->input('current_password'))) if (!$this->user->verifyPassword($request->input('current_password')))
return json(trans('user.profile.password.wrong-password'), 1); return json(trans('user.profile.password.wrong-password'), 1);
if ($this->user->changePasswd($request->input('new_password'))) if ($this->user->changePasswd($request->input('new_password'))) {
event(new UserProfileUpdated($action, $this->user));
return json(trans('user.profile.password.success'), 0); return json(trans('user.profile.password.success'), 0);
}
break; break; // @codeCoverageIgnore
case 'email': case 'email':
$this->validate($request, [ $this->validate($request, [
@ -148,10 +154,12 @@ class UserController extends Controller
if (!$this->user->verifyPassword($request->input('password'))) if (!$this->user->verifyPassword($request->input('password')))
return json(trans('user.profile.email.wrong-password'), 1); return json(trans('user.profile.email.wrong-password'), 1);
if ($this->user->setEmail($request->input('new_email'))) if ($this->user->setEmail($request->input('new_email'))) {
event(new UserProfileUpdated($action, $this->user));
return json(trans('user.profile.email.success'), 0); return json(trans('user.profile.email.success'), 0);
}
break; break; // @codeCoverageIgnore
case 'delete': case 'delete':
$this->validate($request, [ $this->validate($request, [
@ -162,24 +170,24 @@ class UserController extends Controller
return json(trans('user.profile.delete.wrong-password'), 1); return json(trans('user.profile.delete.wrong-password'), 1);
if ($this->user->delete()) { if ($this->user->delete()) {
setcookie('uid', '', time() - 3600, '/');
setcookie('token', '', time() - 3600, '/');
session()->flush(); session()->flush();
return json(trans('user.profile.delete.success'), 0); return response()
->json([
'errno' => 0,
'msg' => trans('user.profile.delete.success')
])
->cookie('uid', '', time() - 3600, '/')
->cookie('token', '', time() - 3600, '/');
} }
break; break; // @codeCoverageIgnore
default: default:
return json(trans('general.illegal-parameters'), 1); return json(trans('general.illegal-parameters'), 1);
break; break;
} }
} // @codeCoverageIgnore
event(new UserProfileUpdated($action, $this->user));
}
/** /**
* Set user avatar. * Set user avatar.
@ -204,6 +212,6 @@ class UserController extends Controller
} else { } else {
return json(trans('skinlib.non-existent'), 1); return json(trans('skinlib.non-existent'), 1);
} }
} } // @codeCoverageIgnore
} }

View File

@ -168,7 +168,8 @@ class User extends Model
/** /**
* Set new email for user. * Set new email for user.
* *
* @param string $new_email * @param string $new_email
* @return bool
*/ */
public function setEmail($new_email) public function setEmail($new_email)
{ {

View File

@ -0,0 +1,449 @@
<?php
use App\Events;
use App\Models\User;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class UserControllerTest extends TestCase
{
use DatabaseTransactions;
protected function setUp()
{
parent::setUp();
return $this->actAs('normal');
}
public function testIndex()
{
$user = factory(User::class)->create();
factory(\App\Models\Player::class)->create(['uid' => $user->uid]);
$players_count = option('score_per_player') / option('user_initial_score');
$this->actAs($user)
->visit('/user')
->assertViewHas('user')
->assertViewHas('statistics')
->see(1 / $players_count * 100) // Players
->see(0) // Storage
->see(bs_announcement())
->see($user->score);
}
public function testSign()
{
option(['sign_score' => '50,50']);
$user = factory(User::class)->create();
// Success
$this->actAs($user)
->post('/user/sign')
->seeJson([
'errno' => 0,
'msg' => trans('user.sign-success', ['score' => 50]),
'score' => option('user_initial_score') + 50,
'storage' => [
'percentage' => 0,
'total' => option('user_initial_score') + 50,
'used' => 0
],
'remaining_time' => (int) option('sign_gap_time')
]);
// Remaining time is greater than 0
$this->post('/user/sign')
->seeJson([
'errno' => 1,
'msg' => trans(
'user.cant-sign-until',
[
'time' => option('sign_gap_time'),
'unit' => trans('user.time-unit-hour')
]
)
]);
// Can sign after 0 o'clock
option(['sign_after_zero' => true]);
$diff = \Carbon\Carbon::now()->diffInSeconds(\Carbon\Carbon::tomorrow());
$unit = '';
if ($diff / 3600 >= 1) {
$diff = round($diff / 3600);
$unit = 'hour';
} else {
$diff = round($diff / 60);
$unit = 'min';
}
$this->post('/user/sign')
->seeJson([
'errno' => 1,
'msg' => trans(
'user.cant-sign-until',
[
'time' => $diff,
'unit' => trans("user.time-unit-$unit")
]
)
]);
$user->last_sign_at = \Carbon\Carbon::today()->toDateTimeString();
$user->save();
$this->post('/user/sign')
->seeJson([
'errno' => 0
]);
}
public function testProfile()
{
$this->visit('/user/profile')
->assertViewHas('user');
}
public function testHandleProfile()
{
$user = factory(User::class)->create();
$user->changePasswd('12345678');
// Invalid action
$this->actAs($user)
->post('/user/profile')
->seeJson([
'errno' => 1,
'msg' => trans('general.illegal-parameters')
]);
// Change nickname without `new_nickname` field
$this->post('/user/profile', [
'action' => 'nickname'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.required', ['attribute' => 'new nickname'])
]);
// Invalid nickname
$this->post('/user/profile', [
'action' => 'nickname',
'new_nickname' => '\\'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.nickname', ['attribute' => 'new nickname'])
]);
// Too long nickname
$this->post('/user/profile', [
'action' => 'nickname',
'new_nickname' => str_random(256)
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.max.string', ['attribute' => 'new nickname', 'max' => 255])
]);
// Change nickname successfully
$this->expectsEvents(Events\UserProfileUpdated::class);
$this->post('/user/profile', [
'action' => 'nickname',
'new_nickname' => 'nickname'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 0,
'msg' => trans('user.profile.nickname.success', ['nickname' => 'nickname'])
]);
$this->assertEquals('nickname', User::find($user->uid)->nickname);
// Change password without `current_password` field
$this->post('/user/profile', [
'action' => 'password'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.required', ['attribute' => 'current password'])
]);
// Too short current password
$this->post('/user/profile', [
'action' => 'password',
'current_password' => '1'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.min.string', ['attribute' => 'current password', 'min' => 6])
]);
// Too long current password
$this->post('/user/profile', [
'action' => 'password',
'current_password' => str_random(17)
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.max.string', ['attribute' => 'current password', 'max' => 16])
]);
// Too short new password
$this->post('/user/profile', [
'action' => 'password',
'current_password' => '12345678',
'new_password' => '1'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.min.string', ['attribute' => 'new password', 'min' => 8])
]);
// Too long new password
$this->post('/user/profile', [
'action' => 'password',
'current_password' => '12345678',
'new_password' => str_random(17)
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.max.string', ['attribute' => 'new password', 'max' => 16])
]);
// Wrong old password
$this->post('/user/profile', [
'action' => 'password',
'current_password' => '1234567',
'new_password' => '87654321'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('user.profile.password.wrong-password')
]);
// Change password successfully
$this->expectsEvents(Events\EncryptUserPassword::class);
$this->post('/user/profile', [
'action' => 'password',
'current_password' => '12345678',
'new_password' => '87654321'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 0,
'msg' => trans('user.profile.password.success')
]);
$this->assertTrue(User::find($user->uid)->verifyPassword('87654321'));
// After changed password, user should re-login.
$this->visit('/user')->seePageIs('/auth/login');
$user = User::find($user->uid);
// Change email without `new_email` field
$this->actAs($user)
->post(
'/user/profile',
['action' => 'email'],
['X-Requested-With' => 'XMLHttpRequest'])
->seeJson([
'errno' => 1,
'msg' => trans('validation.required', ['attribute' => 'new email'])
]);
// Invalid email
$this->post('/user/profile', [
'action' => 'email',
'new_email' => 'not_an_email'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.email', ['attribute' => 'new email'])
]);
// Too short current password
$this->post('/user/profile', [
'action' => 'email',
'new_email' => 'a@b.c',
'password' => '1'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.min.string', ['attribute' => 'password', 'min' => 6])
]);
// Too long current password
$this->post('/user/profile', [
'action' => 'email',
'new_email' => 'a@b.c',
'password' => str_random(17)
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.max.string', ['attribute' => 'password', 'max' => 16])
]);
// Use a duplicated email
$this->post('/user/profile', [
'action' => 'email',
'new_email' => $user->email,
'password' => '87654321'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('user.profile.email.existed')
]);
// Wrong password
$this->post('/user/profile', [
'action' => 'email',
'new_email' => 'a@b.c',
'password' => '7654321'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('user.profile.email.wrong-password')
]);
// Change email successfully
$this->post('/user/profile', [
'action' => 'email',
'new_email' => 'a@b.c',
'password' => '87654321'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 0,
'msg' => trans('user.profile.email.success')
]);
$this->assertEquals('a@b.c', User::find($user->uid)->email);
// After changed email, user should re-login.
$this->visit('/user')->seePageIs('/auth/login');
$user = User::find($user->uid);
// Delete account without `password` field
$this->actAs($user)
->post(
'/user/profile',
['action' => 'delete'],
['X-Requested-With' => 'XMLHttpRequest'])
->seeJson([
'errno' => 1,
'msg' => trans('validation.required', ['attribute' => 'password'])
]);
// Too short current password
$this->post('/user/profile', [
'action' => 'delete',
'password' => '1'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.min.string', ['attribute' => 'password', 'min' => 6])
]);
// Too long current password
$this->post('/user/profile', [
'action' => 'delete',
'password' => str_random(17)
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('validation.max.string', ['attribute' => 'password', 'max' => 16])
]);
// Wrong password
$this->post('/user/profile', [
'action' => 'delete',
'password' => '7654321'
], [
'X-Requested-With' => 'XMLHttpRequest'
])->seeJson([
'errno' => 1,
'msg' => trans('user.profile.delete.wrong-password')
]);
// Delete account successfully
$this->post('/user/profile', [
'action' => 'delete',
'password' => '87654321'
])->seeJson([
'errno' => 0,
'msg' => trans('user.profile.delete.success')
])->seeCookie('uid', '')
->seeCookie('token', '');
$this->assertNull(User::find($user->uid));
}
public function testSetAvatar()
{
$user = factory(User::class)->create();
$steve = factory(\App\Models\Texture::class)->create();
$cape = factory(\App\Models\Texture::class, 'cape')->create();
// Without `tid` field
$this->actAs($user)
->post('/user/profile/avatar', [], [
'X-Requested-With' => 'XMLHttpRequest'
])
->seeJson([
'errno' => 1,
'msg' => trans('validation.required', ['attribute' => 'tid'])
]);
// TID is not a integer
$this->actAs($user)
->post('/user/profile/avatar', [
'tid' => 'string'
], [
'X-Requested-With' => 'XMLHttpRequest'
])
->seeJson([
'errno' => 1,
'msg' => trans('validation.integer', ['attribute' => 'tid'])
]);
// Texture cannot be found
$this->actAs($user)
->post('/user/profile/avatar', [
'tid' => 0
])
->seeJson([
'errno' => 1,
'msg' => trans('skinlib.non-existent')
]);
// Use cape
$this->actAs($user)
->post('/user/profile/avatar', [
'tid' => $cape->tid
])
->seeJson([
'errno' => 1,
'msg' => trans('user.profile.avatar.wrong-type')
]);
// Success
$this->actAs($user)
->post('/user/profile/avatar', [
'tid' => $steve->tid
])
->seeJson([
'errno' => 0,
'msg' => trans('user.profile.avatar.success')
]);
$this->assertEquals($steve->tid, User::find($user->uid)->avatar);
}
}