feat: add feedback comments activity notifications

This commit is contained in:
2026-04-30 13:24:23 -04:00
parent 4873f39192
commit 1263e28c00
26 changed files with 2255 additions and 18 deletions

View File

@@ -1,5 +1,7 @@
using Socialize.Api.Modules.Feedback.Data;
using Socialize.Api.Modules.Feedback.Contracts;
using Socialize.Api.Modules.Feedback.Services;
using System.Text.Json;
namespace Socialize.Tests.Feedback;
@@ -105,6 +107,26 @@ public class FeedbackRulesTests
Assert.False(otherUserAllowed);
}
[Fact]
public void CanReporterComment_requires_report_owner()
{
Guid reporterUserId = Guid.NewGuid();
FeedbackReport report = new() { ReporterUserId = reporterUserId };
bool ownerAllowed = FeedbackAccessRules.CanReporterComment(report, reporterUserId);
bool otherUserAllowed = FeedbackAccessRules.CanReporterComment(report, Guid.NewGuid());
Assert.True(ownerAllowed);
Assert.False(otherUserAllowed);
}
[Fact]
public void CanDeveloperComment_requires_developer_role()
{
Assert.True(FeedbackAccessRules.CanDeveloperComment(isDeveloper: true));
Assert.False(FeedbackAccessRules.CanDeveloperComment(isDeveloper: false));
}
[Fact]
public void CanAccessScreenshot_allows_report_owner()
{
@@ -185,4 +207,68 @@ public class FeedbackRulesTests
Assert.Equal(["bug", "mobile"], tags);
}
[Fact]
public void Feedback_report_dto_returns_mixed_timeline_in_created_order()
{
Guid reportId = Guid.NewGuid();
DateTimeOffset now = DateTimeOffset.UtcNow;
FeedbackReport report = new()
{
Id = reportId,
Type = FeedbackType.Bug,
Status = FeedbackStatus.New,
Description = "Broken layout",
ReporterUserId = Guid.NewGuid(),
ReporterDisplayName = "Reporter",
ReporterEmail = "reporter@example.com",
SubmittedPath = "/app/example",
CreatedAt = now,
LastActivityAt = now.AddMinutes(2),
};
report.ActivityEntries.Add(new FeedbackActivityEntry
{
Id = Guid.NewGuid(),
FeedbackReportId = reportId,
ActorUserId = Guid.NewGuid(),
ActorDisplayName = "Developer",
ActorEmail = "dev@example.com",
ActivityType = FeedbackActivityTypes.StatusChanged,
FromValue = "New",
ToValue = "Planned",
CreatedAt = now.AddMinutes(2),
});
report.Comments.Add(new FeedbackComment
{
Id = Guid.NewGuid(),
FeedbackReportId = reportId,
AuthorUserId = report.ReporterUserId,
AuthorDisplayName = "Reporter",
AuthorEmail = "reporter@example.com",
AuthorRole = "Reporter",
Body = "More context",
CreatedAt = now.AddMinutes(1),
});
FeedbackReportDto dto = report.ToDto();
Assert.Equal(["Comment", "Activity"], dto.Timeline.Select(item => item.Kind).ToArray());
Assert.Equal("More context", dto.Timeline.First().Body);
Assert.Equal(FeedbackActivityTypes.StatusChanged, dto.Timeline.Last().ActivityType);
}
[Fact]
public void Feedback_notification_metadata_includes_target_route()
{
Guid reportId = Guid.NewGuid();
string developerMetadata = FeedbackNotificationRoutes.BuildMetadataJson(reportId, developerRoute: true);
string reporterMetadata = FeedbackNotificationRoutes.BuildMetadataJson(reportId, developerRoute: false);
using JsonDocument developerDocument = JsonDocument.Parse(developerMetadata);
using JsonDocument reporterDocument = JsonDocument.Parse(reporterMetadata);
Assert.Equal($"/app/feedback/{reportId}", developerDocument.RootElement.GetProperty("route").GetString());
Assert.Equal($"/app/my-feedback/{reportId}", reporterDocument.RootElement.GetProperty("route").GetString());
Assert.True(developerDocument.RootElement.GetProperty("isFeedbackNotification").GetBoolean());
}
}