feat(KAN-45): rebuild project notification settings
CI/CD / preconditions (pull_request) Successful in 1s
CI/CD / test_and_check_app (pull_request) Successful in 29m56s
CI/CD / Publish immutable image (pull_request) Skipped

This commit is contained in:
2026-09-15 22:44:16 +02:00
parent b226ee8d48
commit 3f795ba32e
11 changed files with 1752 additions and 1190 deletions
@@ -430,4 +430,66 @@ class ProjectNotificationSettingsControllerTest extends TestCase
->missing('notificationActions.0.delivery_url'),
);
}
public function test_editor_accepts_array_filters_and_can_clear_discord_mentions(): void
{
$user = User::factory()->create();
$project = Project::factory()->create();
$notificationAction = NotificationAction::factory()->discord()->for($project)->create([
'channel_configuration' => ['allowed_mentions' => ['users']],
'delivery_url' => 'https://discord.com/api/webhooks/123456/original-secret',
]);
$this->syncProjectPermissions($project, $user, ['edit']);
$this->actingAs($user)
->patch(route('projects.settings.notifications.update', [$project, $notificationAction]), [
'name' => 'Paused alerts',
'event_type' => NotificationEventType::TicketAssigneeChanged->value,
'channel' => NotificationChannel::Discord->value,
'enabled' => false,
'delivery_url' => null,
'message_template' => '$ticket_key: $url',
'channel_configuration' => ['allowed_mentions' => []],
'filters' => [
['attribute' => 'ticket.key', 'operator' => 'in', 'value' => ['CORE-1', 'CORE-2']],
['attribute' => 'actor.name', 'operator' => 'exists', 'value' => null],
],
])
->assertSessionHasNoErrors()
->assertRedirect(route('projects.settings.notifications', $project));
$notificationAction->refresh();
$this->assertFalse($notificationAction->enabled);
$this->assertSame(['allowed_mentions' => []], $notificationAction->channel_configuration);
$this->assertSame('https://discord.com/api/webhooks/123456/original-secret', $notificationAction->delivery_url);
$this->assertSame([
['attribute' => 'ticket.key', 'operator' => 'in', 'value' => ['CORE-1', 'CORE-2']],
['attribute' => 'actor.name', 'operator' => 'exists', 'value' => null],
], $notificationAction->filters);
}
public function test_invalid_editor_update_does_not_change_saved_configuration(): void
{
$user = User::factory()->create();
$project = Project::factory()->create();
$notificationAction = NotificationAction::factory()->discord()->for($project)->create();
$original = $notificationAction->fresh()->getRawOriginal();
$this->syncProjectPermissions($project, $user, ['edit']);
$this->actingAs($user)
->from(route('projects.settings.notifications', $project))
->patch(route('projects.settings.notifications.update', [$project, $notificationAction]), [
'name' => 'Invalid update',
'event_type' => NotificationEventType::TicketCreate->value,
'channel' => NotificationChannel::Discord->value,
'enabled' => false,
'delivery_url' => 'invalid-url',
'message_template' => '',
'channel_configuration' => ['allowed_mentions' => ['unsupported']],
'filters' => [['attribute' => 'ticket.key', 'operator' => 'in', 'value' => []]],
])
->assertSessionHasErrors(['delivery_url', 'message_template', 'channel_configuration.allowed_mentions.0', 'filters.0.value']);
$this->assertSame($original, $notificationAction->fresh()->getRawOriginal());
}
}
@@ -0,0 +1,19 @@
<?php
namespace Tests\Feature\Projects;
use Symfony\Component\Process\Process;
use Tests\TestCase;
class ProjectNotificationSettingsUiTest extends TestCase
{
public function test_notification_settings_render_actions_and_serialize_filter_values(): void
{
$process = new Process(['node', 'tests/Fixtures/project-notification-settings.mjs'], base_path());
$process->setTimeout(60);
$process->run();
$this->assertTrue($process->isSuccessful(), $process->getOutput().$process->getErrorOutput());
$this->assertStringContainsString('Notification settings checks passed.', $process->getOutput());
}
}