From 69fe80353ceca149a4d130d88c57ede976274081 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:55:12 +0200 Subject: [PATCH] =?UTF-8?q?test(alerts):=20close=20repo=20IT=20gaps=20?= =?UTF-8?q?=E2=80=94=20filterInEnvLive=20other-env=20+=20bulkMarkRead=20so?= =?UTF-8?q?ft-delete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- .../PostgresAlertInstanceRepositoryIT.java | 64 ++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/storage/PostgresAlertInstanceRepositoryIT.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/storage/PostgresAlertInstanceRepositoryIT.java index 5ee591a0..b2a221a6 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/storage/PostgresAlertInstanceRepositoryIT.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/storage/PostgresAlertInstanceRepositoryIT.java @@ -22,6 +22,7 @@ class PostgresAlertInstanceRepositoryIT extends AbstractPostgresIT { private PostgresAlertInstanceRepository repo; private UUID envId; + private UUID otherEnvId; private UUID ruleId; private final String userId = "inbox-user-" + UUID.randomUUID(); private final String groupId = UUID.randomUUID().toString(); @@ -31,11 +32,15 @@ class PostgresAlertInstanceRepositoryIT extends AbstractPostgresIT { void setup() { repo = new PostgresAlertInstanceRepository(jdbcTemplate, new ObjectMapper()); envId = UUID.randomUUID(); + otherEnvId = UUID.randomUUID(); ruleId = UUID.randomUUID(); jdbcTemplate.update( "INSERT INTO environments (id, slug, display_name) VALUES (?, ?, ?)", envId, "test-env-" + UUID.randomUUID(), "Test Env"); + jdbcTemplate.update( + "INSERT INTO environments (id, slug, display_name) VALUES (?, ?, ?)", + otherEnvId, "other-env-" + UUID.randomUUID(), "Other Env"); jdbcTemplate.update( "INSERT INTO users (user_id, provider, email) VALUES (?, 'local', ?) ON CONFLICT (user_id) DO NOTHING", userId, userId + "@example.com"); @@ -52,9 +57,14 @@ class PostgresAlertInstanceRepositoryIT extends AbstractPostgresIT { void cleanup() { jdbcTemplate.update("DELETE FROM alert_notifications WHERE alert_instance_id IN " + "(SELECT id FROM alert_instances WHERE environment_id = ?)", envId); + jdbcTemplate.update("DELETE FROM alert_notifications WHERE alert_instance_id IN " + + "(SELECT id FROM alert_instances WHERE environment_id = ?)", otherEnvId); jdbcTemplate.update("DELETE FROM alert_instances WHERE environment_id = ?", envId); + jdbcTemplate.update("DELETE FROM alert_instances WHERE environment_id = ?", otherEnvId); jdbcTemplate.update("DELETE FROM alert_rules WHERE environment_id = ?", envId); + jdbcTemplate.update("DELETE FROM alert_rules WHERE environment_id = ?", otherEnvId); jdbcTemplate.update("DELETE FROM environments WHERE id = ?", envId); + jdbcTemplate.update("DELETE FROM environments WHERE id = ?", otherEnvId); jdbcTemplate.update("DELETE FROM users WHERE user_id = ?", userId); } @@ -380,8 +390,34 @@ class PostgresAlertInstanceRepositoryIT extends AbstractPostgresIT { UUID unknownId = UUID.randomUUID(); // not in DB at all - var kept = repo.filterInEnvLive(List.of(a.id(), b.id(), unknownId), envId); + // Insert a rule + instance in the second environment (otherEnvId) to prove + // that the SQL env-filter actually excludes rows from a different environment. + UUID otherRuleId = seedRuleInEnv("other-rule", otherEnvId); + var otherEnvInst = newInstanceInEnv(otherRuleId, otherEnvId, List.of(userId), List.of(), List.of()); + repo.save(otherEnvInst); + + var kept = repo.filterInEnvLive(List.of(a.id(), b.id(), unknownId, otherEnvInst.id()), envId); assertThat(kept).containsExactly(a.id()); + assertThat(kept).doesNotContain(otherEnvInst.id()); + } + + @Test + void bulkMarkRead_respects_deleted_at() { + var live = insertFreshFiring(); + // second instance — need a fresh ruleId due to the open-rule unique index + UUID ruleId2 = seedRule("rule-deleted"); + var deleted = newInstance(ruleId2, List.of(userId), List.of(), List.of()); + repo.save(deleted); + + repo.softDelete(deleted.id(), Instant.parse("2026-04-21T10:00:00Z")); + + repo.bulkMarkRead(List.of(live.id(), deleted.id()), Instant.parse("2026-04-21T10:05:00Z")); + + // live row is marked read + assertThat(repo.findById(live.id()).orElseThrow().readAt()) + .isEqualTo(Instant.parse("2026-04-21T10:05:00Z")); + // soft-deleted row is NOT touched by bulkMarkRead + assertThat(repo.findById(deleted.id()).orElseThrow().readAt()).isNull(); } // ------------------------------------------------------------------------- @@ -453,6 +489,32 @@ class PostgresAlertInstanceRepositoryIT extends AbstractPostgresIT { return id; } + /** Inserts a minimal alert_rule in a specific environment and returns its id. */ + private UUID seedRuleInEnv(String name, UUID targetEnvId) { + UUID id = UUID.randomUUID(); + jdbcTemplate.update( + "INSERT INTO alert_rules (id, environment_id, name, severity, condition_kind, condition, " + + "notification_title_tmpl, notification_message_tmpl, created_by, updated_by) " + + "VALUES (?, ?, ?, 'WARNING', 'AGENT_STATE', '{}'::jsonb, 't', 'm', 'sys-user', 'sys-user')", + id, targetEnvId, name + "-" + id); + return id; + } + + /** Creates an AlertInstance bound to a specific environment (not the default envId). */ + private AlertInstance newInstanceInEnv(UUID ruleId, + UUID targetEnvId, + List userIds, + List groupIds, + List roleNames) { + return new AlertInstance( + UUID.randomUUID(), ruleId, Map.of(), targetEnvId, + AlertState.FIRING, AlertSeverity.WARNING, + Instant.now(), null, null, null, null, null, null, + false, null, null, + Map.of(), "title", "message", + userIds, groupIds, roleNames); + } + /** Inserts a minimal alert_rule with re_notify_minutes=1 and returns its id. */ private UUID seedReNotifyRule(String name) { UUID id = UUID.randomUUID();