diff --git a/src/Service/SlackService.php b/src/Service/SlackService.php index e9b8fbd..8603904 100644 --- a/src/Service/SlackService.php +++ b/src/Service/SlackService.php @@ -63,7 +63,7 @@ public function sendRepositoryDiscoveryMessage(DocumentationJar $jar): ResponseI . ":hammer_and_wrench: *Maintainers:* <{$deploymentsUrl}|Review pending deployments> | <{$gitUrl}|:git:>\n" . ":information_source: *Extension authors:* <{$webhookDocsUrl}|How does this work?>", 'fallback' => "Repository {$repoKey} is awaiting documentation approval at {$deploymentsUrl}", - 'footer' => sprintf("TYPO3 Intercept \u{00b7} <{%s}|(?)>", self::SOURCE_URL), + 'footer' => sprintf("TYPO3 Intercept \u{00b7} <%s|(?)>", self::SOURCE_URL), 'footer_icon' => self::AVATAR_URL, 'mrkdwn_in' => ['text'], ], diff --git a/tests/Functional/Service/SlackServiceTest.php b/tests/Functional/Service/SlackServiceTest.php index 20913c2..d7bc739 100644 --- a/tests/Functional/Service/SlackServiceTest.php +++ b/tests/Functional/Service/SlackServiceTest.php @@ -89,6 +89,15 @@ public function testSendRepositoryDiscoveryMessageContainsExpectedPayload(): voi self::assertStringContainsString('github.com/TYPO3GmbH/site-intercept', $attachment['footer']); self::assertStringContainsString('SlackService.php', $attachment['footer']); + // Every link target must be a bare URL, `<{https://…}|label>` is rendered verbatim by Slack + foreach (['text', 'footer'] as $field) { + preg_match_all('/<([^|>]*)\|[^>]*>/', $attachment[$field], $links); + self::assertNotEmpty($links[1], sprintf('No Slack link found in attachment field "%s"', $field)); + foreach ($links[1] as $target) { + self::assertMatchesRegularExpression('#^https?://\S+$#', $target); + } + } + // Must opt into mrkdwn rendering for the text field self::assertContains('text', $attachment['mrkdwn_in']);