Get Person Count working correctly

Fix up some unit tests
This commit is contained in:
Amelia 2025-06-22 21:12:14 +02:00
parent 578c8b1e56
commit 8bc792e64a
5 changed files with 147 additions and 82 deletions

View file

@ -61,10 +61,9 @@ public class GenreRepositoryTests : AbstractDbTest
var lib0 = new LibraryBuilder("lib0")
.WithSeries(new SeriesBuilder("lib0-s0")
.WithMetadata(new SeriesMetadata
{
Genres = [SharedSeriesChaptersGenre, SharedSeriesGenre, Lib0SeriesChaptersGenre, Lib0SeriesGenre]
})
.WithMetadata(new SeriesMetadataBuilder()
.WithGenres([SharedSeriesChaptersGenre, SharedSeriesGenre, Lib0SeriesChaptersGenre, Lib0SeriesGenre])
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1")
.WithGenres([SharedSeriesChaptersGenre, SharedChaptersGenre, Lib0SeriesChaptersGenre, Lib0ChaptersGenre])
@ -78,10 +77,10 @@ public class GenreRepositoryTests : AbstractDbTest
var lib1 = new LibraryBuilder("lib1")
.WithSeries(new SeriesBuilder("lib1-s0")
.WithMetadata(new SeriesMetadata
{
Genres = [SharedSeriesChaptersGenre, SharedSeriesGenre, Lib1SeriesChaptersGenre, Lib1SeriesGenre]
})
.WithMetadata(new SeriesMetadataBuilder()
.WithGenres([SharedSeriesChaptersGenre, SharedSeriesGenre, Lib1SeriesChaptersGenre, Lib1SeriesGenre])
.WithAgeRating(AgeRating.Mature17Plus)
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1")
.WithGenres([SharedSeriesChaptersGenre, SharedChaptersGenre, Lib1SeriesChaptersGenre, Lib1ChaptersGenre])
@ -92,6 +91,19 @@ public class GenreRepositoryTests : AbstractDbTest
.Build())
.Build())
.Build())
.WithSeries(new SeriesBuilder("lib1-s1")
.WithMetadata(new SeriesMetadataBuilder()
.WithGenres([SharedSeriesChaptersGenre, SharedSeriesGenre, Lib1SeriesChaptersGenre, Lib1SeriesGenre])
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1")
.WithGenres([SharedSeriesChaptersGenre, SharedChaptersGenre, Lib1SeriesChaptersGenre, Lib1ChaptersGenre])
.Build())
.WithChapter(new ChapterBuilder("2")
.WithGenres([SharedSeriesChaptersGenre, SharedChaptersGenre, Lib1SeriesChaptersGenre, Lib1ChaptersGenre])
.Build())
.Build())
.Build())
.Build();
await Context.SaveChangesAsync();
@ -122,8 +134,9 @@ public class GenreRepositoryTests : AbstractDbTest
Assert.Contains(fullAccessGenres, ContainsGenreCheck(genre));
}
Assert.Equal(2, fullAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).SeriesCount);
Assert.Equal(4, fullAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).ChapterCount);
// 1 lib0 series, 2 lib1 series
Assert.Equal(3, fullAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).SeriesCount);
Assert.Equal(6, fullAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).ChapterCount);
Assert.Equal(1, fullAccessGenres.First(dto => dto.Id == Lib0SeriesGenre.Id).SeriesCount);
@ -139,9 +152,12 @@ public class GenreRepositoryTests : AbstractDbTest
Assert.Contains(restrictedAccessGenres, ContainsGenreCheck(Lib1ChaptersGenre));
Assert.Contains(restrictedAccessGenres, ContainsGenreCheck(Lib1ChapterAgeGenre));
Assert.Equal(1, restrictedAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).SeriesCount);
Assert.Equal(2, restrictedAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).ChapterCount);
Assert.Equal(1, restrictedAccessGenres.First(dto => dto.Id == Lib1SeriesGenre.Id).SeriesCount);
// 2 lib1 series
Assert.Equal(2, restrictedAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).SeriesCount);
Assert.Equal(4, restrictedAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).ChapterCount);
Assert.Equal(2, restrictedAccessGenres.First(dto => dto.Id == Lib1SeriesGenre.Id).SeriesCount);
Assert.Equal(4, restrictedAccessGenres.First(dto => dto.Id == Lib1ChaptersGenre.Id).ChapterCount);
Assert.Equal(1, restrictedAccessGenres.First(dto => dto.Id == Lib1ChapterAgeGenre.Id).ChapterCount);
var restrictedAgeAccessGenres = await UnitOfWork.GenreRepository.GetBrowseableGenre(_restrictedAgeAccess.Id, new UserParams());
@ -157,7 +173,10 @@ public class GenreRepositoryTests : AbstractDbTest
Assert.DoesNotContain(restrictedAgeAccessGenres, ContainsGenreCheck(Lib1ChapterAgeGenre));
Assert.Equal(1, restrictedAgeAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).SeriesCount);
Assert.Equal(1, restrictedAgeAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).ChapterCount);
Assert.Equal(1, restrictedAgeAccessGenres.First(dto => dto.Id == Lib1SeriesGenre.Id).SeriesCount);
// These values are a "bug". And should be 2, however chapters are not filtered out when their series is
Assert.Equal(3, restrictedAgeAccessGenres.First(dto => dto.Id == SharedSeriesChaptersGenre.Id).ChapterCount);
Assert.Equal(3, restrictedAgeAccessGenres.First(dto => dto.Id == Lib1ChaptersGenre.Id).ChapterCount);
}
}

