Refactored to not use static variables.

This commit is contained in:
Joseph Milazzo 2025-06-24 06:41:37 -05:00
parent c1471db264
commit 6364b0d010

View file

@ -14,36 +14,8 @@ namespace API.Tests.Repository;
public class TagRepositoryTests : AbstractDbTest public class TagRepositoryTests : AbstractDbTest
{ {
private static readonly Tag SharedSeriesChaptersTag = new TagBuilder("Shared Series Chapter Tag").Build();
private static readonly Tag SharedSeriesTag = new TagBuilder("Shared Series Tag").Build();
private static readonly Tag SharedChaptersTag = new TagBuilder("Shared Chapters Tag").Build();
private static readonly Tag Lib0SeriesChaptersTag = new TagBuilder("Lib0 Series Chapter Tag").Build();
private static readonly Tag Lib0SeriesTag = new TagBuilder("Lib0 Series Tag").Build();
private static readonly Tag Lib0ChaptersTag = new TagBuilder("Lib0 Chapters Tag").Build();
private static readonly Tag Lib1SeriesChaptersTag = new TagBuilder("Lib1 Series Chapter Tag").Build();
private static readonly Tag Lib1SeriesTag = new TagBuilder("Lib1 Series Tag").Build();
private static readonly Tag Lib1ChaptersTag = new TagBuilder("Lib1 Chapters Tag").Build();
private static readonly Tag Lib1ChapterAgeTag = new TagBuilder("Lib1 Chapter Age Tag").Build();
private static readonly List<Tag> AllTags =
[
SharedSeriesChaptersTag, SharedSeriesTag, SharedChaptersTag,
Lib0SeriesChaptersTag, Lib0SeriesTag, Lib0ChaptersTag,
Lib1SeriesChaptersTag, Lib1SeriesTag, Lib1ChaptersTag, Lib1ChapterAgeTag
];
/**
* Access to lib0, lib1
*/
private AppUser _fullAccess; private AppUser _fullAccess;
/**
* Access to lib1
*/
private AppUser _restrictedAccess; private AppUser _restrictedAccess;
/**
* Access to lib1, and Teen
*/
private AppUser _restrictedAgeAccess; private AppUser _restrictedAgeAccess;
protected override async Task ResetDb() protected override async Task ResetDb()
@ -53,9 +25,33 @@ public class TagRepositoryTests : AbstractDbTest
await Context.SaveChangesAsync(); await Context.SaveChangesAsync();
} }
private async Task SeedDb() private TestTagSet CreateTestTags()
{
return new TestTagSet
{
SharedSeriesChaptersTag = new TagBuilder("Shared Series Chapter Tag").Build(),
SharedSeriesTag = new TagBuilder("Shared Series Tag").Build(),
SharedChaptersTag = new TagBuilder("Shared Chapters Tag").Build(),
Lib0SeriesChaptersTag = new TagBuilder("Lib0 Series Chapter Tag").Build(),
Lib0SeriesTag = new TagBuilder("Lib0 Series Tag").Build(),
Lib0ChaptersTag = new TagBuilder("Lib0 Chapters Tag").Build(),
Lib1SeriesChaptersTag = new TagBuilder("Lib1 Series Chapter Tag").Build(),
Lib1SeriesTag = new TagBuilder("Lib1 Series Tag").Build(),
Lib1ChaptersTag = new TagBuilder("Lib1 Chapters Tag").Build(),
Lib1ChapterAgeTag = new TagBuilder("Lib1 Chapter Age Tag").Build()
};
}
private async Task SeedDbWithTags(TestTagSet tags)
{
await CreateTestUsers();
await AddTagsToContext(tags);
await CreateLibrariesWithTags(tags);
await AssignLibrariesToUsers();
}
private async Task CreateTestUsers()
{ {
// Create users with different access levels
_fullAccess = new AppUserBuilder("amelia", "amelia@example.com").Build(); _fullAccess = new AppUserBuilder("amelia", "amelia@example.com").Build();
_restrictedAccess = new AppUserBuilder("mila", "mila@example.com").Build(); _restrictedAccess = new AppUserBuilder("mila", "mila@example.com").Build();
_restrictedAgeAccess = new AppUserBuilder("eva", "eva@example.com").Build(); _restrictedAgeAccess = new AppUserBuilder("eva", "eva@example.com").Build();
@ -66,67 +62,75 @@ public class TagRepositoryTests : AbstractDbTest
Context.Users.Add(_restrictedAccess); Context.Users.Add(_restrictedAccess);
Context.Users.Add(_restrictedAgeAccess); Context.Users.Add(_restrictedAgeAccess);
await Context.SaveChangesAsync(); await Context.SaveChangesAsync();
}
Context.Tag.Add(SharedSeriesChaptersTag); private async Task AddTagsToContext(TestTagSet tags)
Context.Tag.Add(SharedSeriesTag); {
Context.Tag.Add(SharedChaptersTag); var allTags = tags.GetAllTags();
Context.Tag.Add(Lib0SeriesChaptersTag); Context.Tag.AddRange(allTags);
Context.Tag.Add(Lib0SeriesTag);
Context.Tag.Add(Lib0ChaptersTag);
Context.Tag.Add(Lib1SeriesChaptersTag);
Context.Tag.Add(Lib1SeriesTag);
Context.Tag.Add(Lib1ChaptersTag);
await Context.SaveChangesAsync(); await Context.SaveChangesAsync();
}
private async Task CreateLibrariesWithTags(TestTagSet tags)
{
var lib0 = new LibraryBuilder("lib0") var lib0 = new LibraryBuilder("lib0")
.WithSeries(new SeriesBuilder("lib0-s0") .WithSeries(new SeriesBuilder("lib0-s0")
.WithMetadata(new SeriesMetadata .WithMetadata(new SeriesMetadata
{ {
Tags = [SharedSeriesChaptersTag, SharedSeriesTag, Lib0SeriesChaptersTag, Lib0SeriesTag] Tags = [tags.SharedSeriesChaptersTag, tags.SharedSeriesTag, tags.Lib0SeriesChaptersTag, tags.Lib0SeriesTag]
}) })
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1") .WithChapter(new ChapterBuilder("1")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib0SeriesChaptersTag, Lib0ChaptersTag]) .WithTags([tags.SharedSeriesChaptersTag, tags.SharedChaptersTag, tags.Lib0SeriesChaptersTag, tags.Lib0ChaptersTag])
.Build()) .Build())
.WithChapter(new ChapterBuilder("2") .WithChapter(new ChapterBuilder("2")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib1SeriesChaptersTag, Lib1ChaptersTag]) .WithTags([tags.SharedSeriesChaptersTag, tags.SharedChaptersTag, tags.Lib1SeriesChaptersTag, tags.Lib1ChaptersTag])
.Build()) .Build())
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
var lib1 = new LibraryBuilder("lib1") var lib1 = new LibraryBuilder("lib1")
.WithSeries(new SeriesBuilder("lib1-s0") .WithSeries(new SeriesBuilder("lib1-s0")
.WithMetadata(new SeriesMetadataBuilder() .WithMetadata(new SeriesMetadataBuilder()
.WithTags([SharedSeriesChaptersTag, SharedSeriesTag, Lib1SeriesChaptersTag, Lib1SeriesTag]) .WithTags([tags.SharedSeriesChaptersTag, tags.SharedSeriesTag, tags.Lib1SeriesChaptersTag, tags.Lib1SeriesTag])
.WithAgeRating(AgeRating.Mature17Plus) .WithAgeRating(AgeRating.Mature17Plus)
.Build()) .Build())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1") .WithChapter(new ChapterBuilder("1")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib1SeriesChaptersTag, Lib1ChaptersTag]) .WithTags([tags.SharedSeriesChaptersTag, tags.SharedChaptersTag, tags.Lib1SeriesChaptersTag, tags.Lib1ChaptersTag])
.Build()) .Build())
.WithChapter(new ChapterBuilder("2") .WithChapter(new ChapterBuilder("2")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib1SeriesChaptersTag, Lib1ChaptersTag, Lib1ChapterAgeTag]) .WithTags([tags.SharedSeriesChaptersTag, tags.SharedChaptersTag, tags.Lib1SeriesChaptersTag, tags.Lib1ChaptersTag, tags.Lib1ChapterAgeTag])
.WithAgeRating(AgeRating.Mature17Plus) .WithAgeRating(AgeRating.Mature17Plus)
.Build()) .Build())
.Build()) .Build())
.Build()) .Build())
.WithSeries(new SeriesBuilder("lib1-s1") .WithSeries(new SeriesBuilder("lib1-s1")
.WithMetadata(new SeriesMetadataBuilder() .WithMetadata(new SeriesMetadataBuilder()
.WithTags([SharedSeriesChaptersTag, SharedSeriesTag, Lib1SeriesChaptersTag, Lib1SeriesTag]) .WithTags([tags.SharedSeriesChaptersTag, tags.SharedSeriesTag, tags.Lib1SeriesChaptersTag, tags.Lib1SeriesTag])
.Build()) .Build())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1") .WithChapter(new ChapterBuilder("1")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib1SeriesChaptersTag, Lib1ChaptersTag]) .WithTags([tags.SharedSeriesChaptersTag, tags.SharedChaptersTag, tags.Lib1SeriesChaptersTag, tags.Lib1ChaptersTag])
.Build()) .Build())
.WithChapter(new ChapterBuilder("2") .WithChapter(new ChapterBuilder("2")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib1SeriesChaptersTag, Lib1ChaptersTag]) .WithTags([tags.SharedSeriesChaptersTag, tags.SharedChaptersTag, tags.Lib1SeriesChaptersTag, tags.Lib1ChaptersTag])
.WithAgeRating(AgeRating.Mature17Plus) .WithAgeRating(AgeRating.Mature17Plus)
.Build()) .Build())
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
Context.Library.Add(lib0);
Context.Library.Add(lib1);
await Context.SaveChangesAsync(); await Context.SaveChangesAsync();
}
private async Task AssignLibrariesToUsers()
{
var lib0 = Context.Library.First(l => l.Name == "lib0");
var lib1 = Context.Library.First(l => l.Name == "lib1");
_fullAccess.Libraries.Add(lib0); _fullAccess.Libraries.Add(lib0);
_fullAccess.Libraries.Add(lib1); _fullAccess.Libraries.Add(lib1);
@ -136,70 +140,139 @@ public class TagRepositoryTests : AbstractDbTest
await Context.SaveChangesAsync(); await Context.SaveChangesAsync();
} }
private Predicate<BrowseTagDto> ContainsTagCheck(Tag tag) private static Predicate<BrowseTagDto> ContainsTagCheck(Tag tag)
{ {
return t => t.Id == tag.Id; return t => t.Id == tag.Id;
} }
[Fact] private static void AssertTagPresent(IEnumerable<BrowseTagDto> tags, Tag expectedTag)
public async Task GetBrowseableTag()
{ {
await ResetDb(); Assert.Contains(tags, ContainsTagCheck(expectedTag));
await SeedDb();
var fullAccessTags = await UnitOfWork.TagRepository.GetBrowseableTag(_fullAccess.Id, new UserParams());
Assert.Equal(AllTags.Count, fullAccessTags.TotalCount);
foreach (var tag in AllTags)
{
Assert.Contains(fullAccessTags, ContainsTagCheck(tag));
} }
// 1 series lib0, 2 series lib1 private static void AssertTagNotPresent(IEnumerable<BrowseTagDto> tags, Tag expectedTag)
Assert.Equal(3, fullAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).SeriesCount); {
Assert.Equal(6, fullAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount); Assert.DoesNotContain(tags, ContainsTagCheck(expectedTag));
Assert.Equal(1, fullAccessTags.First(dto => dto.Id == Lib0SeriesTag.Id).SeriesCount); }
private static BrowseTagDto GetTagDto(IEnumerable<BrowseTagDto> tags, Tag tag)
{
return tags.First(dto => dto.Id == tag.Id);
}
[Fact]
public async Task GetBrowseableTag_FullAccess_ReturnsAllTagsWithCorrectCounts()
{
// Arrange
await ResetDb();
var tags = CreateTestTags();
await SeedDbWithTags(tags);
// Act
var fullAccessTags = await UnitOfWork.TagRepository.GetBrowseableTag(_fullAccess.Id, new UserParams());
// Assert
Assert.Equal(tags.GetAllTags().Count, fullAccessTags.TotalCount);
foreach (var tag in tags.GetAllTags())
{
AssertTagPresent(fullAccessTags, tag);
}
// Verify counts - 1 series lib0, 2 series lib1 = 3 total series
Assert.Equal(3, GetTagDto(fullAccessTags, tags.SharedSeriesChaptersTag).SeriesCount);
Assert.Equal(6, GetTagDto(fullAccessTags, tags.SharedSeriesChaptersTag).ChapterCount);
Assert.Equal(1, GetTagDto(fullAccessTags, tags.Lib0SeriesTag).SeriesCount);
}
[Fact]
public async Task GetBrowseableTag_RestrictedAccess_ReturnsOnlyAccessibleTags()
{
// Arrange
await ResetDb();
var tags = CreateTestTags();
await SeedDbWithTags(tags);
// Act
var restrictedAccessTags = await UnitOfWork.TagRepository.GetBrowseableTag(_restrictedAccess.Id, new UserParams()); var restrictedAccessTags = await UnitOfWork.TagRepository.GetBrowseableTag(_restrictedAccess.Id, new UserParams());
// Should see: 3 shared + 4 library 1 specific = 7 tags // Assert - Should see: 3 shared + 4 library 1 specific = 7 tags
Assert.Equal(7, restrictedAccessTags.TotalCount); Assert.Equal(7, restrictedAccessTags.TotalCount);
// Verify Library 1 and shared tags are present // Verify shared and Library 1 tags are present
Assert.Contains(restrictedAccessTags, ContainsTagCheck(SharedSeriesChaptersTag)); AssertTagPresent(restrictedAccessTags, tags.SharedSeriesChaptersTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(SharedSeriesTag)); AssertTagPresent(restrictedAccessTags, tags.SharedSeriesTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(SharedChaptersTag)); AssertTagPresent(restrictedAccessTags, tags.SharedChaptersTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1SeriesChaptersTag)); AssertTagPresent(restrictedAccessTags, tags.Lib1SeriesChaptersTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1SeriesTag)); AssertTagPresent(restrictedAccessTags, tags.Lib1SeriesTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1ChaptersTag)); AssertTagPresent(restrictedAccessTags, tags.Lib1ChaptersTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1ChapterAgeTag)); AssertTagPresent(restrictedAccessTags, tags.Lib1ChapterAgeTag);
// Verify Count is correctly limited: 2 series lib1 // Verify Library 0 specific tags are not present
Assert.Equal(2, restrictedAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).SeriesCount); AssertTagNotPresent(restrictedAccessTags, tags.Lib0SeriesChaptersTag);
Assert.Equal(4, restrictedAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount); AssertTagNotPresent(restrictedAccessTags, tags.Lib0SeriesTag);
Assert.Equal(2, restrictedAccessTags.First(dto => dto.Id == Lib1SeriesTag.Id).SeriesCount); AssertTagNotPresent(restrictedAccessTags, tags.Lib0ChaptersTag);
Assert.Equal(4, restrictedAccessTags.First(dto => dto.Id == Lib1ChaptersTag.Id).ChapterCount);
// Verify counts - 2 series lib1
Assert.Equal(2, GetTagDto(restrictedAccessTags, tags.SharedSeriesChaptersTag).SeriesCount);
Assert.Equal(4, GetTagDto(restrictedAccessTags, tags.SharedSeriesChaptersTag).ChapterCount);
Assert.Equal(2, GetTagDto(restrictedAccessTags, tags.Lib1SeriesTag).SeriesCount);
Assert.Equal(4, GetTagDto(restrictedAccessTags, tags.Lib1ChaptersTag).ChapterCount);
}
[Fact]
public async Task GetBrowseableTag_RestrictedAgeAccess_FiltersAgeRestrictedContent()
{
// Arrange
await ResetDb();
var tags = CreateTestTags();
await SeedDbWithTags(tags);
// Act
var restrictedAgeAccessTags = await UnitOfWork.TagRepository.GetBrowseableTag(_restrictedAgeAccess.Id, new UserParams()); var restrictedAgeAccessTags = await UnitOfWork.TagRepository.GetBrowseableTag(_restrictedAgeAccess.Id, new UserParams());
// Should see: 3 shared + 3 lib1 specific = 6 tags // Assert - Should see: 3 shared + 3 lib1 specific = 6 tags (age-restricted tag filtered out)
Assert.Equal(6, restrictedAgeAccessTags.TotalCount); Assert.Equal(6, restrictedAgeAccessTags.TotalCount);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(SharedSeriesChaptersTag)); // Verify accessible tags are present
Assert.Contains(restrictedAccessTags, ContainsTagCheck(SharedSeriesTag)); AssertTagPresent(restrictedAgeAccessTags, tags.SharedSeriesChaptersTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(SharedChaptersTag)); AssertTagPresent(restrictedAgeAccessTags, tags.SharedSeriesTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1SeriesChaptersTag)); AssertTagPresent(restrictedAgeAccessTags, tags.SharedChaptersTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1SeriesTag)); AssertTagPresent(restrictedAgeAccessTags, tags.Lib1SeriesChaptersTag);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1ChaptersTag)); AssertTagPresent(restrictedAgeAccessTags, tags.Lib1SeriesTag);
AssertTagPresent(restrictedAgeAccessTags, tags.Lib1ChaptersTag);
Assert.DoesNotContain(restrictedAgeAccessTags, ContainsTagCheck(Lib1ChapterAgeTag)); // Verify age-restricted tag is filtered out
AssertTagNotPresent(restrictedAgeAccessTags, tags.Lib1ChapterAgeTag);
// Verify Count is correctly limited: 1 series lib1 // Verify counts - 1 series lib1 (age-restricted series filtered out)
Assert.Equal(1, restrictedAgeAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).SeriesCount); Assert.Equal(1, GetTagDto(restrictedAgeAccessTags, tags.SharedSeriesChaptersTag).SeriesCount);
Assert.Equal(2, restrictedAgeAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount); Assert.Equal(2, GetTagDto(restrictedAgeAccessTags, tags.SharedSeriesChaptersTag).ChapterCount);
Assert.Equal(1, restrictedAgeAccessTags.First(dto => dto.Id == Lib1SeriesTag.Id).SeriesCount); Assert.Equal(1, GetTagDto(restrictedAgeAccessTags, tags.Lib1SeriesTag).SeriesCount);
Assert.Equal(2, restrictedAgeAccessTags.First(dto => dto.Id == Lib1ChaptersTag.Id).ChapterCount); Assert.Equal(2, GetTagDto(restrictedAgeAccessTags, tags.Lib1ChaptersTag).ChapterCount);
}
private class TestTagSet
{
public Tag SharedSeriesChaptersTag { get; set; }
public Tag SharedSeriesTag { get; set; }
public Tag SharedChaptersTag { get; set; }
public Tag Lib0SeriesChaptersTag { get; set; }
public Tag Lib0SeriesTag { get; set; }
public Tag Lib0ChaptersTag { get; set; }
public Tag Lib1SeriesChaptersTag { get; set; }
public Tag Lib1SeriesTag { get; set; }
public Tag Lib1ChaptersTag { get; set; }
public Tag Lib1ChapterAgeTag { get; set; }
public List<Tag> GetAllTags()
{
return
[
SharedSeriesChaptersTag, SharedSeriesTag, SharedChaptersTag,
Lib0SeriesChaptersTag, Lib0SeriesTag, Lib0ChaptersTag,
Lib1SeriesChaptersTag, Lib1SeriesTag, Lib1ChaptersTag, Lib1ChapterAgeTag
];
}
} }
} }