test(alerts): cover global read — one user marks read, others see readAt
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -442,6 +442,62 @@ class AlertControllerIT extends AbstractPostgresIT {
|
|||||||
assertThat(bothRead).as("read must appear with no read filter").isTrue();
|
assertThat(bothRead).as("read must appear with no read filter").isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void read_is_global_other_users_see_readAt_set() throws Exception {
|
||||||
|
// Seed an alert targeting BOTH users so the viewer's GET /{id} is visible
|
||||||
|
AlertInstance instance = new AlertInstance(
|
||||||
|
UUID.randomUUID(), null, null, envIdA,
|
||||||
|
AlertState.FIRING, AlertSeverity.WARNING,
|
||||||
|
Instant.now(), null, null, null, null, null, null, false,
|
||||||
|
42.0, 1000.0, null, "Global read test", "Operator reads, viewer sees it",
|
||||||
|
List.of("test-operator", "test-viewer"), List.of(), List.of());
|
||||||
|
instance = instanceRepo.save(instance);
|
||||||
|
|
||||||
|
// Operator (user A) marks the alert as read
|
||||||
|
ResponseEntity<String> readResp = restTemplate.exchange(
|
||||||
|
"/api/v1/environments/" + envSlugA + "/alerts/" + instance.id() + "/read",
|
||||||
|
HttpMethod.POST,
|
||||||
|
new HttpEntity<>(securityHelper.authHeaders(operatorJwt)),
|
||||||
|
String.class);
|
||||||
|
assertThat(readResp.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
|
||||||
|
// Viewer (user B) fetches the same alert and must see readAt != null
|
||||||
|
ResponseEntity<String> getResp = restTemplate.exchange(
|
||||||
|
"/api/v1/environments/" + envSlugA + "/alerts/" + instance.id(),
|
||||||
|
HttpMethod.GET,
|
||||||
|
new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)),
|
||||||
|
String.class);
|
||||||
|
assertThat(getResp.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
JsonNode node = objectMapper.readTree(getResp.getBody());
|
||||||
|
assertThat(node.path("readAt").isNull())
|
||||||
|
.as("viewer must see readAt as non-null after operator marked read")
|
||||||
|
.isFalse();
|
||||||
|
assertThat(node.path("readAt").isMissingNode())
|
||||||
|
.as("readAt field must be present in response")
|
||||||
|
.isFalse();
|
||||||
|
|
||||||
|
// Viewer's list endpoint must also show the alert with readAt set
|
||||||
|
ResponseEntity<String> listResp = restTemplate.exchange(
|
||||||
|
"/api/v1/environments/" + envSlugA + "/alerts",
|
||||||
|
HttpMethod.GET,
|
||||||
|
new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)),
|
||||||
|
String.class);
|
||||||
|
assertThat(listResp.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
JsonNode listBody = objectMapper.readTree(listResp.getBody());
|
||||||
|
UUID instanceId = instance.id();
|
||||||
|
boolean foundWithReadAt = false;
|
||||||
|
for (JsonNode item : listBody) {
|
||||||
|
if (item.path("id").asText().equals(instanceId.toString())) {
|
||||||
|
assertThat(item.path("readAt").isNull())
|
||||||
|
.as("list entry readAt must be non-null for viewer after global read")
|
||||||
|
.isFalse();
|
||||||
|
foundWithReadAt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertThat(foundWithReadAt).as("alert must appear in viewer's list with readAt set").isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Helpers
|
// Helpers
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user