diff --git a/app/Http/Controllers/PlayerController.php b/app/Http/Controllers/PlayerController.php index 992a9a33..ba351973 100644 --- a/app/Http/Controllers/PlayerController.php +++ b/app/Http/Controllers/PlayerController.php @@ -56,7 +56,7 @@ class PlayerController extends Controller 'player_name' => 'required|'.(option('allow_chinese_playername') ? 'pname_chinese' : 'playername') ]); - Event::fire(new CheckPlayerExists($request->input('player_name'))); + event(new CheckPlayerExists($request->input('player_name'))); if (!Player::where('player_name', $request->input('player_name'))->get()->isEmpty()) { return json(trans('user.player.add.repeated'), 6); @@ -66,7 +66,7 @@ class PlayerController extends Controller return json(trans('user.player.add.lack-score'), 7); } - Event::fire(new PlayerWillBeAdded($request->input('player_name'))); + event(new PlayerWillBeAdded($request->input('player_name'))); $player = new Player; @@ -76,7 +76,7 @@ class PlayerController extends Controller $player->last_modified = Utils::getTimeFormatted(); $player->save(); - Event::fire(new PlayerWasAdded($player)); + event(new PlayerWasAdded($player)); $this->user->setScore(option('score_per_player'), 'minus'); @@ -87,22 +87,21 @@ class PlayerController extends Controller { $player_name = $this->player->player_name; - Event::fire(new PlayerWillBeDeleted($this->player)); + event(new PlayerWillBeDeleted($this->player)); - if ($this->player->delete()) { + $this->player->delete(); - if (option('return_score')) - $this->user->setScore(Option::get('score_per_player'), 'plus'); + if (option('return_score')) + $this->user->setScore(Option::get('score_per_player'), 'plus'); - Event::fire(new PlayerWasDeleted($player_name)); + event(new PlayerWasDeleted($player_name)); - return json(trans('user.player.delete.success', ['name' => $player_name]), 0); - } + return json(trans('user.player.delete.success', ['name' => $player_name]), 0); } public function show() { - return json_encode($this->player->toArray(), JSON_NUMERIC_CHECK); + return response()->json($this->player->toArray()); } public function rename(Request $request) @@ -126,6 +125,9 @@ class PlayerController extends Controller /** * A wrapper of Player::setTexture() + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse */ public function setTexture(Request $request) { diff --git a/app/Models/Player.php b/app/Models/Player.php index a6995e2c..2b50742f 100644 --- a/app/Models/Player.php +++ b/app/Models/Player.php @@ -46,7 +46,7 @@ class Player extends Model /** * Return the owner of the player. * - * @return App\Models\User + * @return \App\Models\User */ public function user() { @@ -75,7 +75,7 @@ class Player extends Model * Set textures for the player. * * @param array $tids - * @return mixed + * @return $this */ public function setTexture(Array $tids) { @@ -91,7 +91,9 @@ class Player extends Model $this->save(); - return Event::fire(new PlayerProfileUpdated($this)); + event(new PlayerProfileUpdated($this)); + + return $this; } /** @@ -165,6 +167,8 @@ class Player extends Model * Set preferred model for the player. * * @param string $type slim|default + * + * @return $this */ public function setPreference($type) { @@ -173,7 +177,9 @@ class Player extends Model 'last_modified' => Utils::getTimeFormatted() ]); - return Event::fire(new PlayerProfileUpdated($this)); + event(new PlayerProfileUpdated($this)); + + return $this; } /** @@ -190,7 +196,7 @@ class Player extends Model * Rename the player. * * @param string $new_name - * @return mixed + * @return $this; */ public function rename($new_name) { @@ -201,18 +207,24 @@ class Player extends Model $this->player_name = $new_name; - return Event::fire(new PlayerProfileUpdated($this)); + event(new PlayerProfileUpdated($this)); + + return $this; } /** * Set a new owner for the player. * * @param int $uid + * + * @return $this */ public function setOwner($uid) { $this->update(['uid' => $uid]); - return Event::fire(new PlayerProfileUpdated($this)); + event(new PlayerProfileUpdated($this)); + + return $this; } /** diff --git a/resources/assets/src/js/__tests__/user.test.js b/resources/assets/src/js/__tests__/user.test.js index c65929f1..8e4d5e47 100644 --- a/resources/assets/src/js/__tests__/user.test.js +++ b/resources/assets/src/js/__tests__/user.test.js @@ -404,7 +404,7 @@ describe('tests for "player" module', () => { expect($('#1').hasClass('player-selected')).toBe(false); expect($('#2').hasClass('player-selected')).toBe(true); expect(fetch).toBeCalledWith({ - type: 'POST', + type: 'GET', url: 'user/player/show', dataType: 'json', data: { pid: '2' } diff --git a/resources/assets/src/js/user/player.js b/resources/assets/src/js/user/player.js index 406818cb..1409371e 100644 --- a/resources/assets/src/js/user/player.js +++ b/resources/assets/src/js/user/player.js @@ -26,7 +26,7 @@ $('body').on('click', '.player', function () { async function showPlayerTexturePreview(pid) { try { const result = await fetch({ - type: 'POST', + type: 'GET', url: url('user/player/show'), dataType: 'json', data: { pid: pid } diff --git a/routes/web.php b/routes/web.php index c4ef9be3..43d95ed6 100644 --- a/routes/web.php +++ b/routes/web.php @@ -55,10 +55,9 @@ Route::group(['middleware' => 'auth', 'prefix' => 'user'], function () // Player Route::any ('/player', 'PlayerController@index'); Route::post('/player/add', 'PlayerController@add'); - Route::post('/player/show', 'PlayerController@show'); + Route::any ('/player/show', 'PlayerController@show'); Route::post('/player/preference', 'PlayerController@setPreference'); Route::post('/player/set', 'PlayerController@setTexture'); - Route::post('/player/texture', 'PlayerController@changeTexture'); Route::post('/player/texture/clear', 'PlayerController@clearTexture'); Route::post('/player/rename', 'PlayerController@rename'); Route::post('/player/delete', 'PlayerController@delete'); diff --git a/tests/PlayerControllerTest.php b/tests/PlayerControllerTest.php new file mode 100644 index 00000000..dcfd40b3 --- /dev/null +++ b/tests/PlayerControllerTest.php @@ -0,0 +1,318 @@ +actAs('normal'); + } + + public function testIndex() + { + $this->visit('/user/player?pid=5') + ->assertViewHas('players') + ->assertViewHas('user'); + } + + public function testAdd() + { + // Without player name + $this->post('/user/player/add', [], ['X-Requested-With' => 'XMLHttpRequest']) + ->seeJson([ + 'errno' => 1, + 'msg' => trans('validation.required', ['attribute' => 'Player Name']) + ]); + + // Not allowed to use Chinese characters + option(['allow_chinese_playername' => false]); + $this->post('/user/player/add', [ + 'player_name' => '角色名' + ], ['X-Requested-With' => 'XMLHttpRequest']) + ->seeJson([ + 'errno' => 1, + 'msg' => trans('validation.playername', ['attribute' => 'Player Name']) + ]); + + // Lack of score + $user = factory(User::class)->create(['score' => 0]); + $this->actAs($user) + ->post('/user/player/add', ['player_name' => 'no_score']) + ->seeJson([ + 'errno' => 7, + 'msg' => trans('user.player.add.lack-score') + ]); + $this->expectsEvents(Events\CheckPlayerExists::class); + + // Allowed to use Chinese characters + option(['allow_chinese_playername' => true]); + $user = factory(User::class)->create(); + $score = $user->score; + $this->actAs($user) + ->post('/user/player/add', [ + 'player_name' => '角色名' + ])->seeJson([ + 'errno' => 0, + 'msg' => trans('user.player.add.success', ['name' => '角色名']) + ]); + $this->expectsEvents(Events\PlayerWillBeAdded::class); + $this->expectsEvents(Events\PlayerWasAdded::class); + $player = Player::where('player_name', '角色名')->first(); + $this->assertNotNull($player); + $this->assertEquals($user->uid, $player->uid); + $this->assertEquals('角色名', $player->player_name); + $this->assertEquals('default', $player->preference); + $this->assertEquals( + $score - option('score_per_player'), + User::find($user->uid)->score + ); + + // Add a existed player + $this->post('/user/player/add', ['player_name' => '角色名']) + ->seeJson([ + 'errno' => 6, + 'msg' => trans('user.player.add.repeated') + ]); + } + + public function testDelete() + { + $player = factory(Player::class)->create(); + $user = User::find($player->uid); + $this->expectsEvents(Events\PlayerWillBeDeleted::class); + $this->actAs($user) + ->post('/user/player/delete', ['pid' => $player->pid]) + ->seeJson([ + 'errno' => 0, + 'msg' => trans('user.player.delete.success', ['name' => $player->player_name]) + ]); + $this->assertNull(Player::find($player->pid)); + $this->expectsEvents(Events\PlayerWasDeleted::class); + $this->assertEquals( + $user->score + option('score_per_player'), + User::find($user->uid)->score + ); + + // No returning score + option(['return_score' => false]); + $player = factory(Player::class)->create(); + $user = User::find($player->uid); + $this->actAs($user) + ->post('/user/player/delete', ['pid' => $player->pid]) + ->seeJson([ + 'errno' => 0, + 'msg' => trans('user.player.delete.success', ['name' => $player->player_name]) + ]); + $this->assertEquals( + $user->score, + User::find($user->uid)->score + ); + } + + public function testShow() + { + $player = factory(Player::class)->create(['last_modified' => '2017-11-11 22:51:00']); + $this->get('/user/player/show?pid='.$player->pid) + ->seeJson($player->toArray()); + } + + public function testRename() + { + $player = factory(Player::class)->create(); + $user = User::find($player->uid); + + // Without new player name + $this->actAs($user) + ->post('/user/player/rename', [ + 'pid' => $player->pid, + ], [ + 'X-Requested-With' => 'XMLHttpRequest' + ])->seeJson([ + 'errno' => 1, + 'msg' => trans('validation.required', ['attribute' => 'Player Name']) + ]); + + // Chinese characters are not allowed + option(['allow_chinese_playername' => false]); + $this->post('/user/player/rename', [ + 'pid' => $player->pid, + 'new_player_name' => '角色名' + ], [ + 'X-Requested-With' => 'XMLHttpRequest' + ])->seeJson([ + 'errno' => 1, + 'msg' => trans('validation.playername', ['attribute' => 'Player Name']) + ]); + + // Other invalid characters + option(['allow_chinese_playername' => true]); + $this->post('/user/player/rename', [ + 'pid' => $player->pid, + 'new_player_name' => '\\' + ], [ + 'X-Requested-With' => 'XMLHttpRequest' + ])->seeJson([ + 'errno' => 1, + 'msg' => trans('validation.pname_chinese', ['attribute' => 'Player Name']) + ]); + + // Use a duplicated player name + $name = factory(Player::class)->create()->player_name; + $this->post('/user/player/rename', [ + 'pid' => $player->pid, + 'new_player_name' => $name + ])->seeJson([ + 'errno' => 6, + 'msg' => trans('user.player.rename.repeated') + ]); + + // Success + $this->expectsEvents(Events\PlayerProfileUpdated::class); + $this->post('/user/player/rename', [ + 'pid' => $player->pid, + 'new_player_name' => 'new_name' + ])->seeJson([ + 'errno' => 0, + 'msg' => trans( + 'user.player.rename.success', + ['old' => $player->player_name, 'new' => 'new_name'] + ) + ]); + } + + public function testSetTexture() + { + $player = factory(Player::class)->create(); + $user = User::find($player->uid); + $steve = factory(Texture::class)->create(); + $alex = factory(Texture::class, 'alex')->create(); + $cape = factory(Texture::class, 'cape')->create(); + + // Set a not-existed texture + $this->actAs($user) + ->post('/user/player/set', [ + 'pid' => $player->pid, + 'tid' => ['steve' => -1] + ])->seeJson([ + 'errno' => 6, + 'msg' => trans('skinlib.un-existent') + ]); + + $this->post('/user/player/set', [ + 'pid' => $player->pid, + 'tid' => ['steve' => $steve->tid] + ])->seeJson([ + 'errno' => 0, + 'msg' => trans('user.player.set.success', ['name' => $player->player_name]) + ]); + $this->expectsEvents(Events\PlayerProfileUpdated::class); + $this->assertEquals($steve->tid, Player::find($player->pid)->tid_steve); + + $this->post('/user/player/set', [ + 'pid' => $player->pid, + 'tid' => ['alex' => $alex->tid] + ])->seeJson([ + 'errno' => 0, + 'msg' => trans('user.player.set.success', ['name' => $player->player_name]) + ]); + $this->assertEquals($alex->tid, Player::find($player->pid)->tid_alex); + + $this->post('/user/player/set', [ + 'pid' => $player->pid, + 'tid' => ['cape' => $cape->tid] + ])->seeJson([ + 'errno' => 0, + 'msg' => trans('user.player.set.success', ['name' => $player->player_name]) + ]); + $this->assertEquals($cape->tid, Player::find($player->pid)->tid_cape); + + // Invalid texture type is acceptable + $this->post('/user/player/set', [ + 'pid' => $player->pid, + 'tid' => ['nope' => $steve->tid] // TID must be valid + ])->seeJson([ + 'errno' => 0, + 'msg' => trans('user.player.set.success', ['name' => $player->player_name]) + ]); + } + + public function testClearTexture() + { + $player = factory(Player::class)->create(); + $user = User::find($player->uid); + + $player->setTexture([ + 'tid_steve' => 1, + 'tid_alex' => 2, + 'tid_cape' => 3 + ]); + $player = Player::find($player->pid); + + $this->expectsEvents(Events\PlayerProfileUpdated::class); + $this->actAs($user) + ->post('/user/player/texture/clear', [ + 'pid' => $player->pid, + 'steve' => 1, // "1" stands for "true" + 'alex' => 1, + 'cape' => 1, + 'nope' => 1, // Invalid texture type is acceptable + ])->seeJson([ + 'errno' => 0, + 'msg' => trans('user.player.clear.success', ['name' => $player->player_name]) + ]); + $this->assertEquals(0, Player::find($player->pid)->tid_steve); + $this->assertEquals(0, Player::find($player->pid)->tid_alex); + $this->assertEquals(0, Player::find($player->pid)->tid_cape); + } + + public function testSetPreference() + { + // Without `preference` field + $player = factory(Player::class)->create(); + $this->post('/user/player/preference', [ + 'pid' => $player->pid + ], [ + 'X-Requested-With' => 'XMLHttpRequest' + ])->seeJson([ + 'errno' => 1, + 'msg' => trans('validation.required', ['attribute' => 'preference']) + ]); + + // value of `preference` is invalid + $this->post('/user/player/preference', [ + 'pid' => $player->pid, + 'preference' => 'steve' + ], [ + 'X-Requested-With' => 'XMLHttpRequest' + ])->seeJson([ + 'errno' => 1, + 'msg' => trans('validation.preference', ['attribute' => 'preference']) + ]); + + // Success + $this->expectsEvents(Events\PlayerProfileUpdated::class); + $this->post('/user/player/preference', [ + 'pid' => $player->pid, + 'preference' => 'slim' + ], [ + 'X-Requested-With' => 'XMLHttpRequest' + ])->seeJson([ + 'errno' => 0, + 'msg' => trans( + 'user.player.preference.success', + ['name' => $player->player_name, 'preference' => 'slim'] + ) + ]); + $this->assertEquals('slim', Player::find($player->pid)->preference); + } +}