Files
social-media/backend/tests/Socialize.Tests/Feedback/FeedbackRulesTests.cs

189 lines
5.5 KiB
C#

using Socialize.Api.Modules.Feedback.Data;
using Socialize.Api.Modules.Feedback.Services;
namespace Socialize.Tests.Feedback;
public class FeedbackRulesTests
{
[Theory]
[InlineData("Bug", FeedbackType.Bug)]
[InlineData("suggestion", FeedbackType.Suggestion)]
[InlineData("Request", FeedbackType.Request)]
public void TryParseType_accepts_supported_types(string value, FeedbackType expected)
{
bool parsed = FeedbackRules.TryParseType(value, out FeedbackType type);
Assert.True(parsed);
Assert.Equal(expected, type);
}
[Theory]
[InlineData("")]
[InlineData("Question")]
[InlineData("Incident")]
public void TryParseType_rejects_unsupported_types(string value)
{
bool parsed = FeedbackRules.TryParseType(value, out _);
Assert.False(parsed);
}
[Theory]
[InlineData("New", FeedbackStatus.New)]
[InlineData("Planned", FeedbackStatus.Planned)]
[InlineData("Resolved", FeedbackStatus.Resolved)]
[InlineData("Won't Do", FeedbackStatus.WontDo)]
[InlineData("WontDo", FeedbackStatus.WontDo)]
[InlineData("Cancelled", FeedbackStatus.Cancelled)]
public void TryParseStatus_accepts_supported_statuses(string value, FeedbackStatus expected)
{
bool parsed = FeedbackRules.TryParseStatus(value, out FeedbackStatus status);
Assert.True(parsed);
Assert.Equal(expected, status);
}
[Fact]
public void CanDeveloperSetStatus_rejects_cancelled_destination()
{
bool allowed = FeedbackRules.CanDeveloperSetStatus(FeedbackStatus.New, FeedbackStatus.Cancelled);
Assert.False(allowed);
}
[Fact]
public void CanDeveloperSetStatus_rejects_changes_after_cancelled()
{
bool allowed = FeedbackRules.CanDeveloperSetStatus(FeedbackStatus.Cancelled, FeedbackStatus.Planned);
Assert.False(allowed);
}
[Fact]
public void CanReporterCancel_rejects_cancelled_report()
{
bool allowed = FeedbackRules.CanReporterCancel(FeedbackStatus.Cancelled);
Assert.False(allowed);
}
[Fact]
public void CanReporterAccess_allows_report_owner()
{
Guid reporterUserId = Guid.NewGuid();
FeedbackReport report = new() { ReporterUserId = reporterUserId };
bool allowed = FeedbackAccessRules.CanReporterAccess(report, reporterUserId);
Assert.True(allowed);
}
[Fact]
public void CanReporterAccess_rejects_other_users()
{
FeedbackReport report = new() { ReporterUserId = Guid.NewGuid() };
bool allowed = FeedbackAccessRules.CanReporterAccess(report, Guid.NewGuid());
Assert.False(allowed);
}
[Fact]
public void CanReporterCancel_requires_owner_and_non_final_status()
{
Guid reporterUserId = Guid.NewGuid();
FeedbackReport report = new()
{
ReporterUserId = reporterUserId,
Status = FeedbackStatus.New,
};
bool ownerAllowed = FeedbackAccessRules.CanReporterCancel(report, reporterUserId);
bool otherUserAllowed = FeedbackAccessRules.CanReporterCancel(report, Guid.NewGuid());
Assert.True(ownerAllowed);
Assert.False(otherUserAllowed);
}
[Fact]
public void CanAccessScreenshot_allows_report_owner()
{
Guid reporterUserId = Guid.NewGuid();
FeedbackReport report = new() { ReporterUserId = reporterUserId };
bool allowed = FeedbackAccessRules.CanAccessScreenshot(report, reporterUserId, isDeveloper: false);
Assert.True(allowed);
}
[Fact]
public void CanAccessScreenshot_allows_developer()
{
FeedbackReport report = new() { ReporterUserId = Guid.NewGuid() };
bool allowed = FeedbackAccessRules.CanAccessScreenshot(report, Guid.NewGuid(), isDeveloper: true);
Assert.True(allowed);
}
[Fact]
public void CanAccessScreenshot_rejects_unrelated_non_developer()
{
FeedbackReport report = new() { ReporterUserId = Guid.NewGuid() };
bool allowed = FeedbackAccessRules.CanAccessScreenshot(report, Guid.NewGuid(), isDeveloper: false);
Assert.False(allowed);
}
[Theory]
[InlineData("image/png")]
[InlineData("image/jpeg")]
[InlineData("image/jpg")]
public void Screenshot_content_type_allows_png_and_jpeg(string contentType)
{
bool allowed = FeedbackScreenshotRules.IsAllowedContentType(contentType);
Assert.True(allowed);
}
[Theory]
[InlineData("text/html")]
[InlineData("application/pdf")]
[InlineData("")]
public void Screenshot_content_type_rejects_non_images(string contentType)
{
bool allowed = FeedbackScreenshotRules.IsAllowedContentType(contentType);
Assert.False(allowed);
}
[Theory]
[InlineData(1)]
[InlineData(FeedbackScreenshotRules.MaxScreenshotBytes)]
public void Screenshot_size_allows_non_empty_files_up_to_limit(long sizeBytes)
{
bool allowed = FeedbackScreenshotRules.IsAllowedSize(sizeBytes);
Assert.True(allowed);
}
[Theory]
[InlineData(0)]
[InlineData(FeedbackScreenshotRules.MaxScreenshotBytes + 1)]
public void Screenshot_size_rejects_empty_and_oversized_files(long sizeBytes)
{
bool allowed = FeedbackScreenshotRules.IsAllowedSize(sizeBytes);
Assert.False(allowed);
}
[Fact]
public void NormalizeTags_trims_deduplicates_and_orders()
{
IReadOnlyCollection<string> tags = FeedbackRules.NormalizeTags([" mobile ", "bug", "Mobile", ""]);
Assert.Equal(["bug", "mobile"], tags);
}
}