*/ public static function supportedVariableProvider(): array { return [ 'url' => [ 'template' => '$url', 'expected' => 'https://kanbangit.test/projects/core/tickets/42', ], 'ticket_key' => [ 'template' => '$ticket_key', 'expected' => 'CORE-42', ], 'ticket_title' => [ 'template' => '$ticket_title', 'expected' => 'Fix webhook delivery', ], 'project_name' => [ 'template' => '$project_name', 'expected' => 'Core Platform', ], 'status_from' => [ 'template' => '$status_from', 'expected' => 'Backlog', ], 'status_to' => [ 'template' => '$status_to', 'expected' => 'Doing', ], 'actor_name' => [ 'template' => '$actor_name', 'expected' => 'Erica Example', ], ]; } /** * Ensure each supported Discord template variable renders from the event payload. */ #[DataProvider('supportedVariableProvider')] public function test_it_replaces_supported_template_variables(string $template, string $expected): void { $renderedMessage = app(RenderDiscordMessageTemplate::class)->handle($template, $this->event()); $this->assertSame($expected, $renderedMessage); } /** * Ensure unknown placeholder-like text stays untouched while supported variables still render. */ public function test_unknown_template_text_remains_literal(): void { $renderedMessage = app(RenderDiscordMessageTemplate::class)->handle( '[$ticket_key] $unknown moved to $status_to', $this->event(), ); $this->assertSame('[CORE-42] $unknown moved to Doing', $renderedMessage); } private function event(): TicketStatusChanged { return new TicketStatusChanged(new TicketStatusChangedPayload( projectId: 10, projectKey: 'CORE', projectName: 'Core Platform', ticketId: 42, ticketKey: 'CORE-42', ticketTitle: 'Fix webhook delivery', ticketUrl: 'https://kanbangit.test/projects/core/tickets/42', actorId: 7, actorName: 'Erica Example', fromStatusId: 1, fromStatusLabel: 'Backlog', toStatusId: 2, toStatusLabel: 'Doing', occurredAt: CarbonImmutable::parse('2026-04-24T09:15:30+00:00'), )); } }