From 3e1438f5e42558b648dcf8baa63d670c43f03506 Mon Sep 17 00:00:00 2001
From: Alex Garrett-Smith Edit Feedback
+
+
+
{{ idea.latest_status_update.message }}
diff --git a/resources/js/actions/App/Http/Controllers/IdeaController.ts b/resources/js/actions/App/Http/Controllers/IdeaController.ts index 1a87918..0a23785 100644 --- a/resources/js/actions/App/Http/Controllers/IdeaController.ts +++ b/resources/js/actions/App/Http/Controllers/IdeaController.ts @@ -1,7 +1,7 @@ import { queryParams, type RouteQueryOptions, type RouteDefinition, applyUrlDefaults } from './../../../../wayfinder' /** * @see \App\Http\Controllers\IdeaController::create -* @see app/Http/Controllers/IdeaController.php:26 +* @see app/Http/Controllers/IdeaController.php:27 * @route '/feedback/create' */ export const create = (options?: RouteQueryOptions): RouteDefinition<'get'> => ({ @@ -16,7 +16,7 @@ create.definition = { /** * @see \App\Http\Controllers\IdeaController::create -* @see app/Http/Controllers/IdeaController.php:26 +* @see app/Http/Controllers/IdeaController.php:27 * @route '/feedback/create' */ create.url = (options?: RouteQueryOptions) => { @@ -25,7 +25,7 @@ create.url = (options?: RouteQueryOptions) => { /** * @see \App\Http\Controllers\IdeaController::create -* @see app/Http/Controllers/IdeaController.php:26 +* @see app/Http/Controllers/IdeaController.php:27 * @route '/feedback/create' */ create.get = (options?: RouteQueryOptions): RouteDefinition<'get'> => ({ @@ -35,7 +35,7 @@ create.get = (options?: RouteQueryOptions): RouteDefinition<'get'> => ({ /** * @see \App\Http\Controllers\IdeaController::create -* @see app/Http/Controllers/IdeaController.php:26 +* @see app/Http/Controllers/IdeaController.php:27 * @route '/feedback/create' */ create.head = (options?: RouteQueryOptions): RouteDefinition<'head'> => ({ @@ -45,7 +45,7 @@ create.head = (options?: RouteQueryOptions): RouteDefinition<'head'> => ({ /** * @see \App\Http\Controllers\IdeaController::store -* @see app/Http/Controllers/IdeaController.php:31 +* @see app/Http/Controllers/IdeaController.php:32 * @route '/feedback' */ export const store = (options?: RouteQueryOptions): RouteDefinition<'post'> => ({ @@ -60,7 +60,7 @@ store.definition = { /** * @see \App\Http\Controllers\IdeaController::store -* @see app/Http/Controllers/IdeaController.php:31 +* @see app/Http/Controllers/IdeaController.php:32 * @route '/feedback' */ store.url = (options?: RouteQueryOptions) => { @@ -69,7 +69,7 @@ store.url = (options?: RouteQueryOptions) => { /** * @see \App\Http\Controllers\IdeaController::store -* @see app/Http/Controllers/IdeaController.php:31 +* @see app/Http/Controllers/IdeaController.php:32 * @route '/feedback' */ store.post = (options?: RouteQueryOptions): RouteDefinition<'post'> => ({ @@ -77,9 +77,193 @@ store.post = (options?: RouteQueryOptions): RouteDefinition<'post'> => ({ method: 'post', }) +/** +* @see \App\Http\Controllers\IdeaController::edit +* @see app/Http/Controllers/IdeaController.php:39 +* @route '/feedback/{idea}/edit' +*/ +export const edit = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'get'> => ({ + url: edit.url(args, options), + method: 'get', +}) + +edit.definition = { + methods: ["get","head"], + url: '/feedback/{idea}/edit', +} satisfies RouteDefinition<["get","head"]> + +/** +* @see \App\Http\Controllers\IdeaController::edit +* @see app/Http/Controllers/IdeaController.php:39 +* @route '/feedback/{idea}/edit' +*/ +edit.url = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions) => { + if (typeof args === 'string' || typeof args === 'number') { + args = { idea: args } + } + + if (typeof args === 'object' && !Array.isArray(args) && 'id' in args) { + args = { idea: args.id } + } + + if (Array.isArray(args)) { + args = { + idea: args[0], + } + } + + args = applyUrlDefaults(args) + + const parsedArgs = { + idea: typeof args.idea === 'object' + ? args.idea.id + : args.idea, + } + + return edit.definition.url + .replace('{idea}', parsedArgs.idea.toString()) + .replace(/\/+$/, '') + queryParams(options) +} + +/** +* @see \App\Http\Controllers\IdeaController::edit +* @see app/Http/Controllers/IdeaController.php:39 +* @route '/feedback/{idea}/edit' +*/ +edit.get = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'get'> => ({ + url: edit.url(args, options), + method: 'get', +}) + +/** +* @see \App\Http\Controllers\IdeaController::edit +* @see app/Http/Controllers/IdeaController.php:39 +* @route '/feedback/{idea}/edit' +*/ +edit.head = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'head'> => ({ + url: edit.url(args, options), + method: 'head', +}) + +/** +* @see \App\Http\Controllers\IdeaController::update +* @see app/Http/Controllers/IdeaController.php:48 +* @route '/feedback/{idea}' +*/ +export const update = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'put'> => ({ + url: update.url(args, options), + method: 'put', +}) + +update.definition = { + methods: ["put"], + url: '/feedback/{idea}', +} satisfies RouteDefinition<["put"]> + +/** +* @see \App\Http\Controllers\IdeaController::update +* @see app/Http/Controllers/IdeaController.php:48 +* @route '/feedback/{idea}' +*/ +update.url = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions) => { + if (typeof args === 'string' || typeof args === 'number') { + args = { idea: args } + } + + if (typeof args === 'object' && !Array.isArray(args) && 'id' in args) { + args = { idea: args.id } + } + + if (Array.isArray(args)) { + args = { + idea: args[0], + } + } + + args = applyUrlDefaults(args) + + const parsedArgs = { + idea: typeof args.idea === 'object' + ? args.idea.id + : args.idea, + } + + return update.definition.url + .replace('{idea}', parsedArgs.idea.toString()) + .replace(/\/+$/, '') + queryParams(options) +} + +/** +* @see \App\Http\Controllers\IdeaController::update +* @see app/Http/Controllers/IdeaController.php:48 +* @route '/feedback/{idea}' +*/ +update.put = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'put'> => ({ + url: update.url(args, options), + method: 'put', +}) + +/** +* @see \App\Http\Controllers\IdeaController::destroy +* @see app/Http/Controllers/IdeaController.php:55 +* @route '/feedback/{idea}' +*/ +export const destroy = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'delete'> => ({ + url: destroy.url(args, options), + method: 'delete', +}) + +destroy.definition = { + methods: ["delete"], + url: '/feedback/{idea}', +} satisfies RouteDefinition<["delete"]> + +/** +* @see \App\Http\Controllers\IdeaController::destroy +* @see app/Http/Controllers/IdeaController.php:55 +* @route '/feedback/{idea}' +*/ +destroy.url = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions) => { + if (typeof args === 'string' || typeof args === 'number') { + args = { idea: args } + } + + if (typeof args === 'object' && !Array.isArray(args) && 'id' in args) { + args = { idea: args.id } + } + + if (Array.isArray(args)) { + args = { + idea: args[0], + } + } + + args = applyUrlDefaults(args) + + const parsedArgs = { + idea: typeof args.idea === 'object' + ? args.idea.id + : args.idea, + } + + return destroy.definition.url + .replace('{idea}', parsedArgs.idea.toString()) + .replace(/\/+$/, '') + queryParams(options) +} + +/** +* @see \App\Http\Controllers\IdeaController::destroy +* @see app/Http/Controllers/IdeaController.php:55 +* @route '/feedback/{idea}' +*/ +destroy.delete = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'delete'> => ({ + url: destroy.url(args, options), + method: 'delete', +}) + /** * @see \App\Http\Controllers\IdeaController::show -* @see app/Http/Controllers/IdeaController.php:14 +* @see app/Http/Controllers/IdeaController.php:15 * @route '/feedback/{idea}' */ export const show = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'get'> => ({ @@ -94,7 +278,7 @@ show.definition = { /** * @see \App\Http\Controllers\IdeaController::show -* @see app/Http/Controllers/IdeaController.php:14 +* @see app/Http/Controllers/IdeaController.php:15 * @route '/feedback/{idea}' */ show.url = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions) => { @@ -127,7 +311,7 @@ show.url = (args: { idea: number | { id: number } } | [idea: number | { id: numb /** * @see \App\Http\Controllers\IdeaController::show -* @see app/Http/Controllers/IdeaController.php:14 +* @see app/Http/Controllers/IdeaController.php:15 * @route '/feedback/{idea}' */ show.get = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'get'> => ({ @@ -137,7 +321,7 @@ show.get = (args: { idea: number | { id: number } } | [idea: number | { id: numb /** * @see \App\Http\Controllers\IdeaController::show -* @see app/Http/Controllers/IdeaController.php:14 +* @see app/Http/Controllers/IdeaController.php:15 * @route '/feedback/{idea}' */ show.head = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'head'> => ({ @@ -145,6 +329,6 @@ show.head = (args: { idea: number | { id: number } } | [idea: number | { id: num method: 'head', }) -const IdeaController = { create, store, show } +const IdeaController = { create, store, edit, update, destroy, show } export default IdeaController \ No newline at end of file diff --git a/resources/js/routes/feedback/index.ts b/resources/js/routes/feedback/index.ts index 166d7cc..faa3c32 100644 --- a/resources/js/routes/feedback/index.ts +++ b/resources/js/routes/feedback/index.ts @@ -2,7 +2,7 @@ import { queryParams, type RouteQueryOptions, type RouteDefinition, applyUrlDefa import comments from './comments' /** * @see \App\Http\Controllers\IdeaController::create -* @see app/Http/Controllers/IdeaController.php:26 +* @see app/Http/Controllers/IdeaController.php:27 * @route '/feedback/create' */ export const create = (options?: RouteQueryOptions): RouteDefinition<'get'> => ({ @@ -17,7 +17,7 @@ create.definition = { /** * @see \App\Http\Controllers\IdeaController::create -* @see app/Http/Controllers/IdeaController.php:26 +* @see app/Http/Controllers/IdeaController.php:27 * @route '/feedback/create' */ create.url = (options?: RouteQueryOptions) => { @@ -26,7 +26,7 @@ create.url = (options?: RouteQueryOptions) => { /** * @see \App\Http\Controllers\IdeaController::create -* @see app/Http/Controllers/IdeaController.php:26 +* @see app/Http/Controllers/IdeaController.php:27 * @route '/feedback/create' */ create.get = (options?: RouteQueryOptions): RouteDefinition<'get'> => ({ @@ -36,7 +36,7 @@ create.get = (options?: RouteQueryOptions): RouteDefinition<'get'> => ({ /** * @see \App\Http\Controllers\IdeaController::create -* @see app/Http/Controllers/IdeaController.php:26 +* @see app/Http/Controllers/IdeaController.php:27 * @route '/feedback/create' */ create.head = (options?: RouteQueryOptions): RouteDefinition<'head'> => ({ @@ -46,7 +46,7 @@ create.head = (options?: RouteQueryOptions): RouteDefinition<'head'> => ({ /** * @see \App\Http\Controllers\IdeaController::store -* @see app/Http/Controllers/IdeaController.php:31 +* @see app/Http/Controllers/IdeaController.php:32 * @route '/feedback' */ export const store = (options?: RouteQueryOptions): RouteDefinition<'post'> => ({ @@ -61,7 +61,7 @@ store.definition = { /** * @see \App\Http\Controllers\IdeaController::store -* @see app/Http/Controllers/IdeaController.php:31 +* @see app/Http/Controllers/IdeaController.php:32 * @route '/feedback' */ store.url = (options?: RouteQueryOptions) => { @@ -70,7 +70,7 @@ store.url = (options?: RouteQueryOptions) => { /** * @see \App\Http\Controllers\IdeaController::store -* @see app/Http/Controllers/IdeaController.php:31 +* @see app/Http/Controllers/IdeaController.php:32 * @route '/feedback' */ store.post = (options?: RouteQueryOptions): RouteDefinition<'post'> => ({ @@ -78,6 +78,190 @@ store.post = (options?: RouteQueryOptions): RouteDefinition<'post'> => ({ method: 'post', }) +/** +* @see \App\Http\Controllers\IdeaController::edit +* @see app/Http/Controllers/IdeaController.php:39 +* @route '/feedback/{idea}/edit' +*/ +export const edit = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'get'> => ({ + url: edit.url(args, options), + method: 'get', +}) + +edit.definition = { + methods: ["get","head"], + url: '/feedback/{idea}/edit', +} satisfies RouteDefinition<["get","head"]> + +/** +* @see \App\Http\Controllers\IdeaController::edit +* @see app/Http/Controllers/IdeaController.php:39 +* @route '/feedback/{idea}/edit' +*/ +edit.url = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions) => { + if (typeof args === 'string' || typeof args === 'number') { + args = { idea: args } + } + + if (typeof args === 'object' && !Array.isArray(args) && 'id' in args) { + args = { idea: args.id } + } + + if (Array.isArray(args)) { + args = { + idea: args[0], + } + } + + args = applyUrlDefaults(args) + + const parsedArgs = { + idea: typeof args.idea === 'object' + ? args.idea.id + : args.idea, + } + + return edit.definition.url + .replace('{idea}', parsedArgs.idea.toString()) + .replace(/\/+$/, '') + queryParams(options) +} + +/** +* @see \App\Http\Controllers\IdeaController::edit +* @see app/Http/Controllers/IdeaController.php:39 +* @route '/feedback/{idea}/edit' +*/ +edit.get = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'get'> => ({ + url: edit.url(args, options), + method: 'get', +}) + +/** +* @see \App\Http\Controllers\IdeaController::edit +* @see app/Http/Controllers/IdeaController.php:39 +* @route '/feedback/{idea}/edit' +*/ +edit.head = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'head'> => ({ + url: edit.url(args, options), + method: 'head', +}) + +/** +* @see \App\Http\Controllers\IdeaController::update +* @see app/Http/Controllers/IdeaController.php:48 +* @route '/feedback/{idea}' +*/ +export const update = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'put'> => ({ + url: update.url(args, options), + method: 'put', +}) + +update.definition = { + methods: ["put"], + url: '/feedback/{idea}', +} satisfies RouteDefinition<["put"]> + +/** +* @see \App\Http\Controllers\IdeaController::update +* @see app/Http/Controllers/IdeaController.php:48 +* @route '/feedback/{idea}' +*/ +update.url = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions) => { + if (typeof args === 'string' || typeof args === 'number') { + args = { idea: args } + } + + if (typeof args === 'object' && !Array.isArray(args) && 'id' in args) { + args = { idea: args.id } + } + + if (Array.isArray(args)) { + args = { + idea: args[0], + } + } + + args = applyUrlDefaults(args) + + const parsedArgs = { + idea: typeof args.idea === 'object' + ? args.idea.id + : args.idea, + } + + return update.definition.url + .replace('{idea}', parsedArgs.idea.toString()) + .replace(/\/+$/, '') + queryParams(options) +} + +/** +* @see \App\Http\Controllers\IdeaController::update +* @see app/Http/Controllers/IdeaController.php:48 +* @route '/feedback/{idea}' +*/ +update.put = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'put'> => ({ + url: update.url(args, options), + method: 'put', +}) + +/** +* @see \App\Http\Controllers\IdeaController::destroy +* @see app/Http/Controllers/IdeaController.php:55 +* @route '/feedback/{idea}' +*/ +export const destroy = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'delete'> => ({ + url: destroy.url(args, options), + method: 'delete', +}) + +destroy.definition = { + methods: ["delete"], + url: '/feedback/{idea}', +} satisfies RouteDefinition<["delete"]> + +/** +* @see \App\Http\Controllers\IdeaController::destroy +* @see app/Http/Controllers/IdeaController.php:55 +* @route '/feedback/{idea}' +*/ +destroy.url = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions) => { + if (typeof args === 'string' || typeof args === 'number') { + args = { idea: args } + } + + if (typeof args === 'object' && !Array.isArray(args) && 'id' in args) { + args = { idea: args.id } + } + + if (Array.isArray(args)) { + args = { + idea: args[0], + } + } + + args = applyUrlDefaults(args) + + const parsedArgs = { + idea: typeof args.idea === 'object' + ? args.idea.id + : args.idea, + } + + return destroy.definition.url + .replace('{idea}', parsedArgs.idea.toString()) + .replace(/\/+$/, '') + queryParams(options) +} + +/** +* @see \App\Http\Controllers\IdeaController::destroy +* @see app/Http/Controllers/IdeaController.php:55 +* @route '/feedback/{idea}' +*/ +destroy.delete = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'delete'> => ({ + url: destroy.url(args, options), + method: 'delete', +}) + /** * @see \App\Http\Controllers\VoteController::__invoke * @see app/Http/Controllers/VoteController.php:11 @@ -196,7 +380,7 @@ react.post = (args: { idea: number | { id: number } } | [idea: number | { id: nu /** * @see \App\Http\Controllers\IdeaController::show -* @see app/Http/Controllers/IdeaController.php:14 +* @see app/Http/Controllers/IdeaController.php:15 * @route '/feedback/{idea}' */ export const show = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'get'> => ({ @@ -211,7 +395,7 @@ show.definition = { /** * @see \App\Http\Controllers\IdeaController::show -* @see app/Http/Controllers/IdeaController.php:14 +* @see app/Http/Controllers/IdeaController.php:15 * @route '/feedback/{idea}' */ show.url = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions) => { @@ -244,7 +428,7 @@ show.url = (args: { idea: number | { id: number } } | [idea: number | { id: numb /** * @see \App\Http\Controllers\IdeaController::show -* @see app/Http/Controllers/IdeaController.php:14 +* @see app/Http/Controllers/IdeaController.php:15 * @route '/feedback/{idea}' */ show.get = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'get'> => ({ @@ -254,7 +438,7 @@ show.get = (args: { idea: number | { id: number } } | [idea: number | { id: numb /** * @see \App\Http\Controllers\IdeaController::show -* @see app/Http/Controllers/IdeaController.php:14 +* @see app/Http/Controllers/IdeaController.php:15 * @route '/feedback/{idea}' */ show.head = (args: { idea: number | { id: number } } | [idea: number | { id: number } ] | number | { id: number }, options?: RouteQueryOptions): RouteDefinition<'head'> => ({ @@ -330,6 +514,9 @@ unsubscribe.head = (args: { idea: number | { id: number }, user: number | { id: const feedback = { create: Object.assign(create, create), store: Object.assign(store, store), + edit: Object.assign(edit, edit), + update: Object.assign(update, update), + destroy: Object.assign(destroy, destroy), vote: Object.assign(vote, vote), react: Object.assign(react, react), comments: Object.assign(comments, comments), diff --git a/routes/web.php b/routes/web.php index 522d216..7bb0573 100644 --- a/routes/web.php +++ b/routes/web.php @@ -29,6 +29,10 @@ Route::get('/feedback/create', [IdeaController::class, 'create'])->name('feedback.create'); Route::post('/feedback', [IdeaController::class, 'store'])->name('feedback.store'); + Route::get('/feedback/{idea}/edit', [IdeaController::class, 'edit'])->name('feedback.edit'); + Route::put('/feedback/{idea}', [IdeaController::class, 'update'])->name('feedback.update'); + Route::delete('/feedback/{idea}', [IdeaController::class, 'destroy'])->name('feedback.destroy'); + Route::post('/feedback/{idea}/vote', VoteController::class)->name('feedback.vote'); Route::post('/feedback/{idea}/reactions', ReactionController::class)->name('feedback.react'); Route::post('/feedback/{idea}/comments', [CommentController::class, 'store'])->name('feedback.comments.store'); diff --git a/tests/Feature/Ideas/DeleteIdeaTest.php b/tests/Feature/Ideas/DeleteIdeaTest.php new file mode 100644 index 0000000..c5f3e02 --- /dev/null +++ b/tests/Feature/Ideas/DeleteIdeaTest.php @@ -0,0 +1,36 @@ +create(); + + $this->delete(route('feedback.destroy', $idea)) + ->assertRedirect(route('login')); + + $this->assertDatabaseHas('ideas', ['id' => $idea->id]); +}); + +it('forbids a non-author from deleting', function () { + $idea = Idea::factory()->create(); + + $this->actingAs(User::factory()->create()) + ->delete(route('feedback.destroy', $idea)) + ->assertForbidden(); + + $this->assertDatabaseHas('ideas', ['id' => $idea->id]); +}); + +it('deletes the idea for the author', function () { + $idea = Idea::factory()->create(); + + $this->actingAs($idea->user) + ->delete(route('feedback.destroy', $idea)) + ->assertRedirect(route('dashboard')) + ->assertSessionHas('status'); + + $this->assertDatabaseMissing('ideas', ['id' => $idea->id]); +}); diff --git a/tests/Feature/Ideas/UpdateIdeaTest.php b/tests/Feature/Ideas/UpdateIdeaTest.php new file mode 100644 index 0000000..245312f --- /dev/null +++ b/tests/Feature/Ideas/UpdateIdeaTest.php @@ -0,0 +1,108 @@ + [ + 'title' => 'Updated title', + 'description' => 'Updated description for the feedback.', +]; + +// --------------------------------------------------------------------------- +// Auth guard +// --------------------------------------------------------------------------- + +it('redirects guests to login', function () use ($validPayload) { + $idea = Idea::factory()->create(); + + $this->put(route('feedback.update', $idea), $validPayload()) + ->assertRedirect(route('login')); +}); + +it('shows the edit form to the author', function () { + $idea = Idea::factory()->create(); + + $this->actingAs($idea->user) + ->get(route('feedback.edit', $idea)) + ->assertOk() + ->assertInertia(fn ($page) => $page->component('Ideas/Edit')); +}); + +// --------------------------------------------------------------------------- +// Authorization +// --------------------------------------------------------------------------- + +it('forbids a non-author from viewing the edit form', function () { + $idea = Idea::factory()->create(); + + $this->actingAs(User::factory()->create()) + ->get(route('feedback.edit', $idea)) + ->assertForbidden(); +}); + +it('forbids a non-author from updating', function () use ($validPayload) { + $idea = Idea::factory()->create(['title' => 'Original title']); + + $this->actingAs(User::factory()->create()) + ->put(route('feedback.update', $idea), $validPayload()) + ->assertForbidden(); + + $this->assertDatabaseHas('ideas', ['id' => $idea->id, 'title' => 'Original title']); +}); + +// --------------------------------------------------------------------------- +// Successful update +// --------------------------------------------------------------------------- + +it('updates the idea for the author', function () use ($validPayload) { + $idea = Idea::factory()->create(); + + $this->actingAs($idea->user) + ->put(route('feedback.update', $idea), $validPayload()) + ->assertRedirect(route('feedback.show', $idea)) + ->assertSessionHas('status'); + + $this->assertDatabaseHas('ideas', [ + 'id' => $idea->id, + 'title' => 'Updated title', + 'description' => 'Updated description for the feedback.', + ]); +}); + +// --------------------------------------------------------------------------- +// Validation +// --------------------------------------------------------------------------- + +it('requires a title', function () use ($validPayload) { + $idea = Idea::factory()->create(); + + $this->actingAs($idea->user) + ->put(route('feedback.update', $idea), array_merge($validPayload(), ['title' => ''])) + ->assertSessionHasErrors('title'); +}); + +it('requires a description', function () use ($validPayload) { + $idea = Idea::factory()->create(); + + $this->actingAs($idea->user) + ->put(route('feedback.update', $idea), array_merge($validPayload(), ['description' => ''])) + ->assertSessionHasErrors('description'); +}); + +it('rejects a title longer than 255 characters', function () use ($validPayload) { + $idea = Idea::factory()->create(); + + $this->actingAs($idea->user) + ->put(route('feedback.update', $idea), array_merge($validPayload(), ['title' => str_repeat('a', 256)])) + ->assertSessionHasErrors('title'); +}); + +it('rejects a description longer than 5000 characters', function () use ($validPayload) { + $idea = Idea::factory()->create(); + + $this->actingAs($idea->user) + ->put(route('feedback.update', $idea), array_merge($validPayload(), ['description' => str_repeat('a', 5001)])) + ->assertSessionHasErrors('description'); +});