diff --git a/resources/assets/src/views/skinlib/Show/addClosetItem.ts b/resources/assets/src/views/skinlib/Show/addClosetItem.ts index fd4eda9f..73412a56 100644 --- a/resources/assets/src/views/skinlib/Show/addClosetItem.ts +++ b/resources/assets/src/views/skinlib/Show/addClosetItem.ts @@ -25,7 +25,7 @@ export default async function addClosetItem( } const { code, message } = await fetch.post( - '/user/closet/add', + '/user/closet', { tid: texture.tid, name }, ) if (code === 0) { diff --git a/resources/assets/src/views/user/Closet/index.tsx b/resources/assets/src/views/user/Closet/index.tsx index 765cd4f2..bbfea392 100644 --- a/resources/assets/src/views/user/Closet/index.tsx +++ b/resources/assets/src/views/user/Closet/index.tsx @@ -105,8 +105,8 @@ const Closet: React.FC = () => { return } - const { code, message } = await fetch.post( - `/user/closet/rename/${item.tid}`, + const { code, message } = await fetch.put( + `/user/closet/${item.tid}`, { name }, ) if (code === 0) { diff --git a/resources/assets/src/views/user/Closet/removeClosetItem.ts b/resources/assets/src/views/user/Closet/removeClosetItem.ts index b72ea229..da36d5a4 100644 --- a/resources/assets/src/views/user/Closet/removeClosetItem.ts +++ b/resources/assets/src/views/user/Closet/removeClosetItem.ts @@ -12,8 +12,8 @@ export default async function removeClosetItem(tid: number): Promise { return false } - const { code, message } = await fetch.post( - `/user/closet/remove/${tid}`, + const { code, message } = await fetch.del( + `/user/closet/${tid}`, ) if (code === 0) { toast.success(message) diff --git a/resources/assets/tests/views/skinlib/Show.test.tsx b/resources/assets/tests/views/skinlib/Show.test.tsx index 1a178412..3aed7ff1 100644 --- a/resources/assets/tests/views/skinlib/Show.test.tsx +++ b/resources/assets/tests/views/skinlib/Show.test.tsx @@ -376,7 +376,7 @@ describe('add to closet', () => { }) fireEvent.click(getByText(t('general.confirm'))) await waitFor(() => - expect(fetch.post).toBeCalledWith('/user/closet/add', { + expect(fetch.post).toBeCalledWith('/user/closet', { tid: fixtureSkin.tid, name: 't', }), @@ -400,7 +400,7 @@ describe('add to closet', () => { }) fireEvent.click(getByText(t('general.confirm'))) await waitFor(() => - expect(fetch.post).toBeCalledWith('/user/closet/add', { + expect(fetch.post).toBeCalledWith('/user/closet', { tid: fixtureSkin.tid, name: 't', }), @@ -419,7 +419,7 @@ describe('remove from closet', () => { }) it('succeeded', async () => { - fetch.post.mockResolvedValue({ code: 0, message: 'ok' }) + fetch.del.mockResolvedValue({ code: 0, message: 'ok' }) const { getByText, getByRole, queryByText } = render() await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) @@ -427,9 +427,7 @@ describe('remove from closet', () => { fireEvent.click(getByText(t('skinlib.removeFromCloset'))) fireEvent.click(getByText(t('general.confirm'))) await waitFor(() => - expect(fetch.post).toBeCalledWith( - `/user/closet/remove/${fixtureSkin.tid}`, - ), + expect(fetch.del).toBeCalledWith(`/user/closet/${fixtureSkin.tid}`), ) expect(queryByText('ok')).toBeInTheDocument() expect(getByRole('status')).toHaveClass('alert-success') @@ -437,7 +435,7 @@ describe('remove from closet', () => { }) it('failed', async () => { - fetch.post.mockResolvedValue({ code: 1, message: 'failed' }) + fetch.del.mockResolvedValue({ code: 1, message: 'failed' }) const { getByText, getByRole, queryByText } = render() await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) @@ -445,9 +443,7 @@ describe('remove from closet', () => { fireEvent.click(getByText(t('skinlib.removeFromCloset'))) fireEvent.click(getByText(t('general.confirm'))) await waitFor(() => - expect(fetch.post).toBeCalledWith( - `/user/closet/remove/${fixtureSkin.tid}`, - ), + expect(fetch.del).toBeCalledWith(`/user/closet/${fixtureSkin.tid}`), ) expect(queryByText('failed')).toBeInTheDocument() expect(getByRole('alert')).toHaveClass('alert-danger') diff --git a/resources/assets/tests/views/skinlib/SkinLibrary.test.tsx b/resources/assets/tests/views/skinlib/SkinLibrary.test.tsx index 475b074f..07447fa1 100644 --- a/resources/assets/tests/views/skinlib/SkinLibrary.test.tsx +++ b/resources/assets/tests/views/skinlib/SkinLibrary.test.tsx @@ -391,26 +391,26 @@ describe('remove from closet', () => { }) it('succeeded', async () => { - fetch.post.mockResolvedValue({ code: 0, message: 'ok' }) + fetch.del.mockResolvedValue({ code: 0, message: 'ok' }) const { getByText, queryByText } = render() await waitFor(() => expect(fetch.get).toBeCalled()) fireEvent.click(getByText(fixtureItem.likes.toString())) fireEvent.click(getByText(t('general.confirm'))) - await waitFor(() => expect(fetch.post).toBeCalled()) + await waitFor(() => expect(fetch.del).toBeCalled()) expect(queryByText((fixtureItem.likes - 1).toString())).toBeInTheDocument() }) it('failed', async () => { - fetch.post.mockResolvedValue({ code: 1, message: 'failed' }) + fetch.del.mockResolvedValue({ code: 1, message: 'failed' }) const { getByText, queryByText } = render() await waitFor(() => expect(fetch.get).toBeCalled()) fireEvent.click(getByText(fixtureItem.likes.toString())) fireEvent.click(getByText(t('general.confirm'))) - await waitFor(() => expect(fetch.post).toBeCalled()) + await waitFor(() => expect(fetch.del).toBeCalled()) expect(queryByText(fixtureItem.likes.toString())).toBeInTheDocument() }) }) diff --git a/resources/assets/tests/views/user/Closet.test.tsx b/resources/assets/tests/views/user/Closet.test.tsx index 8b7b7a36..96036e6f 100644 --- a/resources/assets/tests/views/user/Closet.test.tsx +++ b/resources/assets/tests/views/user/Closet.test.tsx @@ -129,7 +129,7 @@ describe('rename item', () => { }) it('succeeded', async () => { - fetch.post.mockResolvedValue({ code: 0, message: 'success' }) + fetch.put.mockResolvedValue({ code: 0, message: 'success' }) const { getByText, getByDisplayValue, getByRole, queryByText } = render( , @@ -142,12 +142,9 @@ describe('rename item', () => { }) fireEvent.click(getByText(t('general.confirm'))) await waitFor(() => - expect(fetch.post).toBeCalledWith( - `/user/closet/rename/${fixtureSkin.tid}`, - { - name: 'my skin', - }, - ), + expect(fetch.put).toBeCalledWith(`/user/closet/${fixtureSkin.tid}`, { + name: 'my skin', + }), ) expect(queryByText('my skin')).toBeInTheDocument() expect(queryByText('success')).toBeInTheDocument() @@ -155,8 +152,6 @@ describe('rename item', () => { }) it('empty name', async () => { - fetch.post.mockResolvedValue({ code: 0, message: 'success' }) - const { getByText, getByDisplayValue, queryByText } = render() await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) @@ -165,14 +160,14 @@ describe('rename item', () => { target: { value: '' }, }) fireEvent.click(getByText(t('general.confirm'))) - await waitFor(() => expect(fetch.post).not.toBeCalled()) + await waitFor(() => expect(fetch.put).not.toBeCalled()) expect(queryByText(t('skinlib.emptyNewTextureName'))).toBeInTheDocument() fireEvent.click(getByText(t('general.cancel'))) }) it('failed', async () => { - fetch.post.mockResolvedValue({ code: 1, message: 'failed' }) + fetch.put.mockResolvedValue({ code: 1, message: 'failed' }) const { getByText, getByDisplayValue, getByRole, queryByText } = render( , @@ -185,30 +180,14 @@ describe('rename item', () => { }) fireEvent.click(getByText(t('general.confirm'))) await waitFor(() => - expect(fetch.post).toBeCalledWith( - `/user/closet/rename/${fixtureSkin.tid}`, - { - name: 'my skin', - }, - ), + expect(fetch.put).toBeCalledWith(`/user/closet/${fixtureSkin.tid}`, { + name: 'my skin', + }), ) expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument() expect(queryByText('failed')).toBeInTheDocument() expect(getByRole('alert')).toHaveClass('alert-danger') }) - - it('cancelled', async () => { - const { getByText, getByDisplayValue, queryByText } = render() - await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) - - fireEvent.click(getByText(t('user.renameItem'))) - fireEvent.input(getByDisplayValue(fixtureSkin.pivot.item_name), { - target: { value: 'my skin' }, - }) - fireEvent.click(getByText(t('general.cancel'))) - await waitFor(() => expect(fetch.post).not.toBeCalled()) - expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument() - }) }) describe('remove item', () => { @@ -217,7 +196,7 @@ describe('remove item', () => { }) it('succeeded', async () => { - fetch.post.mockResolvedValue({ code: 0, message: 'success' }) + fetch.del.mockResolvedValue({ code: 0, message: 'success' }) const { getByText, getByRole, queryByText } = render() await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) @@ -225,9 +204,7 @@ describe('remove item', () => { fireEvent.click(getByText(t('user.removeItem'))) fireEvent.click(getByText(t('general.confirm'))) await waitFor(() => - expect(fetch.post).toBeCalledWith( - `/user/closet/remove/${fixtureSkin.tid}`, - ), + expect(fetch.del).toBeCalledWith(`/user/closet/${fixtureSkin.tid}`), ) expect(queryByText(/skin library/i)).toBeInTheDocument() expect(queryByText('success')).toBeInTheDocument() @@ -235,7 +212,7 @@ describe('remove item', () => { }) it('failed', async () => { - fetch.post.mockResolvedValue({ code: 1, message: 'failed' }) + fetch.del.mockResolvedValue({ code: 1, message: 'failed' }) const { getByText, getByRole, queryByText } = render() await waitFor(() => expect(fetch.get).toBeCalledTimes(1)) @@ -243,9 +220,7 @@ describe('remove item', () => { fireEvent.click(getByText(t('user.removeItem'))) fireEvent.click(getByText(t('general.confirm'))) await waitFor(() => - expect(fetch.post).toBeCalledWith( - `/user/closet/remove/${fixtureSkin.tid}`, - ), + expect(fetch.del).toBeCalledWith(`/user/closet/${fixtureSkin.tid}`), ) expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument() expect(queryByText('failed')).toBeInTheDocument() @@ -258,7 +233,7 @@ describe('remove item', () => { fireEvent.click(getByText(t('user.removeItem'))) fireEvent.click(getByText(t('general.cancel'))) - await waitFor(() => expect(fetch.post).not.toBeCalled()) + await waitFor(() => expect(fetch.del).not.toBeCalled()) expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument() }) }) diff --git a/routes/web.php b/routes/web.php index 4d681f9e..f2ee72e9 100644 --- a/routes/web.php +++ b/routes/web.php @@ -84,9 +84,9 @@ Route::prefix('user') Route::get('', 'ClosetController@index')->name('page'); Route::get('list', 'ClosetController@getClosetData')->name('list'); Route::get('ids', 'ClosetController@allIds')->name('ids'); - Route::post('add', 'ClosetController@add')->name('add'); - Route::post('remove/{tid}', 'ClosetController@remove')->name('remove'); - Route::post('rename/{tid}', 'ClosetController@rename')->name('rename'); + Route::post('', 'ClosetController@add')->name('add'); + Route::put('{tid}', 'ClosetController@rename')->name('rename'); + Route::delete('{tid}', 'ClosetController@remove')->name('remove'); }); // OAuth2 Management diff --git a/tests/HttpTest/ControllersTest/ClosetControllerTest.php b/tests/HttpTest/ControllersTest/ClosetControllerTest.php index 5690cf87..a09f6797 100644 --- a/tests/HttpTest/ControllersTest/ClosetControllerTest.php +++ b/tests/HttpTest/ControllersTest/ClosetControllerTest.php @@ -88,17 +88,18 @@ class ClosetControllerTest extends TestCase option(['score_per_closet_item' => 10]); // missing `tid` field - $this->postJson('/user/closet/add')->assertJsonValidationErrors('tid'); + $this->postJson(route('user.closet.add')) + ->assertJsonValidationErrors('tid'); // `tid` is not a integer $this->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => 'string'] )->assertJsonValidationErrors('tid'); // missing `name` field $this->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => 0] )->assertJsonValidationErrors('name'); @@ -114,7 +115,7 @@ class ClosetControllerTest extends TestCase } ); $this->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => $texture->tid, 'name' => $name] )->assertJson(['code' => 1, 'message' => 'rejected']); $filter->assertApplied( @@ -142,7 +143,7 @@ class ClosetControllerTest extends TestCase $this->user->score = 0; $this->user->save(); $this->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => $texture->tid, 'name' => $name] )->assertJson([ 'code' => 1, @@ -153,7 +154,7 @@ class ClosetControllerTest extends TestCase $this->user->score = 100; $this->user->save(); $this->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => -1, 'name' => 'my'] )->assertJson([ 'code' => 1, @@ -167,7 +168,7 @@ class ClosetControllerTest extends TestCase 'uploader' => $uploader->uid + 1, ]); $this->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => $privateTexture->tid, 'name' => $name] )->assertJson([ 'code' => 1, @@ -180,7 +181,7 @@ class ClosetControllerTest extends TestCase ]); $this->actingAs(factory(User::class)->state('admin')->create()) ->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => $privateTexture->tid, 'name' => $name] )->assertJson([ 'code' => 0, @@ -191,7 +192,7 @@ class ClosetControllerTest extends TestCase Event::fake(); $this->actingAs($this->user) ->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => $texture->tid, 'name' => $name] )->assertJson([ 'code' => 0, @@ -224,7 +225,7 @@ class ClosetControllerTest extends TestCase // if the texture is duplicated, should be warned $this->postJson( - '/user/closet/add', + route('user.closet.add'), ['tid' => $texture->tid, 'name' => $name] )->assertJson([ 'code' => 1, @@ -239,7 +240,8 @@ class ClosetControllerTest extends TestCase $name = 'new'; // missing `name` field - $this->postJson('/user/closet/rename/0')->assertJsonValidationErrors('name'); + $this->putJson(route('user.closet.rename', ['tid' => 0])) + ->assertJsonValidationErrors('name'); // rejection $filter = Fakes\Filter::fake(); @@ -253,8 +255,10 @@ class ClosetControllerTest extends TestCase } ); $this->user->closet()->attach($texture->tid, ['item_name' => 'name']); - $this->postJson('/user/closet/rename/'.$texture->tid, ['name' => $name]) - ->assertJson(['code' => 1, 'message' => 'rejected']); + $this->putJson( + route('user.closet.rename', ['tid' => $texture->tid]), + ['name' => $name] + )->assertJson(['code' => 1, 'message' => 'rejected']); $filter->assertApplied( 'rename_closet_item_name', function ($itemName, $tid) use ($name, $texture) { @@ -278,20 +282,24 @@ class ClosetControllerTest extends TestCase // rename a not-existed texture Fakes\Filter::fake(); - $this->postJson('/user/closet/rename/-1', ['name' => $name]) - ->assertJson([ - 'code' => 1, - 'message' => trans('user.closet.remove.non-existent'), - ]); + $this->putJson( + route('user.closet.rename', ['tid' => -1]), + ['name' => $name] + )->assertJson([ + 'code' => 1, + 'message' => trans('user.closet.remove.non-existent'), + ]); // rename a closet item successfully Event::fake(); $this->user->closet()->attach($texture->tid, ['item_name' => $texture->name]); - $this->postJson('/user/closet/rename/'.$texture->tid, ['name' => $name]) - ->assertJson([ - 'code' => 0, - 'message' => trans('user.closet.rename.success', ['name' => $name]), - ]); + $this->putJson( + route('user.closet.rename', ['tid' => $texture->tid]), + ['name' => $name] + )->assertJson([ + 'code' => 0, + 'message' => trans('user.closet.rename.success', ['name' => $name]), + ]); $this->assertEquals(1, $this->user->closet()->where('item_name', $name)->count()); Event::assertDispatched( 'closet.renaming', @@ -321,7 +329,7 @@ class ClosetControllerTest extends TestCase $likes = $texture->likes; // rename a not-existed texture - $this->postJson('/user/closet/remove/-1') + $this->deleteJson(route('user.closet.remove', ['tid' => -1])) ->assertJson([ 'code' => 1, 'message' => trans('user.closet.remove.non-existent'), @@ -341,7 +349,7 @@ class ClosetControllerTest extends TestCase return new Rejection('rejected'); }); $this->user->closet()->attach($texture->tid, ['item_name' => 'name']); - $this->postJson('/user/closet/remove/'.$texture->tid) + $this->deleteJson(route('user.closet.remove', ['tid' => $texture->tid])) ->assertJson(['code' => 1, 'message' => 'rejected']); $this->user->closet()->detach($texture->tid); Fakes\Filter::fake(); @@ -351,7 +359,7 @@ class ClosetControllerTest extends TestCase option(['score_award_per_like' => 5]); $this->user->closet()->attach($texture->tid, ['item_name' => 'name']); $score = $this->user->score; - $this->postJson('/user/closet/remove/'.$texture->tid) + $this->deleteJson(route('user.closet.remove', ['tid' => $texture->tid])) ->assertJson([ 'code' => 0, 'message' => trans('user.closet.remove.success'), @@ -384,7 +392,8 @@ class ClosetControllerTest extends TestCase option(['return_score' => false]); $this->user->closet()->attach($texture->tid, ['item_name' => 'name']); $score = $this->user->score; - $this->postJson('/user/closet/remove/'.$texture->tid)->assertJson(['code' => 0]); + $this->deleteJson(route('user.closet.remove', ['tid' => $texture->tid])) + ->assertJson(['code' => 0]); $this->assertEquals($likes - 1, Texture::find($texture->tid)->likes); $this->assertEquals($score, $this->user->score); $this->assertEquals(0, $this->user->closet()->count());