View file

@ -56,9 +56,9 @@ public class PersonRepositoryTests : AbstractDbTest
_restrictedAgeAccess.AgeRestriction = AgeRating.Teen;
_restrictedAgeAccess.AgeRestrictionIncludeUnknowns = true;
Context.Users.Add(_fullAccess);
Context.Users.Add(_restrictedAccess);
Context.Users.Add(_restrictedAgeAccess);
Context.AppUser.Add(_fullAccess);
Context.AppUser.Add(_restrictedAccess);
Context.AppUser.Add(_restrictedAgeAccess);
await Context.SaveChangesAsync();
Context.Person.AddRange(AllPeople);
@ -129,10 +129,10 @@ public class PersonRepositoryTests : AbstractDbTest
.WithPerson(Lib1ChaptersPerson, PersonRole.Team)
.Build())
.WithChapter(new ChapterBuilder("2")
.WithPerson(SharedSeriesChaptersPerson, PersonRole.Team)
.WithPerson(SharedChaptersPerson, PersonRole.Team)
.WithPerson(Lib1SeriesChaptersPerson, PersonRole.Team)
.WithPerson(Lib1ChaptersPerson, PersonRole.Team)
.WithPerson(SharedSeriesChaptersPerson, PersonRole.Translator)
.WithPerson(SharedChaptersPerson, PersonRole.Translator)
.WithPerson(Lib1SeriesChaptersPerson, PersonRole.Translator)
.WithPerson(Lib1ChaptersPerson, PersonRole.Translator)
.Build())
.Build())
.Build())
@ -186,19 +186,18 @@ public class PersonRepositoryTests : AbstractDbTest
Assert.Contains(restrictedAccessPeople, ContainsPersonCheck(Lib1ChaptersPerson));
Assert.Contains(restrictedAccessPeople, ContainsPersonCheck(Lib1ChapterAgePerson));
// Count is not working when restricted
//Assert.Equal(2, restrictedAccessPeople.First(dto => dto.Id == SharedSeriesChaptersPerson.Id).SeriesCount);
//Assert.Equal(4, restrictedAccessPeople.First(dto => dto.Id == SharedSeriesChaptersPerson.Id).ChapterCount);
//Assert.Equal(2, restrictedAccessPeople.First(dto => dto.Id == Lib1SeriesPerson.Id).SeriesCount);
Assert.Equal(2, restrictedAccessPeople.First(dto => dto.Id == SharedSeriesChaptersPerson.Id).SeriesCount);
Assert.Equal(4, restrictedAccessPeople.First(dto => dto.Id == SharedSeriesChaptersPerson.Id).ChapterCount);
Assert.Equal(2, restrictedAccessPeople.First(dto => dto.Id == Lib1SeriesPerson.Id).SeriesCount);
// Fails because of the chapter - series issue
/*var restrictedAgeAccessPeople = await UnitOfWork.PersonRepository.GetBrowsePersonDtos(_restrictedAgeAccess.Id,
var restrictedAgeAccessPeople = await UnitOfWork.PersonRepository.GetBrowsePersonDtos(_restrictedAgeAccess.Id,
new BrowsePersonFilterDto(), new UserParams());
Assert.Equal(0, restrictedAgeAccessPeople.TotalCount);
// Note: There is a potential bug here where a person in a different chapter of an age restricted series will show up
Assert.Equal(6, restrictedAgeAccessPeople.TotalCount);
foreach (var person in AllPeople) Assert.DoesNotContain(fullAccessPeople, ContainsPersonCheck(person));*/
Assert.DoesNotContain(restrictedAgeAccessPeople, ContainsPersonCheck(Lib1ChapterAgePerson));
}
[Fact]
@ -210,16 +209,16 @@ public class PersonRepositoryTests : AbstractDbTest
var sharedSeriesRoles = await UnitOfWork.PersonRepository.GetRolesForPersonByName(SharedSeriesPerson.Id, _fullAccess.Id);
var chapterRoles = await UnitOfWork.PersonRepository.GetRolesForPersonByName(SharedChaptersPerson.Id, _fullAccess.Id);
var ageChapterRoles = await UnitOfWork.PersonRepository.GetRolesForPersonByName(Lib1ChapterAgePerson.Id, _fullAccess.Id);
Assert.Equal(2, sharedSeriesRoles.Count());
Assert.Equal(4, chapterRoles.Count());
Assert.Equal(3, sharedSeriesRoles.Count());
Assert.Equal(6, chapterRoles.Count());
Assert.Single(ageChapterRoles);
var restrictedRoles = await UnitOfWork.PersonRepository.GetRolesForPersonByName(SharedSeriesPerson.Id, _restrictedAccess.Id);
var restrictedChapterRoles = await UnitOfWork.PersonRepository.GetRolesForPersonByName(SharedChaptersPerson.Id, _restrictedAccess.Id);
var restrictedAgePersonChapterRoles = await UnitOfWork.PersonRepository.GetRolesForPersonByName(Lib1ChapterAgePerson.Id, _restrictedAccess.Id);
Assert.Single(restrictedRoles);
Assert.Equal(2, restrictedChapterRoles.Count());
Assert.Equal(2, restrictedRoles.Count());
Assert.Equal(4, restrictedChapterRoles.Count());
Assert.Single(restrictedAgePersonChapterRoles);
var restrictedAgeRoles = await UnitOfWork.PersonRepository.GetRolesForPersonByName(SharedSeriesPerson.Id, _restrictedAgeAccess.Id);
@ -227,8 +226,7 @@ public class PersonRepositoryTests : AbstractDbTest
var restrictedAgeAgePersonChapterRoles = await UnitOfWork.PersonRepository.GetRolesForPersonByName(Lib1ChapterAgePerson.Id, _restrictedAgeAccess.Id);
Assert.Single(restrictedAgeRoles);
Assert.Equal(2, restrictedAgeChapterRoles.Count());
// This works because both series & chapter have the correct age rating. The series-chapter issue is possible here
// Just not int he example I worked out in this scenario
// Note: There is a potential bug here where a person in a different chapter of an age restricted series will show up
Assert.Empty(restrictedAgeAgePersonChapterRoles);
}
@ -247,10 +245,9 @@ public class PersonRepositoryTests : AbstractDbTest
Assert.NotNull(await UnitOfWork.PersonRepository.GetPersonDtoByName(SharedSeriesPerson.Name, _restrictedAccess.Id));
Assert.NotNull(await UnitOfWork.PersonRepository.GetPersonDtoByName(Lib1SeriesPerson.Name, _restrictedAccess.Id));
// NOTE: The commend out Asserts fail because the chapter - series issue
Assert.Null(await UnitOfWork.PersonRepository.GetPersonDtoByName(Lib0ChaptersPerson.Name, _restrictedAgeAccess.Id));
//Assert.Null(await UnitOfWork.PersonRepository.GetPersonDtoByName(SharedSeriesPerson.Name, _restrictedAgeAccess.Id));
//Assert.Null(await UnitOfWork.PersonRepository.GetPersonDtoByName(Lib1SeriesPerson.Name, _restrictedAgeAccess.Id));
Assert.NotNull(await UnitOfWork.PersonRepository.GetPersonDtoByName(Lib1SeriesPerson.Name, _restrictedAgeAccess.Id));
// Note: There is a potential bug here where a person in a different chapter of an age restricted series will show up
Assert.Null(await UnitOfWork.PersonRepository.GetPersonDtoByName(Lib1ChapterAgePerson.Name, _restrictedAgeAccess.Id));
}
@ -293,14 +290,14 @@ public class PersonRepositoryTests : AbstractDbTest
restrictedAgeChapters = await UnitOfWork.PersonRepository.GetChaptersForPersonByRole(SharedChaptersPerson.Id, _restrictedAgeAccess.Id, PersonRole.Imprint);
Assert.Single(chapters);
Assert.Single(restrictedChapters);
//Assert.Empty(restrictedAgeChapters); This passed because of the series-chapter issue. The user cannot see the series, but can see this chapter
Assert.Empty(restrictedAgeChapters);
// Lib1 - not age restricted
chapters = await UnitOfWork.PersonRepository.GetChaptersForPersonByRole(SharedChaptersPerson.Id, _fullAccess.Id, PersonRole.Team);
restrictedChapters = await UnitOfWork.PersonRepository.GetChaptersForPersonByRole(SharedChaptersPerson.Id, _restrictedAccess.Id, PersonRole.Team);
restrictedAgeChapters = await UnitOfWork.PersonRepository.GetChaptersForPersonByRole(SharedChaptersPerson.Id, _restrictedAgeAccess.Id, PersonRole.Team);
Assert.Equal(2, chapters.Count());
Assert.Equal(2, restrictedChapters.Count());
Assert.Equal(2, restrictedAgeChapters.Count());
Assert.Single(chapters);
Assert.Single(restrictedChapters);
Assert.Single(restrictedAgeChapters);
}
}

