test(audit): add youParticipated and youMentioned repository tests

Add isYouParticipated() to ActivityFeedRow interface and cover four
behaviours in AuditLogQueryRepositoryRolledUpTest: youParticipated
true/false and retroactive youMentioned true/false coverage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-20 21:19:27 +02:00
committed by marcel
parent 6f3aa056a1
commit 9c52e1921f
3 changed files with 80 additions and 3 deletions

View File

@@ -12,6 +12,7 @@ public interface ActivityFeedRow {
UUID getDocumentId();
Instant getHappenedAt();
boolean isYouMentioned();
boolean isYouParticipated();
int getCount();
Instant getHappenedAtUntil();
}

View File

@@ -17,6 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
@@ -28,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class AuditLogQueryRepositoryRolledUpTest {
static final UUID USER_ID = UUID.fromString("dddddddd-dddd-dddd-dddd-dddddddddddd");
static final UUID OTHER_USER_ID = UUID.fromString("cccccccc-cccc-cccc-cccc-cccccccccccc");
static final UUID DOC_ID = UUID.fromString("eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee");
static final UUID OTHER_DOC_ID = UUID.fromString("ffffffff-ffff-ffff-ffff-ffffffffffff");
@@ -42,6 +44,9 @@ class AuditLogQueryRepositoryRolledUpTest {
jdbcTemplate.update(
"INSERT INTO users (id, enabled, email, password) VALUES (?, true, ?, 'pw')",
USER_ID, "rollup-" + USER_ID + "@test.com");
jdbcTemplate.update(
"INSERT INTO users (id, enabled, email, password) VALUES (?, true, ?, 'pw')",
OTHER_USER_ID, "rollup-" + OTHER_USER_ID + "@test.com");
jdbcTemplate.update(
"INSERT INTO documents (id, title, original_filename, status) VALUES (?, 'Brief A', 'a.pdf', 'PLACEHOLDER')",
DOC_ID);
@@ -51,17 +56,32 @@ class AuditLogQueryRepositoryRolledUpTest {
}
private void insertAuditEvent(UUID actorId, UUID docId, String kind, Instant happenedAt) {
insertAuditEvent(actorId, docId, kind, happenedAt, Map.of());
}
private void insertAuditEvent(UUID actorId, UUID docId, String kind, Instant happenedAt, Map<String, String> payload) {
String payloadJson = payload.isEmpty() ? null
: payload.entrySet().stream()
.map(e -> "\"" + e.getKey() + "\": \"" + e.getValue() + "\"")
.collect(java.util.stream.Collectors.joining(", ", "{", "}"));
MapSqlParameterSource params = new MapSqlParameterSource()
.addValue("kind", kind)
.addValue("actor", actorId)
.addValue("doc", docId)
.addValue("t", OffsetDateTime.ofInstant(happenedAt, java.time.ZoneOffset.UTC));
.addValue("t", OffsetDateTime.ofInstant(happenedAt, java.time.ZoneOffset.UTC))
.addValue("payload", payloadJson, java.sql.Types.OTHER);
named().update(
"INSERT INTO audit_log (kind, actor_id, document_id, happened_at) "
+ "VALUES (:kind, :actor, :doc, :t)",
"INSERT INTO audit_log (kind, actor_id, document_id, happened_at, payload) "
+ "VALUES (:kind, :actor, :doc, :t, :payload::jsonb)",
params);
}
private void insertReplyNotification(UUID recipientId, UUID docId, UUID commentId) {
jdbcTemplate.update(
"INSERT INTO notifications (recipient_id, type, document_id, reference_id) VALUES (?, 'REPLY', ?, ?)",
recipientId, docId, commentId);
}
@Test
void rolledUpFeed_combines_same_actor_same_doc_within_2h() {
insertUserAndDocs();
@@ -173,4 +193,59 @@ class AuditLogQueryRepositoryRolledUpTest {
assertThat(r.getHappenedAtUntil()).isNull();
});
}
@Test
void youParticipated_is_true_when_user_has_reply_notification_for_comment() {
insertUserAndDocs();
UUID commentId = UUID.randomUUID();
insertAuditEvent(OTHER_USER_ID, DOC_ID, "COMMENT_ADDED",
Instant.parse("2026-04-20T10:00:00Z"), Map.of("commentId", commentId.toString()));
insertReplyNotification(USER_ID, DOC_ID, commentId);
List<ActivityFeedRow> rows = auditLogQueryRepository.findRolledUpActivityFeed(USER_ID.toString(), 40);
assertThat(rows).anySatisfy(r ->
assertThat(r.isYouParticipated()).isTrue()
);
}
@Test
void youParticipated_is_false_for_comment_with_no_reply_notification() {
insertUserAndDocs();
UUID commentId = UUID.randomUUID();
insertAuditEvent(OTHER_USER_ID, DOC_ID, "COMMENT_ADDED",
Instant.parse("2026-04-20T10:00:00Z"), Map.of("commentId", commentId.toString()));
List<ActivityFeedRow> rows = auditLogQueryRepository.findRolledUpActivityFeed(USER_ID.toString(), 40);
assertThat(rows).allSatisfy(r ->
assertThat(r.isYouParticipated()).isFalse()
);
}
@Test
void youMentioned_is_true_when_mention_created_payload_matches_current_user() {
insertUserAndDocs();
insertAuditEvent(OTHER_USER_ID, DOC_ID, "MENTION_CREATED",
Instant.parse("2026-04-20T10:00:00Z"), Map.of("mentionedUserId", USER_ID.toString()));
List<ActivityFeedRow> rows = auditLogQueryRepository.findRolledUpActivityFeed(USER_ID.toString(), 40);
assertThat(rows).anySatisfy(r ->
assertThat(r.isYouMentioned()).isTrue()
);
}
@Test
void youMentioned_is_false_when_mention_created_payload_targets_different_user() {
insertUserAndDocs();
insertAuditEvent(USER_ID, DOC_ID, "MENTION_CREATED",
Instant.parse("2026-04-20T10:00:00Z"), Map.of("mentionedUserId", OTHER_USER_ID.toString()));
List<ActivityFeedRow> rows = auditLogQueryRepository.findRolledUpActivityFeed(USER_ID.toString(), 40);
assertThat(rows).allSatisfy(r ->
assertThat(r.isYouMentioned()).isFalse()
);
}
}

View File

@@ -104,6 +104,7 @@ class DashboardServiceTest {
public UUID getDocumentId() { return docId; }
public Instant getHappenedAt() { return Instant.now(); }
public boolean isYouMentioned() { return false; }
public boolean isYouParticipated() { return false; }
public int getCount() { return 1; }
public Instant getHappenedAtUntil() { return null; }
};