Model ticket link counterparts explicitly
linter / quality (pull_request) Successful in 3m5s
tests / ci (8.4) (pull_request) Failing after 1m41s

This commit is contained in:
2026-05-23 10:29:22 +00:00
parent d60c33fa7c
commit 486994e441
22 changed files with 312 additions and 66 deletions
@@ -55,6 +55,7 @@ class ProjectTicketControllerTest extends TestCase
]);
$ticketLinkType = TicketLinkType::factory()->for($project)->create([
'label' => 'Relates to',
'counterpart_label' => 'Relates to',
'position' => 1,
]);
@@ -137,6 +138,7 @@ class ProjectTicketControllerTest extends TestCase
->where('ticket.worklog_entries.0.actor.name', $viewer->name)
->where('linkedTickets.0.linked_ticket.ticket_key', 'CORE-2')
->where('linkedTickets.0.ticket_link_type.label', 'Relates to')
->where('linkedTickets.0.ticket_link_type.counterpart_label', 'Relates to')
->where('repositoryBranches', [])
->where('repositoryPullRequests', [])
->where('canEditTicket', false)
@@ -144,6 +146,62 @@ class ProjectTicketControllerTest extends TestCase
);
}
/**
* Ensure linked tickets show the counterpart label from the other ticket perspective.
*/
public function test_ticket_detail_uses_counterpart_link_label_for_target_ticket(): void
{
$viewer = User::factory()->create();
$project = Project::factory()->create([
'key' => 'CORE',
]);
app(InitializeProjectTicketMetadata::class)->handle($project);
$priority = $project->ticketPriorities()->firstOrFail();
$taskType = $project->ticketTypes()
->where('is_parent', false)
->orderBy('position')
->firstOrFail();
$sourceTicket = Ticket::factory()->create([
'project_id' => $project->id,
'sequence_number' => 1,
'ticket_key' => 'CORE-1',
'ticket_priority_id' => $priority->id,
'ticket_type_id' => $taskType->id,
'title' => 'Source ticket',
]);
$targetTicket = Ticket::factory()->create([
'project_id' => $project->id,
'sequence_number' => 2,
'ticket_key' => 'CORE-2',
'ticket_priority_id' => $priority->id,
'ticket_type_id' => $taskType->id,
'title' => 'Target ticket',
]);
$ticketLinkType = TicketLinkType::factory()->for($project)->create([
'label' => 'Blocks',
'counterpart_label' => 'Blocked by',
'position' => 1,
]);
TicketLink::factory()->create([
'source_ticket_id' => $sourceTicket->id,
'target_ticket_id' => $targetTicket->id,
'ticket_link_type_id' => $ticketLinkType->id,
]);
$this->syncProjectPermissions($project, $viewer, ['view']);
$this->actingAs($viewer)
->get(route('projects.tickets.show', [$project, $targetTicket]))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->where('linkedTickets.0.linked_ticket.ticket_key', 'CORE-1')
->where('linkedTickets.0.ticket_link_type.label', 'Blocked by')
->where('linkedTickets.0.ticket_link_type.counterpart_label', 'Blocked by'));
}
/**
* Ensure project admins can still inspect the author when project author visibility is disabled.
*/