tweak players API (breaking change)

This commit is contained in:
Pig Fang 2020-05-09 10:11:07 +08:00
parent 88d9901e77
commit 504d985c8d
8 changed files with 36 additions and 35 deletions

View File

@ -60,15 +60,9 @@ class PlayerController extends Controller
]); ]);
} }
public function listAll() public function list()
{ {
$players = Auth::user() return Auth::user()->players;
->players()
->select('pid', 'name', 'tid_skin', 'tid_cape')
->get()
->toArray();
return json('', 0, $players);
} }
public function add(Request $request, Dispatcher $dispatcher) public function add(Request $request, Dispatcher $dispatcher)

View File

@ -30,12 +30,10 @@ const Players: React.FC = () => {
useEffect(() => { useEffect(() => {
const getPlayers = async () => { const getPlayers = async () => {
setIsLoading(true) setIsLoading(true)
const { data } = await fetch.get<fetch.ResponseBody<Player[]>>( const players = await fetch.get<Player[]>('/user/player/list')
'/user/player/list', setPlayers(players)
) if (players.length === 1) {
setPlayers(data) selectPlayer(players[0])
if (data.length === 1) {
selectPlayer(data[0])
} }
setIsLoading(false) setIsLoading(false)
} }

View File

@ -34,7 +34,7 @@ afterEach(() => {
}) })
test('loading indicator', () => { test('loading indicator', () => {
fetch.get.mockResolvedValue({ data: [] }) fetch.get.mockResolvedValue([])
const { queryByTitle } = render(<Players />) const { queryByTitle } = render(<Players />)
expect(queryByTitle('Loading...')).toBeInTheDocument() expect(queryByTitle('Loading...')).toBeInTheDocument()
}) })
@ -48,7 +48,7 @@ test('search players', async () => {
tid_cape: 4, tid_cape: 4,
last_modified: new Date().toString(), last_modified: new Date().toString(),
} }
fetch.get.mockResolvedValue({ data: [fixture, fixture2] }) fetch.get.mockResolvedValue([fixture, fixture2])
const { getByPlaceholderText, queryByText } = render(<Players />) const { getByPlaceholderText, queryByText } = render(<Players />)
await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
@ -63,7 +63,10 @@ test('search players', async () => {
describe('select player automatically', () => { describe('select player automatically', () => {
it('only one player', async () => { it('only one player', async () => {
fetch.get.mockResolvedValue({ data: [fixture] }) fetch.get
.mockResolvedValueOnce([fixture])
.mockResolvedValueOnce({ data: { hash: '', type: 'steve' } })
.mockResolvedValueOnce({ data: { hash: '', type: 'cape' } })
render(<Players />) render(<Players />)
await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
@ -80,7 +83,7 @@ describe('select player automatically', () => {
tid_cape: 4, tid_cape: 4,
last_modified: new Date().toString(), last_modified: new Date().toString(),
} }
fetch.get.mockResolvedValue({ data: [fixture, fixture2] }) fetch.get.mockResolvedValue([fixture, fixture2])
render(<Players />) render(<Players />)
await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
@ -92,7 +95,7 @@ describe('select player automatically', () => {
describe('2d preview', () => { describe('2d preview', () => {
it('skin and cape', async () => { it('skin and cape', async () => {
fetch.get fetch.get
.mockResolvedValueOnce({ data: [fixture] }) .mockResolvedValueOnce([fixture])
.mockResolvedValueOnce({ data: { hash: 'a', type: 'steve' } }) .mockResolvedValueOnce({ data: { hash: 'a', type: 'steve' } })
.mockResolvedValueOnce({ data: { hash: 'b', type: 'cape' } }) .mockResolvedValueOnce({ data: { hash: 'b', type: 'cape' } })
@ -113,7 +116,7 @@ describe('2d preview', () => {
it('skin only', async () => { it('skin only', async () => {
fetch.get fetch.get
.mockResolvedValueOnce({ data: [{ ...fixture, tid_cape: 0 }] }) .mockResolvedValueOnce([{ ...fixture, tid_cape: 0 }])
.mockResolvedValueOnce({ data: { hash: 'a', type: 'steve' } }) .mockResolvedValueOnce({ data: { hash: 'a', type: 'steve' } })
const { getByAltText, queryByAltText, getByText, queryByText } = render( const { getByAltText, queryByAltText, getByText, queryByText } = render(
@ -133,7 +136,7 @@ describe('2d preview', () => {
it('cape only', async () => { it('cape only', async () => {
fetch.get fetch.get
.mockResolvedValueOnce({ data: [{ ...fixture, tid_skin: 0 }] }) .mockResolvedValueOnce([{ ...fixture, tid_skin: 0 }])
.mockResolvedValueOnce({ data: { hash: 'a', type: 'cape' } }) .mockResolvedValueOnce({ data: { hash: 'a', type: 'cape' } })
const { getByAltText, queryByAltText, getByText, queryByText } = render( const { getByAltText, queryByAltText, getByText, queryByText } = render(
@ -154,7 +157,7 @@ describe('2d preview', () => {
describe('create player', () => { describe('create player', () => {
beforeEach(() => { beforeEach(() => {
fetch.get.mockResolvedValue({ data: [] }) fetch.get.mockResolvedValue([])
}) })
it('alert if score is enough', async () => { it('alert if score is enough', async () => {
@ -259,7 +262,10 @@ describe('create player', () => {
describe('edit player name', () => { describe('edit player name', () => {
beforeEach(() => { beforeEach(() => {
fetch.get.mockResolvedValue({ data: [fixture] }) fetch.get
.mockResolvedValueOnce([fixture])
.mockResolvedValueOnce({ data: { hash: 'a', type: 'skin' } })
.mockResolvedValueOnce({ data: { hash: 'b', type: 'cape' } })
}) })
it('succeeded', async () => { it('succeeded', async () => {
@ -351,7 +357,10 @@ describe('edit player name', () => {
describe('reset texture', () => { describe('reset texture', () => {
beforeEach(() => { beforeEach(() => {
fetch.get.mockResolvedValue({ data: [fixture] }) fetch.get
.mockResolvedValueOnce([fixture])
.mockResolvedValueOnce({ data: { hash: 'a', type: 'skin' } })
.mockResolvedValueOnce({ data: { hash: 'b', type: 'cape' } })
}) })
it('clear skin and cape', async () => { it('clear skin and cape', async () => {
@ -471,7 +480,10 @@ describe('reset texture', () => {
describe('delete player', () => { describe('delete player', () => {
beforeEach(() => { beforeEach(() => {
fetch.get.mockResolvedValue({ data: [fixture] }) fetch.get
.mockResolvedValueOnce([fixture])
.mockResolvedValueOnce({ data: { hash: 'a', type: 'skin' } })
.mockResolvedValueOnce({ data: { hash: 'b', type: 'cape' } })
}) })
it('succeeded', async () => { it('succeeded', async () => {

View File

@ -29,7 +29,7 @@
- Added support of clicking on the uploader's nickname in skin library to view other uploads of that user. - Added support of clicking on the uploader's nickname in skin library to view other uploads of that user.
- Added `php artisan update` command for updating by CLI. - Added `php artisan update` command for updating by CLI.
## Tweaked ## Changed
- Tweaked policy of retrieve CA cert for GuzzleHttp. - Tweaked policy of retrieve CA cert for GuzzleHttp.
- Refactor account system. - Refactor account system.
@ -49,6 +49,7 @@
- Make "CSRF token mismatched" error friendly. - Make "CSRF token mismatched" error friendly.
- Reduced times of sending verification email. - Reduced times of sending verification email.
- Changed icon of "Walking/Running" button of skin viewer. - Changed icon of "Walking/Running" button of skin viewer.
- Changed API of retrieving all players.
## Fixed ## Fixed

View File

@ -49,6 +49,7 @@
- 使 "CSRF token mismatched" 的错误提示变得友好 - 使 "CSRF token mismatched" 的错误提示变得友好
- 减少发送验证邮件的次数 - 减少发送验证邮件的次数
- 更换皮肤预览器的「行走/奔跑」按钮图标 - 更换皮肤预览器的「行走/奔跑」按钮图标
- 更改获取角色的 API
## 修复 ## 修复

View File

@ -16,7 +16,7 @@ Route::prefix('user')->middleware('auth:jwt,oauth')->group(function () {
}); });
Route::prefix('players')->middleware('auth:jwt,oauth')->group(function () { Route::prefix('players')->middleware('auth:jwt,oauth')->group(function () {
Route::get('', 'PlayerController@listAll'); Route::get('', 'PlayerController@list');
Route::post('', 'PlayerController@add'); Route::post('', 'PlayerController@add');
Route::delete('{pid}', 'PlayerController@delete'); Route::delete('{pid}', 'PlayerController@delete');
Route::put('{pid}/name', 'PlayerController@rename'); Route::put('{pid}/name', 'PlayerController@rename');

View File

@ -70,7 +70,7 @@ Route::prefix('user')
->middleware('verified') ->middleware('verified')
->group(function () { ->group(function () {
Route::get('', 'PlayerController@index')->name('page'); Route::get('', 'PlayerController@index')->name('page');
Route::get('list', 'PlayerController@listAll')->name('list'); Route::get('list', 'PlayerController@list')->name('list');
Route::post('add', 'PlayerController@add')->name('add'); Route::post('add', 'PlayerController@add')->name('add');
Route::post('set/{pid}', 'PlayerController@setTexture')->name('set'); Route::post('set/{pid}', 'PlayerController@setTexture')->name('set');
Route::post('texture/clear/{pid}', 'PlayerController@clearTexture')->name('clear'); Route::post('texture/clear/{pid}', 'PlayerController@clearTexture')->name('clear');

View File

@ -29,18 +29,13 @@ class PlayerControllerTest extends TestCase
$filter->assertApplied('grid:user.player'); $filter->assertApplied('grid:user.player');
} }
public function testListAll() public function testList()
{ {
$user = factory(User::class)->create(); $user = factory(User::class)->create();
$player = factory(Player::class)->create(['uid' => $user->uid]); $player = factory(Player::class)->create(['uid' => $user->uid]);
$this->actingAs($user) $this->actingAs($user)
->get('/user/player/list') ->get('/user/player/list')
->assertJson(['data' => [ ->assertJson([$player->toArray()]);
[
'pid' => $player->pid,
'name' => $player->name,
],
]]);
} }
public function testAdd() public function testAdd()