View file

@ -96,10 +96,10 @@ public class TagRepositoryTests : AbstractDbTest
.Build();
var lib1 = new LibraryBuilder("lib1")
.WithSeries(new SeriesBuilder("lib1-s0")
.WithMetadata(new SeriesMetadata
{
Tags = [SharedSeriesChaptersTag, SharedSeriesTag, Lib1SeriesChaptersTag, Lib1SeriesTag]
})
.WithMetadata(new SeriesMetadataBuilder()
.WithTags([SharedSeriesChaptersTag, SharedSeriesTag, Lib1SeriesChaptersTag, Lib1SeriesTag])
.WithAgeRating(AgeRating.Mature17Plus)
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib1SeriesChaptersTag, Lib1ChaptersTag])
@ -110,6 +110,20 @@ public class TagRepositoryTests : AbstractDbTest
.Build())
.Build())
.Build())
.WithSeries(new SeriesBuilder("lib1-s1")
.WithMetadata(new SeriesMetadataBuilder()
.WithTags([SharedSeriesChaptersTag, SharedSeriesTag, Lib1SeriesChaptersTag, Lib1SeriesTag])
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib1SeriesChaptersTag, Lib1ChaptersTag])
.Build())
.WithChapter(new ChapterBuilder("2")
.WithTags([SharedSeriesChaptersTag, SharedChaptersTag, Lib1SeriesChaptersTag, Lib1ChaptersTag])
.WithAgeRating(AgeRating.Mature17Plus)
.Build())
.Build())
.Build())
.Build();
await Context.SaveChangesAsync();
@ -140,8 +154,9 @@ public class TagRepositoryTests : AbstractDbTest
Assert.Contains(fullAccessTags, ContainsTagCheck(tag));
}
Assert.Equal(2, fullAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).SeriesCount);
Assert.Equal(4, fullAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount);
// 1 series lib0, 2 series lib1
Assert.Equal(3, fullAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).SeriesCount);
Assert.Equal(6, fullAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount);
Assert.Equal(1, fullAccessTags.First(dto => dto.Id == Lib0SeriesTag.Id).SeriesCount);
@ -159,15 +174,16 @@ public class TagRepositoryTests : AbstractDbTest
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1ChaptersTag));
Assert.Contains(restrictedAccessTags, ContainsTagCheck(Lib1ChapterAgeTag));
// Verify Count is correctly limited
Assert.Equal(1, restrictedAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).SeriesCount);
Assert.Equal(2, restrictedAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount);
Assert.Equal(1, restrictedAccessTags.First(dto => dto.Id == Lib1SeriesTag.Id).SeriesCount);
// Verify Count is correctly limited: 2 series lib1
Assert.Equal(2, restrictedAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).SeriesCount);
Assert.Equal(4, restrictedAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount);
Assert.Equal(2, restrictedAccessTags.First(dto => dto.Id == Lib1SeriesTag.Id).SeriesCount);
Assert.Equal(4, restrictedAccessTags.First(dto => dto.Id == Lib1ChaptersTag.Id).ChapterCount);
var restrictedAgeAccessTags = await UnitOfWork.TagRepository.GetBrowseableTag(_restrictedAgeAccess.Id, new UserParams());
// Should see: 3 shared + 3 library 1 specific = 6 tags
// Should see: 3 shared + 3 lib1 specific = 6 tags
Assert.Equal(6, restrictedAgeAccessTags.TotalCount);
Assert.Contains(restrictedAccessTags, ContainsTagCheck(SharedSeriesChaptersTag));
@ -179,12 +195,11 @@ public class TagRepositoryTests : AbstractDbTest
Assert.DoesNotContain(restrictedAgeAccessTags, ContainsTagCheck(Lib1ChapterAgeTag));
// Verify Count is correctly limited
// Verify Count is correctly limited: 1 series lib1
Assert.Equal(1, restrictedAgeAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).SeriesCount);
Assert.Equal(1, restrictedAgeAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount);
Assert.Equal(2, restrictedAgeAccessTags.First(dto => dto.Id == SharedSeriesChaptersTag.Id).ChapterCount);
Assert.Equal(1, restrictedAgeAccessTags.First(dto => dto.Id == Lib1SeriesTag.Id).SeriesCount);
Assert.Equal(2, restrictedAgeAccessTags.First(dto => dto.Id == Lib1ChaptersTag.Id).ChapterCount);
}
}

