189 lines
5.5 KiB
C#
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);
|
|
}
|
|
}
|