Add endpoint and functionality to test Slack internal department goal progress webhook

This commit is contained in:
Jeppe Bundgaard
2026-06-29 11:32:47 +02:00
parent 42f8ae0c47
commit 3ea92be722
6 changed files with 177 additions and 1 deletions
+17
View File
@@ -11712,6 +11712,23 @@ paths:
schema: schema:
$ref: '#/components/schemas/SlackInternalDepartmentGoalProgressConfigResponse' $ref: '#/components/schemas/SlackInternalDepartmentGoalProgressConfigResponse'
/slack/config/internal-department-goal-progress/test:
post:
tags: [Config]
summary: Test Slack internal department goal progress webhook
operationId: testSlackInternalDepartmentGoalProgressWebhook
responses:
'200':
description: Slack internal department goal progress webhook test completed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/SlackConfigTestResponse'
'400':
description: Slack internal department goal progress webhook URL is not configured
'502':
description: Slack internal department goal progress webhook test failed
/backups/config: /backups/config:
get: get:
tags: [Config] tags: [Config]
+42
View File
@@ -196,6 +196,42 @@ class slack implements notification_i
]; ];
} }
/**
* Send a sanitized internal department goal progress test notification to the saved Slack webhook.
*
* @return array{configured:bool,sent:bool,message:string}
*/
public function test_internal_department_goal_progress_webhook(): array
{
$webhook = $this->get_internal_department_goal_progress_webhook_url();
if ($webhook === '') {
return [
'configured' => false,
'sent' => false,
'message' => 'Slack internal department goal progress webhook URL is not configured.',
];
}
$result = $this->send_webhook_message(
$this->format_internal_department_goal_progress_test(),
$webhook
);
$sent = $this->is_webhook_send_successful($result);
self::add_log($sent
? 'Slack internal department goal progress test webhook sent successfully.'
: 'Slack internal department goal progress test webhook failed.'
);
return [
'configured' => true,
'sent' => $sent,
'message' => $sent
? 'Slack test message sent successfully.'
: 'Slack test message failed.',
];
}
protected function get_customer_registration_webhook_url(): string protected function get_customer_registration_webhook_url(): string
{ {
return trim((string)$this->getConfig()->customer_registration_webhook_url->getVariableValue()); return trim((string)$this->getConfig()->customer_registration_webhook_url->getVariableValue());
@@ -287,4 +323,10 @@ class slack implements notification_i
return "*Truck Wash Slack test*\n" return "*Truck Wash Slack test*\n"
. "Customer registration notifications are configured correctly."; . "Customer registration notifications are configured correctly.";
} }
public function format_internal_department_goal_progress_test(): string
{
return "*Truck Wash Slack test*\n"
. "Internal department goal progress notifications are configured correctly.";
}
} }
+17
View File
@@ -11712,6 +11712,23 @@ paths:
schema: schema:
$ref: '#/components/schemas/SlackInternalDepartmentGoalProgressConfigResponse' $ref: '#/components/schemas/SlackInternalDepartmentGoalProgressConfigResponse'
/slack/config/internal-department-goal-progress/test:
post:
tags: [Config]
summary: Test Slack internal department goal progress webhook
operationId: testSlackInternalDepartmentGoalProgressWebhook
responses:
'200':
description: Slack internal department goal progress webhook test completed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/SlackConfigTestResponse'
'400':
description: Slack internal department goal progress webhook URL is not configured
'502':
description: Slack internal department goal progress webhook test failed
/backups/config: /backups/config:
get: get:
tags: [Config] tags: [Config]
@@ -250,6 +250,35 @@ class moduleConfigRoute
] ]
); );
/** Slack internal department goal progress config > TEST */
$this->post('/slack/config/internal-department-goal-progress/test', function () {
global $response;
$this->requirePermission('slack_config');
$user = (new authentication())->get_user();
if (!$user) {
(new logs_o())->add('slack_config', 'global', 1, 0, 'SLACK_INTERNAL_DEPARTMENT_GOAL_PROGRESS_CONFIG_TEST', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
$result = (new slack())->test_internal_department_goal_progress_webhook();
if (($result['configured'] ?? false) !== true) {
(new logs_o())->add('slack_config', 'global', 0, $user->id, 'SLACK_INTERNAL_DEPARTMENT_GOAL_PROGRESS_CONFIG_TEST', 'Slack internal department goal progress webhook URL is not configured');
$response->error($result['message'] ?? 'Slack internal department goal progress webhook URL is not configured.', 400);
}
if (($result['sent'] ?? false) !== true) {
(new logs_o())->add('slack_config', 'global', 0, $user->id, 'SLACK_INTERNAL_DEPARTMENT_GOAL_PROGRESS_CONFIG_TEST', 'Slack internal department goal progress test webhook failed');
$response->error($result['message'] ?? 'Slack test message failed.', 502);
}
(new logs_o())->add('slack_config', 'global', 1, $user->id, 'SLACK_INTERNAL_DEPARTMENT_GOAL_PROGRESS_CONFIG_TEST', 'Successfully tested Slack internal department goal progress webhook');
$response->success($result);
},
[
'slack_config' => 'Test Slack internal department goal progress config'
]
);
/** Slack internal department goal progress config > GET */ /** Slack internal department goal progress config > GET */
$this->get('/slack/config/internal-department-goal-progress', function () { $this->get('/slack/config/internal-department-goal-progress', function () {
global $response; global $response;
@@ -8,10 +8,12 @@ it('registers Slack module config endpoints and customer registration webhook co
->and($routeContent)->toContain('/slack/config') ->and($routeContent)->toContain('/slack/config')
->and($routeContent)->toContain('/slack/config/test') ->and($routeContent)->toContain('/slack/config/test')
->and($routeContent)->toContain('/slack/config/internal-department-goal-progress') ->and($routeContent)->toContain('/slack/config/internal-department-goal-progress')
->and($routeContent)->toContain('/slack/config/internal-department-goal-progress/test')
->and($routeContent)->toContain("requirePermission('slack_config')") ->and($routeContent)->toContain("requirePermission('slack_config')")
->and($routeContent)->toContain("(new slack())->getConfig()->getConfigRequest()") ->and($routeContent)->toContain("(new slack())->getConfig()->getConfigRequest()")
->and($routeContent)->toContain("(new slack())->getConfig()->postConfigRequest()") ->and($routeContent)->toContain("(new slack())->getConfig()->postConfigRequest()")
->and($routeContent)->toContain("(new slack())->test_customer_registration_webhook()") ->and($routeContent)->toContain("(new slack())->test_customer_registration_webhook()")
->and($routeContent)->toContain("(new slack())->test_internal_department_goal_progress_webhook()")
->and($routeContent)->toContain("(new slack())->get_internal_department_goal_progress_config()") ->and($routeContent)->toContain("(new slack())->get_internal_department_goal_progress_config()")
->and($routeContent)->toContain("set_internal_department_goal_progress_config"); ->and($routeContent)->toContain("set_internal_department_goal_progress_config");
@@ -40,9 +42,11 @@ it('registers Slack module config endpoints and customer registration webhook co
->and($slackClassContent)->not->toBeFalse() ->and($slackClassContent)->not->toBeFalse()
->and($slackClassContent)->toContain('send_customer_registration_notification') ->and($slackClassContent)->toContain('send_customer_registration_notification')
->and($slackClassContent)->toContain('test_customer_registration_webhook') ->and($slackClassContent)->toContain('test_customer_registration_webhook')
->and($slackClassContent)->toContain('test_internal_department_goal_progress_webhook')
->and($slackClassContent)->toContain('get_internal_department_goal_progress_config') ->and($slackClassContent)->toContain('get_internal_department_goal_progress_config')
->and($slackClassContent)->toContain('get_internal_department_goal_progress_webhook_url') ->and($slackClassContent)->toContain('get_internal_department_goal_progress_webhook_url')
->and($slackClassContent)->toContain('format_customer_registration_test') ->and($slackClassContent)->toContain('format_customer_registration_test')
->and($slackClassContent)->toContain('format_internal_department_goal_progress_test')
->and($slackClassContent)->toContain('format_customer_registration') ->and($slackClassContent)->toContain('format_customer_registration')
->and($authRouteContent)->not->toBeFalse() ->and($authRouteContent)->not->toBeFalse()
->and($authRouteContent)->toContain("AUTH_REGISTER_CVR_SLACK_NOTIFICATION_FAILED") ->and($authRouteContent)->toContain("AUTH_REGISTER_CVR_SLACK_NOTIFICATION_FAILED")
@@ -54,6 +58,7 @@ it('registers Slack module config endpoints and customer registration webhook co
->and($openApiContent)->toContain('/slack/config') ->and($openApiContent)->toContain('/slack/config')
->and($openApiContent)->toContain('/slack/config/test') ->and($openApiContent)->toContain('/slack/config/test')
->and($openApiContent)->toContain('/slack/config/internal-department-goal-progress') ->and($openApiContent)->toContain('/slack/config/internal-department-goal-progress')
->and($openApiContent)->toContain('/slack/config/internal-department-goal-progress/test')
->and($openApiContent)->toContain('SlackConfigListResponse') ->and($openApiContent)->toContain('SlackConfigListResponse')
->and($openApiContent)->toContain('SlackInternalDepartmentGoalProgressConfigResponse') ->and($openApiContent)->toContain('SlackInternalDepartmentGoalProgressConfigResponse')
->and($openApiContent)->toContain('SlackConfigTestResponse') ->and($openApiContent)->toContain('SlackConfigTestResponse')
@@ -10,7 +10,8 @@ final class SlackCustomerRegistrationWebhookFake extends slack
public function __construct( public function __construct(
private readonly string $webhook, private readonly string $webhook,
private readonly string $sendResult = 'Message sent successfully. Response: ok' private readonly string $sendResult = 'Message sent successfully. Response: ok',
private readonly ?string $internalDepartmentGoalProgressWebhook = null
) { ) {
// Skip parent config loading for unit isolation. // Skip parent config loading for unit isolation.
} }
@@ -20,6 +21,11 @@ final class SlackCustomerRegistrationWebhookFake extends slack
return $this->webhook; return $this->webhook;
} }
public function get_internal_department_goal_progress_webhook_url(): string
{
return $this->internalDepartmentGoalProgressWebhook ?? $this->webhook;
}
public function send_webhook_message(string $message, string $webhook): string public function send_webhook_message(string $message, string $webhook): string
{ {
$this->messages[] = [ $this->messages[] = [
@@ -84,3 +90,63 @@ it('reports customer registration test notification failures without exposing th
->and(json_encode($slack->get_log(), JSON_UNESCAPED_SLASHES))->toContain('failed') ->and(json_encode($slack->get_log(), JSON_UNESCAPED_SLASHES))->toContain('failed')
->and(json_encode($slack->get_log(), JSON_UNESCAPED_SLASHES))->not->toContain('secret-token'); ->and(json_encode($slack->get_log(), JSON_UNESCAPED_SLASHES))->not->toContain('secret-token');
}); });
it('does not send internal department goal progress test notifications without a saved webhook', function (): void {
$slack = new SlackCustomerRegistrationWebhookFake(
'https://hooks.slack.test/services/customer-registration',
internalDepartmentGoalProgressWebhook: ''
);
$result = $slack->test_internal_department_goal_progress_webhook();
expect($result)
->toBe([
'configured' => false,
'sent' => false,
'message' => 'Slack internal department goal progress webhook URL is not configured.',
])
->and($slack->messages)->toBe([]);
});
it('sends internal department goal progress test notifications to the saved webhook', function (): void {
$slack = new SlackCustomerRegistrationWebhookFake(
'https://hooks.slack.test/services/customer-registration',
internalDepartmentGoalProgressWebhook: 'https://hooks.slack.test/services/internal-goals-secret'
);
$result = $slack->test_internal_department_goal_progress_webhook();
expect($result)
->toBe([
'configured' => true,
'sent' => true,
'message' => 'Slack test message sent successfully.',
])
->and($slack->messages)->toHaveCount(1)
->and($slack->messages[0]['webhook'])->toBe('https://hooks.slack.test/services/internal-goals-secret')
->and($slack->messages[0]['message'])->toContain('Truck Wash Slack test')
->and($slack->messages[0]['message'])->toContain('Internal department goal progress notifications are configured correctly.')
->and(json_encode($slack->get_log(), JSON_UNESCAPED_SLASHES))->toContain('sent successfully')
->and(json_encode($slack->get_log(), JSON_UNESCAPED_SLASHES))->not->toContain('internal-goals-secret');
});
it('reports internal department goal progress test notification failures without exposing the webhook', function (): void {
$slack = new SlackCustomerRegistrationWebhookFake(
'https://hooks.slack.test/services/customer-registration',
'Failed to send message: cURL error for https://hooks.slack.test/services/internal-goals-secret',
'https://hooks.slack.test/services/internal-goals-secret'
);
$result = $slack->test_internal_department_goal_progress_webhook();
expect($result)
->toBe([
'configured' => true,
'sent' => false,
'message' => 'Slack test message failed.',
])
->and($slack->messages)->toHaveCount(1)
->and(json_encode($result, JSON_UNESCAPED_SLASHES))->not->toContain('internal-goals-secret')
->and(json_encode($slack->get_log(), JSON_UNESCAPED_SLASHES))->toContain('failed')
->and(json_encode($slack->get_log(), JSON_UNESCAPED_SLASHES))->not->toContain('internal-goals-secret');
});