View file

@ -218,8 +218,10 @@ public class PersonRepository : IPersonRepository
{
var libs = await _context.Library.Includes(LibraryIncludes.AppUser).ToListAsync();
var libIds = libs.Select(l => l.Id).ToList();
var userLibs = libs.Where(lib => lib.AppUsers.Any(user => user.Id == userId))
.Select(lib => lib.Id).ToList();
var userLibs = libs.Where(lib => lib.AppUsers.Any(user => user.Id == userId)).Select(lib => lib.Id).ToList();
var shouldLibRestrict = libIds.Count != userLibs.Count;
var seriesIds = await _context.Series.Where(s => userLibs.Contains(s.LibraryId)).Select(s => s.Id).ToListAsync();
var query = _context.Person.AsNoTracking();
@ -228,36 +230,61 @@ public class PersonRepository : IPersonRepository
// Apply restrictions
query = query.RestrictAgainstAgeRestriction(ageRating);
query = query.RestrictByLibrary(userLibs, libIds);
if (shouldLibRestrict)
{
query = query.Where(p => p.ChapterPeople.Any(cp => seriesIds.Contains(cp.Chapter.Volume.SeriesId)) ||
p.SeriesMetadataPeople.Any(smp => seriesIds.Contains(smp.SeriesMetadata.SeriesId)));
}
// Apply sorting and limiting
var sortedQuery = query.SortBy(filter.SortOptions);
var limitedQuery = ApplyPersonLimit(sortedQuery, filter.LimitTo);
// I cannot get the counting to work without errors...
// Project to DTO
var projectedQuery = limitedQuery.Select(p => new BrowsePersonDto
IQueryable<BrowsePersonDto> projectedQuery;
if (shouldLibRestrict)
{
Id = p.Id,
Name = p.Name,
Description = p.Description,
CoverImage = p.CoverImage,
SeriesCount = p.SeriesMetadataPeople
.Select(smp => smp.SeriesMetadata)
//.RestrictByLibrary(userLibs, libIds)
//.RestrictAgainstAgeRestriction(ageRating)
.Select(smp => smp.SeriesId)
.Distinct()
.Count(),
ChapterCount = p.ChapterPeople
.Select(chp => chp.Chapter)
//.RestrictByLibrary(userLibs, libIds)
//.RestrictAgainstAgeRestriction(ageRating)
.Select(cp => cp.Id)
.Distinct()
.Count()
});
projectedQuery = limitedQuery.Select(p => new BrowsePersonDto
{
Id = p.Id,
Name = p.Name,
Description = p.Description,
CoverImage = p.CoverImage,
SeriesCount = p.SeriesMetadataPeople
.Select(smp => smp.SeriesMetadata)
.Where(sm => seriesIds.Contains(sm.SeriesId))
.RestrictAgainstAgeRestriction(ageRating)
.Distinct()
.Count(),
ChapterCount = p.ChapterPeople
.Select(chp => chp.Chapter)
.Where(ch => seriesIds.Contains(ch.Volume.SeriesId))
.RestrictAgainstAgeRestriction(ageRating)
.Distinct()
.Count()
});
}
else
{
projectedQuery = limitedQuery.Select(p => new BrowsePersonDto
{
Id = p.Id,
Name = p.Name,
Description = p.Description,
CoverImage = p.CoverImage,
SeriesCount = p.SeriesMetadataPeople
.Select(smp => smp.SeriesMetadata)
.RestrictAgainstAgeRestriction(ageRating)
.Distinct()
.Count(),
ChapterCount = p.ChapterPeople
.Select(chp => chp.Chapter)
.RestrictAgainstAgeRestriction(ageRating)
.Distinct()
.Count()
});
}
return projectedQuery;
}

View file

@ -108,4 +108,11 @@ public class SeriesMetadataBuilder : IEntityBuilder<SeriesMetadata>
_seriesMetadata.TagsLocked = lockStatus;
return this;
}
public SeriesMetadataBuilder WithTags(List<Tag> tags, bool lockStatus = false)
{
_seriesMetadata.Tags = tags;
_seriesMetadata.TagsLocked = lockStatus;
return this;
}
}