From b5ba09d350ae213c0b72e5a7666e672afd9144e0 Mon Sep 17 00:00:00 2001 From: Koda Date: Wed, 20 May 2026 09:53:21 +0000 Subject: [PATCH] Fix acceptance criteria toggle ajax responses --- .../Controllers/ProjectTicketController.php | 10 +++- resources/js/pages/projects/Ticket.vue | 2 +- .../Projects/ProjectTicketControllerTest.php | 46 +++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/ProjectTicketController.php b/app/Http/Controllers/ProjectTicketController.php index 3dc1f78..42cfbb9 100644 --- a/app/Http/Controllers/ProjectTicketController.php +++ b/app/Http/Controllers/ProjectTicketController.php @@ -12,6 +12,7 @@ use App\Http\Requests\StoreProjectTicketRequest; use App\Http\Requests\UpdateProjectTicketRequest; use App\Models\Project; use App\Models\Ticket; +use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Arr; @@ -85,7 +86,7 @@ class ProjectTicketController extends Controller UpdateProjectTicketRequest $request, Project $project, Ticket $ticket, - ): RedirectResponse { + ): RedirectResponse|JsonResponse { $user = $request->user(); abort_unless( @@ -105,6 +106,13 @@ class ProjectTicketController extends Controller ? "{$ticket->ticket_key} was updated." : 'No ticket changes were detected.'; + if ($request->expectsJson()) { + return response()->json([ + 'message' => $statusMessage, + 'updated' => $wasUpdated, + ]); + } + return to_route('projects.tickets.show', [$project, $ticket]) ->with('status', $statusMessage); } diff --git a/resources/js/pages/projects/Ticket.vue b/resources/js/pages/projects/Ticket.vue index 35b7118..0cca9ef 100644 --- a/resources/js/pages/projects/Ticket.vue +++ b/resources/js/pages/projects/Ticket.vue @@ -414,7 +414,7 @@ const persistAcceptanceCriteriaToggle = async ( method: 'PATCH', credentials: 'same-origin', headers: { - Accept: 'text/html, application/xhtml+xml', + Accept: 'application/json', 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken ?? '', 'X-Requested-With': 'XMLHttpRequest', diff --git a/tests/Feature/Projects/ProjectTicketControllerTest.php b/tests/Feature/Projects/ProjectTicketControllerTest.php index e74504a..daaa2bb 100644 --- a/tests/Feature/Projects/ProjectTicketControllerTest.php +++ b/tests/Feature/Projects/ProjectTicketControllerTest.php @@ -661,6 +661,52 @@ class ProjectTicketControllerTest extends TestCase ]); } + public function test_ticket_update_returns_json_for_ajax_requests(): void + { + $editor = User::factory()->create(); + $project = Project::factory()->create([ + 'key' => 'CORE', + ]); + + app(InitializeProjectTicketMetadata::class)->handle($project); + + $priority = $project->ticketPriorities()->firstOrFail(); + $ticketType = $this->nonParentType($project); + $ticket = Ticket::factory()->create([ + 'project_id' => $project->id, + 'sequence_number' => 1, + 'ticket_key' => 'CORE-1', + 'ticket_priority_id' => $priority->id, + 'ticket_type_id' => $ticketType->id, + 'title' => 'Acceptance criteria toggle test', + ]); + + $this->syncProjectPermissions($project, $editor, ['write', 'view']); + + $this->actingAs($editor) + ->withHeaders([ + 'Accept' => 'application/json', + 'X-Requested-With' => 'XMLHttpRequest', + ]) + ->patch(route('projects.tickets.update', [$project, $ticket]), [ + 'acceptance_criteria' => [], + 'blocked_comment' => $ticket->blocked_comment, + 'description' => $ticket->description, + 'field_values' => [], + 'is_blocked' => $ticket->is_blocked, + 'parent_ticket_id' => $ticket->parent_ticket_id, + 'story_points' => $ticket->story_points, + 'ticket_priority_id' => $priority->id, + 'ticket_type_id' => $ticketType->id, + 'title' => $ticket->title, + ]) + ->assertOk() + ->assertJson([ + 'message' => 'No ticket changes were detected.', + 'updated' => false, + ]); + } + /** * Ensure non-parent tickets cannot be assigned as a parent target. */