.NET 7 + Spring Cleaning (#1677)

* Updated to net7.0

* Updated GA to .net 7

* Updated System.IO.Abstractions to use New factory.

* Converted Regex into SourceGenerator in Parser.

* Updated more regex to source generators.

* Enabled Nullability and more regex changes throughout codebase.

* Parser is 100% GeneratedRegexified

* Lots of nullability code

* Enabled nullability for all repositories.

* Fixed another unit test

* Refactored some code around and took care of some todos.

* Updating code for nullability and cleaning up methods that aren't used anymore. Refctored all uses of Parser.Normalize() to use new extension

* More nullability exercises. 500 warnings to go.

* Fixed a bug where custom file uploads for entities wouldn't save in webP.

* Nullability is done for all DTOs

* Fixed all unit tests and nullability for the project. Only OPDS is left which will be done with an upcoming OPDS enhancement.

* Use localization in book service after validating

* Code smells

* Switched to preview build of swashbuckle for .net7 support

* Fixed up merge issues

* Disable emulate comic book when on single page reader

* Fixed a regression where double page renderer wouldn't layout the images correctly

* Updated to swashbuckle which support .net 7

* Fixed a bad GA action

* Some code cleanup

* More code smells

* Took care of most of nullable issues

* Fixed a broken test due to having more than one test run in parallel

* I'm really not sure why the unit tests are failing or are so extremely slow on .net 7

* Updated all dependencies

* Fixed up build and removed hardcoded framework from build scripts. (this merge removes Regex Source generators). Unit tests are completely busted.

* Unit tests and code cleanup. Needs shakeout now.

* Adjusted Series model since a few fields are not-nullable. Removed dead imports on the project.

* Refactored to use Builder pattern for all unit tests.

* Switched nullability down to warnings. It wasn't possible to switch due to constraint issues in DB Migration.
This commit is contained in:
Joe Milazzo 2023-03-05 14:55:13 -06:00 committed by GitHub
parent 76fe3fd64a
commit 5d1dd7b3f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
283 changed files with 4221 additions and 4593 deletions

View file

@ -1,39 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.10" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="NSubstitute" Version="4.4.0" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="17.2.3" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="19.2.1" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PackageReference Include="coverlet.collector" Version="3.2.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\API\API.csproj" />
<ProjectReference Include="..\API\API.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Services\Test Data\ArchiveService\ComicInfos" />
<Folder Include="Services\Test Data\ScannerService\Manga" />
<Folder Include="Services\Test Data\ArchiveService\ComicInfos" />
<Folder Include="Services\Test Data\ScannerService\Manga" />
</ItemGroup>
<ItemGroup>
<None Remove="Extensions\Test Data\modified on run.txt" />
<None Remove="Extensions\Test Data\modified on run.txt" />
</ItemGroup>
</Project>

View file

@ -29,6 +29,7 @@ public abstract class AbstractDbTest
protected const string BackupDirectory = "C:/kavita/config/backups/";
protected const string LogDirectory = "C:/kavita/config/logs/";
protected const string BookmarkDirectory = "C:/kavita/config/bookmarks/";
protected const string SiteThemeDirectory = "C:/kavita/config/themes/";
protected const string TempDirectory = "C:/kavita/config/temp/";
protected const string DataDirectory = "C:/data/";
@ -103,6 +104,7 @@ public abstract class AbstractDbTest
fileSystem.AddDirectory(CoverImageDirectory);
fileSystem.AddDirectory(BackupDirectory);
fileSystem.AddDirectory(BookmarkDirectory);
fileSystem.AddDirectory(SiteThemeDirectory);
fileSystem.AddDirectory(LogDirectory);
fileSystem.AddDirectory(TempDirectory);
fileSystem.AddDirectory(DataDirectory);

View file

@ -1,4 +1,5 @@
using API.Data;
using API.Extensions;
using Xunit;
namespace API.Tests.Entities;
@ -12,7 +13,7 @@ public class SeriesTest
[InlineData("Darker than Black")]
public void CreateSeries(string name)
{
var key = API.Services.Tasks.Scanner.Parser.Parser.Normalize(name);
var key = name.ToNormalized();
var series = DbFactory.Series(name);
Assert.Equal(0, series.Id);
Assert.Equal(0, series.Pages);

View file

@ -27,7 +27,7 @@ public class ParserInfoListExtensions
[InlineData(new[] {"1", "1", "3-5", "5", "8", "0", "0"}, new[] {"1", "3-5", "5", "8", "0"})]
public void DistinctVolumesTest(string[] volumeNumbers, string[] expectedNumbers)
{
var infos = volumeNumbers.Select(n => new ParserInfo() {Volumes = n}).ToList();
var infos = volumeNumbers.Select(n => new ParserInfo() {Series = "", Volumes = n}).ToList();
Assert.Equal(expectedNumbers, infos.DistinctVolumes());
}

View file

@ -1,10 +1,12 @@
using System.Collections.Generic;
using System.Linq;
using API.Data;
using API.Data.Misc;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Tests.Helpers.Builders;
using Xunit;
namespace API.Tests.Extensions;
@ -18,27 +20,24 @@ public class QueryableExtensionsTests
{
var items = new List<Series>()
{
new Series()
{
Metadata = new SeriesMetadata()
new SeriesBuilder("Test 1")
.WithMetadata( new SeriesMetadata()
{
AgeRating = AgeRating.Teen,
}
},
new Series()
{
Metadata = new SeriesMetadata()
})
.Build(),
new SeriesBuilder("Test 2")
.WithMetadata( new SeriesMetadata()
{
AgeRating = AgeRating.Unknown,
}
},
new Series()
{
Metadata = new SeriesMetadata()
})
.Build(),
new SeriesBuilder("Test 3")
.WithMetadata( new SeriesMetadata()
{
AgeRating = AgeRating.X18Plus,
}
},
})
.Build()
};
var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction()
@ -58,6 +57,8 @@ public class QueryableExtensionsTests
{
new CollectionTag()
{
Title = "Test",
NormalizedTitle = "Test".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -68,6 +69,8 @@ public class QueryableExtensionsTests
},
new CollectionTag()
{
Title = "Test",
NormalizedTitle = "Test".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -82,6 +85,8 @@ public class QueryableExtensionsTests
},
new CollectionTag()
{
Title = "Test",
NormalizedTitle = "Test".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -109,6 +114,8 @@ public class QueryableExtensionsTests
{
new Genre()
{
Title = "A",
NormalizedTitle = "A".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -119,6 +126,8 @@ public class QueryableExtensionsTests
},
new Genre()
{
Title = "B",
NormalizedTitle = "B".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -133,6 +142,8 @@ public class QueryableExtensionsTests
},
new Genre()
{
Title = "C",
NormalizedTitle = "C".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -160,6 +171,8 @@ public class QueryableExtensionsTests
{
new Tag()
{
Title = "Test 1",
NormalizedTitle = "Test 1".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -170,6 +183,8 @@ public class QueryableExtensionsTests
},
new Tag()
{
Title = "Test 2",
NormalizedTitle = "Test 2".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -184,6 +199,8 @@ public class QueryableExtensionsTests
},
new Tag()
{
Title = "Test 3",
NormalizedTitle = "Test 3".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
@ -258,20 +275,12 @@ public class QueryableExtensionsTests
[InlineData(false, 1)]
public void RestrictAgainstAgeRestriction_ReadingList_ShouldRestrictEverythingAboveTeen(bool includeUnknowns, int expectedCount)
{
var items = new List<ReadingList>()
{
new ReadingList()
{
AgeRating = AgeRating.Teen,
},
new ReadingList()
{
AgeRating = AgeRating.Unknown,
},
new ReadingList()
{
AgeRating = AgeRating.X18Plus
},
DbFactory.ReadingList("Test List", null, false, AgeRating.Teen),
DbFactory.ReadingList("Test List", null, false, AgeRating.Unknown),
DbFactory.ReadingList("Test List", null, false, AgeRating.X18Plus),
};
var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction()

View file

@ -3,124 +3,31 @@ using System.Linq;
using API.Comparators;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Parser;
using API.Services.Tasks.Scanner;
using API.Tests.Helpers.Builders;
using Xunit;
namespace API.Tests.Extensions;
public class SeriesExtensionsTests
{
[Theory]
[InlineData(new [] {"Darker than Black", "Darker Than Black", "Darker than Black"}, new [] {"Darker than Black"}, true)]
[InlineData(new [] {"Darker than Black", "Darker Than Black", "Darker than Black"}, new [] {"Darker_than_Black"}, true)]
[InlineData(new [] {"Darker than Black", "Darker Than Black", "Darker than Black"}, new [] {"Darker then Black!"}, false)]
[InlineData(new [] {"Salem's Lot", "Salem's Lot", "Salem's Lot"}, new [] {"Salem's Lot"}, true)]
[InlineData(new [] {"Salem's Lot", "Salem's Lot", "Salem's Lot"}, new [] {"salems lot"}, true)]
[InlineData(new [] {"Salem's Lot", "Salem's Lot", "Salem's Lot"}, new [] {"salem's lot"}, true)]
// Different normalizations pass as we check normalization against an on-the-fly calculation so we don't delete series just because we change how normalization works
[InlineData(new [] {"Salem's Lot", "Salem's Lot", "Salem's Lot", "salems lot"}, new [] {"salem's lot"}, true)]
[InlineData(new [] {"Rent-a-Girlfriend", "Rent-a-Girlfriend", "Kanojo, Okarishimasu", "rentagirlfriend"}, new [] {"Kanojo, Okarishimasu"}, true)]
public void NameInListTest(string[] seriesInput, string[] list, bool expected)
{
var series = new Series()
{
Name = seriesInput[0],
LocalizedName = seriesInput[1],
OriginalName = seriesInput[2],
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Services.Tasks.Scanner.Parser.Parser.Normalize(seriesInput[0]),
Metadata = new SeriesMetadata()
};
Assert.Equal(expected, series.NameInList(list));
}
[Theory]
[InlineData(new [] {"Darker than Black", "Darker Than Black", "Darker than Black"}, new [] {"Darker than Black"}, MangaFormat.Archive, true)]
[InlineData(new [] {"Darker than Black", "Darker Than Black", "Darker than Black"}, new [] {"Darker_than_Black"}, MangaFormat.Archive, true)]
[InlineData(new [] {"Darker than Black", "Darker Than Black", "Darker than Black"}, new [] {"Darker then Black!"}, MangaFormat.Archive, false)]
[InlineData(new [] {"Salem's Lot", "Salem's Lot", "Salem's Lot"}, new [] {"Salem's Lot"}, MangaFormat.Archive, true)]
[InlineData(new [] {"Salem's Lot", "Salem's Lot", "Salem's Lot"}, new [] {"salems lot"}, MangaFormat.Archive, true)]
[InlineData(new [] {"Salem's Lot", "Salem's Lot", "Salem's Lot"}, new [] {"salem's lot"}, MangaFormat.Archive, true)]
// Different normalizations pass as we check normalization against an on-the-fly calculation so we don't delete series just because we change how normalization works
[InlineData(new [] {"Salem's Lot", "Salem's Lot", "Salem's Lot", "salems lot"}, new [] {"salem's lot"}, MangaFormat.Archive, true)]
[InlineData(new [] {"Rent-a-Girlfriend", "Rent-a-Girlfriend", "Kanojo, Okarishimasu", "rentagirlfriend"}, new [] {"Kanojo, Okarishimasu"}, MangaFormat.Archive, true)]
public void NameInListParserInfoTest(string[] seriesInput, string[] list, MangaFormat format, bool expected)
{
var series = new Series()
{
Name = seriesInput[0],
LocalizedName = seriesInput[1],
OriginalName = seriesInput[2],
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Services.Tasks.Scanner.Parser.Parser.Normalize(seriesInput[0]),
Metadata = new SeriesMetadata(),
};
var parserInfos = list.Select(s => new ParsedSeries()
{
Name = s,
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize(s),
}).ToList();
// This doesn't do any checks against format
Assert.Equal(expected, series.NameInList(parserInfos));
}
[Theory]
[InlineData(new [] {"Darker than Black", "Darker Than Black", "Darker than Black"}, "Darker than Black", true)]
[InlineData(new [] {"Rent-a-Girlfriend", "Rent-a-Girlfriend", "Kanojo, Okarishimasu", "rentagirlfriend"}, "Kanojo, Okarishimasu", true)]
[InlineData(new [] {"Rent-a-Girlfriend", "Rent-a-Girlfriend", "Kanojo, Okarishimasu", "rentagirlfriend"}, "Rent", false)]
public void NameInParserInfoTest(string[] seriesInput, string parserSeries, bool expected)
{
var series = new Series()
{
Name = seriesInput[0],
LocalizedName = seriesInput[1],
OriginalName = seriesInput[2],
NormalizedName = seriesInput.Length == 4 ? seriesInput[3] : API.Services.Tasks.Scanner.Parser.Parser.Normalize(seriesInput[0]),
Metadata = new SeriesMetadata()
};
var info = new ParserInfo
{
Series = parserSeries
};
Assert.Equal(expected, series.NameInParserInfo(info));
}
[Fact]
public void GetCoverImage_MultipleSpecials_Comics()
{
var series = new Series()
{
Format = MangaFormat.Archive,
Volumes = new List<Volume>()
{
new Volume()
{
Number = 0,
Name = API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume,
Chapters = new List<Chapter>()
{
new Chapter()
{
IsSpecial = true,
Number = API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter,
CoverImage = "Special 1",
},
new Chapter()
{
IsSpecial = true,
Number = API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter,
CoverImage = "Special 2",
}
},
}
}
};
var series = new SeriesBuilder("Test 1")
.WithFormat(MangaFormat.Archive)
.WithVolume(new VolumeBuilder("0")
.WithName(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
.WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter)
.WithCoverImage("Special 1")
.WithIsSpecial(true)
.Build())
.WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter)
.WithCoverImage("Special 2")
.WithIsSpecial(true)
.Build())
.Build())
.Build();
Assert.Equal("Special 1", series.GetCoverImage());
@ -129,33 +36,20 @@ public class SeriesExtensionsTests
[Fact]
public void GetCoverImage_MultipleSpecials_Books()
{
var series = new Series()
{
Format = MangaFormat.Epub,
Volumes = new List<Volume>()
{
new Volume()
{
Number = 0,
Name = API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume,
Chapters = new List<Chapter>()
{
new Chapter()
{
IsSpecial = true,
Number = API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter,
CoverImage = "Special 1",
},
new Chapter()
{
IsSpecial = true,
Number = API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter,
CoverImage = "Special 2",
}
},
}
}
};
var series = new SeriesBuilder("Test 1")
.WithFormat(MangaFormat.Archive)
.WithVolume(new VolumeBuilder("0")
.WithName(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
.WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter)
.WithCoverImage("Special 1")
.WithIsSpecial(true)
.Build())
.WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter)
.WithCoverImage("Special 2")
.WithIsSpecial(true)
.Build())
.Build())
.Build();
Assert.Equal("Special 1", series.GetCoverImage());
}
@ -163,33 +57,20 @@ public class SeriesExtensionsTests
[Fact]
public void GetCoverImage_JustChapters_Comics()
{
var series = new Series()
{
Format = MangaFormat.Archive,
Volumes = new List<Volume>()
{
new Volume()
{
Number = 0,
Name = API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume,
Chapters = new List<Chapter>()
{
new Chapter()
{
IsSpecial = false,
Number = "2.5",
CoverImage = "Special 1",
},
new Chapter()
{
IsSpecial = false,
Number = "2",
CoverImage = "Special 2",
}
},
}
}
};
var series = new SeriesBuilder("Test 1")
.WithFormat(MangaFormat.Archive)
.WithVolume(new VolumeBuilder("0")
.WithName(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
.WithChapter(new ChapterBuilder("2.5")
.WithIsSpecial(false)
.WithCoverImage("Special 1")
.Build())
.WithChapter(new ChapterBuilder("2")
.WithIsSpecial(false)
.WithCoverImage("Special 2")
.Build())
.Build())
.Build();
foreach (var vol in series.Volumes)
{
@ -202,39 +83,24 @@ public class SeriesExtensionsTests
[Fact]
public void GetCoverImage_JustChaptersAndSpecials_Comics()
{
var series = new Series()
{
Format = MangaFormat.Archive,
Volumes = new List<Volume>()
{
new Volume()
{
Number = 0,
Name = API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume,
Chapters = new List<Chapter>()
{
new Chapter()
{
IsSpecial = false,
Number = "2.5",
CoverImage = "Special 1",
},
new Chapter()
{
IsSpecial = false,
Number = "2",
CoverImage = "Special 2",
},
new Chapter()
{
IsSpecial = true,
Number = API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter,
CoverImage = "Special 3",
}
},
}
}
};
var series = new SeriesBuilder("Test 1")
.WithFormat(MangaFormat.Archive)
.WithVolume(new VolumeBuilder("0")
.WithName(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
.WithChapter(new ChapterBuilder("2.5")
.WithIsSpecial(false)
.WithCoverImage("Special 1")
.Build())
.WithChapter(new ChapterBuilder("2")
.WithIsSpecial(false)
.WithCoverImage("Special 2")
.Build())
.WithChapter(new ChapterBuilder("0")
.WithIsSpecial(true)
.WithCoverImage("Special 3")
.Build())
.Build())
.Build();
foreach (var vol in series.Volumes)
{
@ -247,54 +113,31 @@ public class SeriesExtensionsTests
[Fact]
public void GetCoverImage_VolumesChapters_Comics()
{
var series = new Series()
{
Format = MangaFormat.Archive,
Volumes = new List<Volume>()
{
new Volume()
{
Number = 0,
Name = API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume,
Chapters = new List<Chapter>()
{
new Chapter()
{
IsSpecial = false,
Number = "2.5",
CoverImage = "Special 1",
},
new Chapter()
{
IsSpecial = false,
Number = "2",
CoverImage = "Special 2",
},
new Chapter()
{
IsSpecial = true,
Number = API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter,
CoverImage = "Special 3",
}
},
},
new Volume()
{
Number = 1,
Name = "1",
Chapters = new List<Chapter>()
{
new Chapter()
{
IsSpecial = false,
Number = "0",
CoverImage = "Volume 1",
},
},
}
}
};
var series = new SeriesBuilder("Test 1")
.WithFormat(MangaFormat.Archive)
.WithVolume(new VolumeBuilder("0")
.WithName(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
.WithChapter(new ChapterBuilder("2.5")
.WithIsSpecial(false)
.WithCoverImage("Special 1")
.Build())
.WithChapter(new ChapterBuilder("2")
.WithIsSpecial(false)
.WithCoverImage("Special 2")
.Build())
.WithChapter(new ChapterBuilder("0")
.WithIsSpecial(true)
.WithCoverImage("Special 3")
.Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithNumber(1)
.WithChapter(new ChapterBuilder("0")
.WithIsSpecial(false)
.WithCoverImage("Volume 1")
.Build())
.Build())
.Build();
foreach (var vol in series.Volumes)
{
@ -307,54 +150,31 @@ public class SeriesExtensionsTests
[Fact]
public void GetCoverImage_VolumesChaptersAndSpecials_Comics()
{
var series = new Series()
{
Format = MangaFormat.Archive,
Volumes = new List<Volume>()
{
new Volume()
{
Number = 0,
Name = API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume,
Chapters = new List<Chapter>()
{
new Chapter()
{
IsSpecial = false,
Number = "2.5",
CoverImage = "Special 1",
},
new Chapter()
{
IsSpecial = false,
Number = "2",
CoverImage = "Special 2",
},
new Chapter()
{
IsSpecial = true,
Number = API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter,
CoverImage = "Special 3",
}
},
},
new Volume()
{
Number = 1,
Name = "1",
Chapters = new List<Chapter>()
{
new Chapter()
{
IsSpecial = false,
Number = "0",
CoverImage = "Volume 1",
},
},
}
}
};
var series = new SeriesBuilder("Test 1")
.WithFormat(MangaFormat.Archive)
.WithVolume(new VolumeBuilder("0")
.WithName(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
.WithChapter(new ChapterBuilder("2.5")
.WithIsSpecial(false)
.WithCoverImage("Special 1")
.Build())
.WithChapter(new ChapterBuilder("2")
.WithIsSpecial(false)
.WithCoverImage("Special 2")
.Build())
.WithChapter(new ChapterBuilder("0")
.WithIsSpecial(true)
.WithCoverImage("Special 3")
.Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithNumber(1)
.WithChapter(new ChapterBuilder("0")
.WithIsSpecial(false)
.WithCoverImage("Volume 1")
.Build())
.Build())
.Build();
foreach (var vol in series.Volumes)
{

View file

@ -0,0 +1,58 @@
using System.Collections.Generic;
using API.Data;
using API.Entities;
using API.Entities.Enums;
namespace API.Tests.Helpers.Builders;
public class ChapterBuilder : IEntityBuilder<Chapter>
{
private Chapter _chapter;
public Chapter Build() => _chapter;
public ChapterBuilder(string number, string? range=null)
{
_chapter = new Chapter()
{
Range = string.IsNullOrEmpty(range) ? number : range,
Title = string.IsNullOrEmpty(range) ? number : range,
Number = API.Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(number) + string.Empty,
Files = new List<MangaFile>(),
Pages = 1
};
}
public ChapterBuilder WithAgeRating(AgeRating rating)
{
_chapter.AgeRating = rating;
return this;
}
public ChapterBuilder WithPages(int pages)
{
_chapter.Pages = pages;
return this;
}
public ChapterBuilder WithCoverImage(string cover)
{
_chapter.CoverImage = cover;
return this;
}
public ChapterBuilder WithIsSpecial(bool isSpecial)
{
_chapter.IsSpecial = isSpecial;
return this;
}
public ChapterBuilder WithTitle(string title)
{
_chapter.Title = title;
return this;
}
public ChapterBuilder WithFile(MangaFile file)
{
_chapter.Files ??= new List<MangaFile>();
_chapter.Files.Add(file);
return this;
}
}

View file

@ -0,0 +1,6 @@
namespace API.Tests.Helpers.Builders;
public interface IEntityBuilder<out T>
{
public T Build();
}

View file

@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Linq;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
namespace API.Tests.Helpers.Builders;
public class SeriesBuilder : IEntityBuilder<Series>
{
private readonly Series _series;
public Series Build()
{
_series.Pages = _series.Volumes.Sum(v => v.Chapters.Sum(c => c.Pages));
return _series;
}
public SeriesBuilder(string name)
{
_series = new Series()
{
Name = name,
LocalizedName = name.ToNormalized(),
OriginalName = name,
SortName = name,
NormalizedName = name.ToNormalized(),
NormalizedLocalizedName = name.ToNormalized(),
Metadata = new SeriesMetadata(),
Volumes = new List<Volume>()
};
}
public SeriesBuilder WithLocalizedName(string localizedName)
{
_series.LocalizedName = localizedName;
_series.NormalizedLocalizedName = localizedName.ToNormalized();
return this;
}
public SeriesBuilder WithFormat(MangaFormat format)
{
_series.Format = format;
return this;
}
public SeriesBuilder WithVolume(Volume volume)
{
_series.Volumes ??= new List<Volume>();
_series.Volumes.Add(volume);
return this;
}
public SeriesBuilder WithVolumes(List<Volume> volumes)
{
_series.Volumes = volumes;
return this;
}
public SeriesBuilder WithMetadata(SeriesMetadata metadata)
{
_series.Metadata = metadata;
return this;
}
public SeriesBuilder WithPages(int pages)
{
_series.Pages = pages;
return this;
}
}

View file

@ -0,0 +1,37 @@
using System.Collections.Generic;
using API.Data;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
namespace API.Tests.Helpers.Builders;
public class SeriesMetadataBuilder : IEntityBuilder<SeriesMetadata>
{
private SeriesMetadata _seriesMetadata;
public SeriesMetadata Build() => _seriesMetadata;
public SeriesMetadataBuilder()
{
_seriesMetadata = new SeriesMetadata()
{
CollectionTags = new List<CollectionTag>(),
Genres = new List<Genre>(),
Tags = new List<Tag>(),
People = new List<Person>()
};
}
public SeriesMetadataBuilder WithCollectionTag(CollectionTag tag)
{
_seriesMetadata.CollectionTags ??= new List<API.Entities.CollectionTag>();
_seriesMetadata.CollectionTags.Add(tag);
return this;
}
public SeriesMetadataBuilder WithPublicationStatus(PublicationStatus status)
{
_seriesMetadata.PublicationStatus = status;
return this;
}
}

View file

@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Linq;
using API.Data;
using API.Entities;
namespace API.Tests.Helpers.Builders;
public class VolumeBuilder : IEntityBuilder<Volume>
{
private readonly Volume _volume;
public Volume Build() => _volume;
public VolumeBuilder(string volumeNumber)
{
_volume = DbFactory.Volume(volumeNumber);
}
public VolumeBuilder WithName(string name)
{
_volume.Name = name;
return this;
}
public VolumeBuilder WithNumber(int number)
{
_volume.Number = number;
return this;
}
public VolumeBuilder WithChapters(List<Chapter> chapters)
{
_volume.Chapters = chapters;
return this;
}
public VolumeBuilder WithChapter(Chapter chapter)
{
_volume.Chapters ??= new List<Chapter>();
_volume.Chapters.Add(chapter);
_volume.Pages = _volume.Chapters.Sum(c => c.Pages);
return this;
}
}

View file

@ -156,6 +156,8 @@ public class CacheHelperTests
var chapter = new Chapter()
{
Number = "1",
Range = "1",
Created = filesystemFile.LastWriteTime.DateTime,
LastModified = filesystemFile.LastWriteTime.DateTime
};
@ -186,6 +188,8 @@ public class CacheHelperTests
var chapter = new Chapter()
{
Number = "1",
Range = "1",
Created = filesystemFile.LastWriteTime.DateTime,
LastModified = filesystemFile.LastWriteTime.DateTime
};
@ -216,6 +220,8 @@ public class CacheHelperTests
var chapter = new Chapter()
{
Number = "1",
Range = "1",
Created = filesystemFile.LastWriteTime.DateTime,
LastModified = filesystemFile.LastWriteTime.DateTime
};
@ -247,6 +253,8 @@ public class CacheHelperTests
var chapter = new Chapter()
{
Number = "1",
Range = "1",
Created = DateTime.Now.Subtract(TimeSpan.FromMinutes(10)),
LastModified = DateTime.Now.Subtract(TimeSpan.FromMinutes(10))
};
@ -277,6 +285,8 @@ public class CacheHelperTests
var chapter = new Chapter()
{
Number = "1",
Range = "1",
Created = DateTime.Now.Subtract(TimeSpan.FromMinutes(10)),
LastModified = DateTime.Now
};

View file

@ -4,6 +4,7 @@ using API.Data;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
namespace API.Tests.Helpers;
@ -19,7 +20,9 @@ public static class EntityFactory
Name = name,
SortName = name,
LocalizedName = name,
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize(name),
NormalizedName = name.ToNormalized(),
OriginalName = name,
NormalizedLocalizedName = name.ToNormalized(),
Volumes = new List<Volume>(),
Metadata = new SeriesMetadata()
};
@ -38,7 +41,7 @@ public static class EntityFactory
};
}
public static Chapter CreateChapter(string range, bool isSpecial, List<MangaFile> files = null, int pageCount = 0)
public static Chapter CreateChapter(string range, bool isSpecial, List<MangaFile> files = null, int pageCount = 0, string title = null)
{
return new Chapter()
{
@ -47,7 +50,7 @@ public static class EntityFactory
Number = API.Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(range) + string.Empty,
Files = files ?? new List<MangaFile>(),
Pages = pageCount,
Title = title ?? range
};
}
@ -66,3 +69,6 @@ public static class EntityFactory
return DbFactory.CollectionTag(id, title, summary, promoted);
}
}

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using API.Entities.Enums;
using API.Extensions;
using API.Parser;
using API.Services.Tasks.Scanner;
@ -29,12 +30,12 @@ public static class ParserInfoFactory
public static void AddToParsedInfo(IDictionary<ParsedSeries, IList<ParserInfo>> collectedSeries, ParserInfo info)
{
var existingKey = collectedSeries.Keys.FirstOrDefault(ps =>
ps.Format == info.Format && ps.NormalizedName == API.Services.Tasks.Scanner.Parser.Parser.Normalize(info.Series));
ps.Format == info.Format && ps.NormalizedName == info.Series.ToNormalized());
existingKey ??= new ParsedSeries()
{
Format = info.Format,
Name = info.Series,
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize(info.Series)
NormalizedName = info.Series.ToNormalized()
};
if (collectedSeries.GetType() == typeof(ConcurrentDictionary<,>))
{

View file

@ -2,9 +2,11 @@
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Helpers;
using API.Parser;
using API.Services.Tasks.Scanner;
using API.Tests.Helpers.Builders;
using Xunit;
namespace API.Tests.Helpers;
@ -21,23 +23,14 @@ public class ParserInfoHelperTests
ParserInfoFactory.AddToParsedInfo(infos, new ParserInfo() {Series = "Darker than Black", Volumes = "1", Format = MangaFormat.Archive});
//AddToParsedInfo(infos, new ParserInfo() {Series = "Darker than Black", Volumes = "1", Format = MangaFormat.Epub});
var series = new Series()
{
Name = "Darker Than Black",
LocalizedName = "Darker Than Black",
OriginalName = "Darker Than Black",
Volumes = new List<Volume>()
{
new Volume()
{
Number = 1,
Name = "1"
}
},
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker Than Black"),
Metadata = new SeriesMetadata(),
Format = MangaFormat.Epub
};
var series = new SeriesBuilder("Darker Than Black")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithName("1")
.Build())
.WithLocalizedName("Darker Than Black")
.Build();
Assert.False(ParserInfoHelpers.SeriesHasMatchingParserInfoFormat(series, infos));
}
@ -50,23 +43,15 @@ public class ParserInfoHelperTests
ParserInfoFactory.AddToParsedInfo(infos, new ParserInfo() {Series = "Darker than Black", Volumes = "1", Format = MangaFormat.Archive});
ParserInfoFactory.AddToParsedInfo(infos, new ParserInfo() {Series = "Darker than Black", Volumes = "1", Format = MangaFormat.Epub});
var series = new Series()
{
Name = "Darker Than Black",
LocalizedName = "Darker Than Black",
OriginalName = "Darker Than Black",
Volumes = new List<Volume>()
{
new Volume()
{
Number = 1,
Name = "1"
}
},
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker Than Black"),
Metadata = new SeriesMetadata(),
Format = MangaFormat.Epub
};
var series = new SeriesBuilder("Darker Than Black")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithName("1")
.Build())
.WithLocalizedName("Darker Than Black")
.Build();
Assert.True(ParserInfoHelpers.SeriesHasMatchingParserInfoFormat(series, infos));
}

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using API.Data;
using API.Entities;
using API.Entities.Enums;

View file

@ -3,6 +3,7 @@ using System.Linq;
using API.Data;
using API.Entities;
using API.Entities.Enums;
using API.Extensions;
using API.Helpers;
using API.Services.Tasks.Scanner;
using Xunit;
@ -22,21 +23,35 @@ public class SeriesHelperTests
{
Format = MangaFormat.Archive,
Name = "Darker than Black",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
NormalizedName = "Darker than Black".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Archive,
Name = "Darker than Black".ToLower(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
NormalizedName = "Darker than Black".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Archive,
Name = "Darker than Black".ToUpper(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
NormalizedName = "Darker than Black".ToNormalized()
}));
}
[Fact]
public void FindSeries_ShouldFind_NullName()
{
var series = DbFactory.Series("Darker than Black");
series.OriginalName = null;
series.Format = MangaFormat.Archive;
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Archive,
Name = "Darker than Black",
NormalizedName = "Darker than Black".ToNormalized()
}));
}
@ -50,21 +65,21 @@ public class SeriesHelperTests
{
Format = MangaFormat.Image,
Name = "Darker than Black",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
NormalizedName = "Darker than Black".ToNormalized()
}));
Assert.False(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Image,
Name = "Darker than Black".ToLower(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
NormalizedName = "Darker than Black".ToNormalized()
}));
Assert.False(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Image,
Name = "Darker than Black".ToUpper(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker than Black")
NormalizedName = "Darker than Black".ToNormalized()
}));
}
@ -78,28 +93,28 @@ public class SeriesHelperTests
{
Format = MangaFormat.Image,
Name = "Something Random",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
NormalizedName = "Something Random".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Image,
Name = "Something Random".ToLower(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
NormalizedName = "Something Random".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Image,
Name = "Something Random".ToUpper(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
NormalizedName = "Something Random".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Image,
Name = "SomethingRandom".ToUpper(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("SomethingRandom")
NormalizedName = "SomethingRandom".ToNormalized()
}));
}
@ -113,28 +128,28 @@ public class SeriesHelperTests
{
Format = MangaFormat.Image,
Name = "Something Random",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
NormalizedName = "Something Random".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Image,
Name = "Something Random".ToLower(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
NormalizedName = "Something Random".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Image,
Name = "Something Random".ToUpper(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something Random")
NormalizedName = "Something Random".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Image,
Name = "SomethingRandom".ToUpper(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("SomethingRandom")
NormalizedName = "SomethingRandom".ToNormalized()
}));
}
@ -148,14 +163,14 @@ public class SeriesHelperTests
{
Format = MangaFormat.Archive,
Name = "My Dress-Up Darling",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("My Dress-Up Darling")
NormalizedName = "My Dress-Up Darling".ToNormalized()
}));
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
{
Format = MangaFormat.Archive,
Name = "Sono Bisque Doll wa Koi wo Suru".ToLower(),
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Sono Bisque Doll wa Koi wo Suru")
NormalizedName = "Sono Bisque Doll wa Koi wo Suru".ToNormalized()
}));
}
#endregion

View file

@ -1,5 +1,4 @@
using System.IO.Abstractions.TestingHelpers;
using API.Parser;
using API.Services;
using API.Services.Tasks.Scanner.Parser;
using Microsoft.Extensions.Logging;

View file

@ -51,7 +51,7 @@ public class DefaultParserTests
{
const string rootDirectory = "/manga/";
var tokens = expectedParseInfo.Split("~");
var actual = new ParserInfo {Chapters = "0", Volumes = "0"};
var actual = new ParserInfo {Series = "", Chapters = "0", Volumes = "0"};
_defaultParser.ParseFromFallbackFolders(inputFile, rootDirectory, LibraryType.Manga, ref actual);
Assert.Equal(tokens[0], actual.Series);
Assert.Equal(tokens[1], actual.Volumes);

View file

@ -1,4 +1,3 @@
using System.Runtime.InteropServices;
using API.Entities.Enums;
using Xunit;
using Xunit.Abstractions;

View file

@ -249,7 +249,7 @@ public class ParserTests
[InlineData("The ()quick brown fox jumps over the lazy dog")]
[InlineData("The (quick (brown)) fox jumps over the lazy dog")]
[InlineData("The (quick (brown) fox jumps over the lazy dog)")]
public void BalancedParenTestMatches(string input)
public void BalancedParenTest_Matches(string input)
{
Assert.Matches($@"^{BalancedParen}$", input);
}
@ -261,7 +261,7 @@ public class ParserTests
[InlineData("The quick (brown)) fox jumps over the lazy dog")]
[InlineData("The quick (brown) fox jumps over the lazy dog)")]
[InlineData("(The ))(quick (brown) fox jumps over the lazy dog")]
public void BalancedParenTestDoesNotMatch(string input)
public void BalancedParenTest_DoesNotMatch(string input)
{
Assert.DoesNotMatch($@"^{BalancedParen}$", input);
}
@ -273,9 +273,9 @@ public class ParserTests
[InlineData("The []quick brown fox jumps over the lazy dog")]
[InlineData("The [quick [brown]] fox jumps over the lazy dog")]
[InlineData("The [quick [brown] fox jumps over the lazy dog]")]
public void BalancedBrackTestMatches(string input)
public void BalancedBracketTest_Matches(string input)
{
Assert.Matches($@"^{BalancedBrack}$", input);
Assert.Matches($@"^{BalancedBracket}$", input);
}
[Theory]
@ -285,8 +285,8 @@ public class ParserTests
[InlineData("The quick [brown]] fox jumps over the lazy dog")]
[InlineData("The quick [brown] fox jumps over the lazy dog]")]
[InlineData("[The ]][quick [brown] fox jumps over the lazy dog")]
public void BalancedBrackTestDoesNotMatch(string input)
public void BalancedBracketTest_DoesNotMatch(string input)
{
Assert.DoesNotMatch($@"^{BalancedBrack}$", input);
Assert.DoesNotMatch($@"^{BalancedBracket}$", input);
}
}

View file

@ -0,0 +1,177 @@
using System.Collections.Generic;
using System.Data.Common;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using System.Threading.Tasks;
using API.Data;
using API.Entities;
using API.Entities.Enums;
using API.Helpers;
using API.Services;
using AutoMapper;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
namespace API.Tests.Repository;
public class CollectionTagRepositoryTests
{
private readonly IUnitOfWork _unitOfWork;
private readonly DbConnection _connection;
private readonly DataContext _context;
private const string CacheDirectory = "C:/kavita/config/cache/";
private const string CoverImageDirectory = "C:/kavita/config/covers/";
private const string BackupDirectory = "C:/kavita/config/backups/";
private const string DataDirectory = "C:/data/";
public CollectionTagRepositoryTests()
{
var contextOptions = new DbContextOptionsBuilder().UseSqlite(CreateInMemoryDatabase()).Options;
_connection = RelationalOptionsExtension.Extract(contextOptions).Connection;
_context = new DataContext(contextOptions);
Task.Run(SeedDb).GetAwaiter().GetResult();
var config = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperProfiles>());
var mapper = config.CreateMapper();
_unitOfWork = new UnitOfWork(_context, mapper, null);
}
#region Setup
private static DbConnection CreateInMemoryDatabase()
{
var connection = new SqliteConnection("Filename=:memory:");
connection.Open();
return connection;
}
private async Task<bool> SeedDb()
{
await _context.Database.MigrateAsync();
var filesystem = CreateFileSystem();
await Seed.SeedSettings(_context,
new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem));
var setting = await _context.ServerSetting.Where(s => s.Key == ServerSettingKey.CacheDirectory).SingleAsync();
setting.Value = CacheDirectory;
setting = await _context.ServerSetting.Where(s => s.Key == ServerSettingKey.BackupDirectory).SingleAsync();
setting.Value = BackupDirectory;
_context.ServerSetting.Update(setting);
var lib = new Library()
{
Name = "Manga", Folders = new List<FolderPath>() {new FolderPath() {Path = "C:/data/"}}
};
_context.AppUser.Add(new AppUser()
{
UserName = "majora2007",
Libraries = new List<Library>()
{
lib
}
});
return await _context.SaveChangesAsync() > 0;
}
private async Task ResetDb()
{
_context.Series.RemoveRange(_context.Series.ToList());
_context.AppUserRating.RemoveRange(_context.AppUserRating.ToList());
_context.Genre.RemoveRange(_context.Genre.ToList());
_context.CollectionTag.RemoveRange(_context.CollectionTag.ToList());
_context.Person.RemoveRange(_context.Person.ToList());
await _context.SaveChangesAsync();
}
private static MockFileSystem CreateFileSystem()
{
var fileSystem = new MockFileSystem();
fileSystem.Directory.SetCurrentDirectory("C:/kavita/");
fileSystem.AddDirectory("C:/kavita/config/");
fileSystem.AddDirectory(CacheDirectory);
fileSystem.AddDirectory(CoverImageDirectory);
fileSystem.AddDirectory(BackupDirectory);
fileSystem.AddDirectory(DataDirectory);
return fileSystem;
}
#endregion
#region RemoveTagsWithoutSeries
[Fact]
public async Task RemoveTagsWithoutSeries_ShouldRemoveTags()
{
var library = DbFactory.Library("Test", LibraryType.Manga);
var series = DbFactory.Series("Test 1");
var commonTag = DbFactory.CollectionTag(0, "Tag 1");
series.Metadata.CollectionTags.Add(commonTag);
series.Metadata.CollectionTags.Add(DbFactory.CollectionTag(0, "Tag 2"));
var series2 = DbFactory.Series("Test 1");
series2.Metadata.CollectionTags.Add(commonTag);
library.Series.Add(series);
library.Series.Add(series2);
_unitOfWork.LibraryRepository.Add(library);
await _unitOfWork.CommitAsync();
Assert.Equal(2, series.Metadata.CollectionTags.Count);
Assert.Single(series2.Metadata.CollectionTags);
// Delete both series
_unitOfWork.SeriesRepository.Remove(series);
_unitOfWork.SeriesRepository.Remove(series2);
await _unitOfWork.CommitAsync();
// Validate that both tags exist
Assert.Equal(2, (await _unitOfWork.CollectionTagRepository.GetAllTagsAsync()).Count());
await _unitOfWork.CollectionTagRepository.RemoveTagsWithoutSeries();
Assert.Empty(await _unitOfWork.CollectionTagRepository.GetAllTagsAsync());
}
[Fact]
public async Task RemoveTagsWithoutSeries_ShouldNotRemoveTags()
{
var library = DbFactory.Library("Test", LibraryType.Manga);
var series = DbFactory.Series("Test 1");
var commonTag = DbFactory.CollectionTag(0, "Tag 1");
series.Metadata.CollectionTags.Add(commonTag);
series.Metadata.CollectionTags.Add(DbFactory.CollectionTag(0, "Tag 2"));
var series2 = DbFactory.Series("Test 1");
series2.Metadata.CollectionTags.Add(commonTag);
library.Series.Add(series);
library.Series.Add(series2);
_unitOfWork.LibraryRepository.Add(library);
await _unitOfWork.CommitAsync();
Assert.Equal(2, series.Metadata.CollectionTags.Count);
Assert.Single(series2.Metadata.CollectionTags);
await _unitOfWork.CollectionTagRepository.RemoveTagsWithoutSeries();
// Validate that both tags exist
Assert.Equal(2, (await _unitOfWork.CollectionTagRepository.GetAllTagsAsync()).Count());
}
#endregion
}

View file

@ -40,7 +40,7 @@ public class SeriesRepositoryTests
var config = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperProfiles>());
var mapper = config.CreateMapper();
_unitOfWork = new UnitOfWork(_context, mapper, null);
_unitOfWork = new UnitOfWork(_context, mapper, null!);
}
#region Setup
@ -138,11 +138,13 @@ public class SeriesRepositoryTests
}
[InlineData("Heion Sedai no Idaten-tachi", "", MangaFormat.Archive, "The Idaten Deities Know Only Peace")] // Matching on localized name in DB
[InlineData("Heion Sedai no Idaten-tachi", "", MangaFormat.Pdf, null)]
// This test case isn't ready to go
[InlineData("Heion Sedai no Idaten-tachi", MangaFormat.Archive, "", "The Idaten Deities Know Only Peace")] // Matching on localized name in DB
[InlineData("Heion Sedai no Idaten-tachi", MangaFormat.Pdf, "", null)]
public async Task GetFullSeriesByAnyName_Should(string seriesName, MangaFormat format, string localizedName, string? expected)
{
var firstSeries = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1);
await ResetDb();
await SetupSeriesData();
var series =
await _unitOfWork.SeriesRepository.GetFullSeriesByAnyName(seriesName, localizedName,
1, format);
@ -157,6 +159,4 @@ public class SeriesRepositoryTests
}
}
//public async Task
}

View file

@ -5,7 +5,6 @@ using System.IO.Abstractions.TestingHelpers;
using System.IO.Compression;
using System.Linq;
using API.Archive;
using API.Data.Metadata;
using API.Services;
using Microsoft.Extensions.Logging;
using NetVips;

View file

@ -1,18 +1,15 @@
using System.Collections.Generic;
using System.Data.Common;
using System.IO.Abstractions.TestingHelpers;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using API.Data;
using API.Entities;
using API.Entities.Enums;
using API.Extensions;
using API.Services;
using API.Services.Tasks;
using API.SignalR;
using AutoMapper;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.IO.Abstractions.TestingHelpers;
@ -10,9 +9,12 @@ using API.Data.Repositories;
using API.DTOs.Reader;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Helpers;
using API.Services;
using API.SignalR;
using API.Tests.Helpers.Builders;
using AutoMapper;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
@ -136,27 +138,22 @@ public class BookmarkServiceTests
// Delete all Series to reset state
await ResetDB();
_context.Series.Add(new Series()
var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.Build())
.Build())
.Build();
series.Library = new Library()
{
Name = "Test",
Library = new Library() {
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>()
{
new Volume()
{
Chapters = new List<Chapter>()
{
new Chapter()
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series);
}
}
}
}
});
_context.AppUser.Add(new AppUser()
{
@ -194,27 +191,22 @@ public class BookmarkServiceTests
// Delete all Series to reset state
await ResetDB();
_context.Series.Add(new Series()
var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithNumber(1)
.WithChapter(new ChapterBuilder("0")
.Build())
.Build())
.Build();
series.Library = new Library()
{
Name = "Test",
Library = new Library() {
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>()
{
new Volume()
{
Chapters = new List<Chapter>()
{
new Chapter()
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
}
}
}
}
});
_context.Series.Add(series);
_context.AppUser.Add(new AppUser()
@ -270,28 +262,22 @@ public class BookmarkServiceTests
// Delete all Series to reset state
await ResetDB();
_context.Series.Add(new Series()
var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithNumber(1)
.WithChapter(new ChapterBuilder("1")
.Build())
.Build())
.Build();
series.Library = new Library()
{
Name = "Test",
Library = new Library() {
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>()
{
new Volume()
{
Chapters = new List<Chapter>()
{
new Chapter()
{
}
}
}
}
});
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series);
_context.AppUser.Add(new AppUser()
{
@ -342,7 +328,7 @@ public class BookmarkServiceTests
Assert.Equal(2, ds.GetFiles(BookmarkDirectory, searchOption:SearchOption.AllDirectories).Count());
Assert.False(ds.FileSystem.FileInfo.FromFileName(Path.Join(BookmarkDirectory, "1/1/1/0001.jpg")).Exists);
Assert.False(ds.FileSystem.FileInfo.New(Path.Join(BookmarkDirectory, "1/1/1/0001.jpg")).Exists);
}
#endregion
@ -357,27 +343,23 @@ public class BookmarkServiceTests
// Delete all Series to reset state
await ResetDB();
_context.Series.Add(new Series()
var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithNumber(1)
.WithChapter(new ChapterBuilder("1")
.Build())
.Build())
.Build();
series.Library = new Library()
{
Name = "Test",
Library = new Library() {
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>()
{
new Volume()
{
Chapters = new List<Chapter>()
{
new Chapter()
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series);
}
}
}
}
});
_context.AppUser.Add(new AppUser()
{
@ -419,28 +401,22 @@ public class BookmarkServiceTests
// Delete all Series to reset state
await ResetDB();
_context.Series.Add(new Series()
var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithNumber(1)
.WithChapter(new ChapterBuilder("1")
.Build())
.Build())
.Build();
series.Library = new Library()
{
Name = "Test",
Library = new Library() {
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>()
{
new Volume()
{
Chapters = new List<Chapter>()
{
new Chapter()
{
}
}
}
}
});
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series);
_context.AppUser.Add(new AppUser()
{
@ -483,27 +459,19 @@ public class BookmarkServiceTests
// Delete all Series to reset state
await ResetDB();
var series = new Series()
var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithNumber(1)
.WithChapter(new ChapterBuilder("1")
.Build())
.Build())
.Build();
series.Library = new Library()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>()
{
new Volume()
{
Chapters = new List<Chapter>()
{
new Chapter()
{
}
}
}
}
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series);
@ -528,7 +496,7 @@ public class BookmarkServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(1, AppUserIncludes.Bookmarks);
Assert.NotEmpty(user.Bookmarks);
Assert.NotEmpty(user!.Bookmarks);
series.Volumes = new List<Volume>();
_unitOfWork.SeriesRepository.Update(series);

View file

@ -171,6 +171,7 @@ public class CacheServiceTests
var c = new Chapter()
{
Number = "1",
Range = "1",
Files = new List<MangaFile>()
{
new MangaFile()
@ -272,6 +273,8 @@ public class CacheServiceTests
var c = new Chapter()
{
Number = "1",
Range = "1",
Files = new List<MangaFile>()
{
new MangaFile()
@ -303,6 +306,8 @@ public class CacheServiceTests
var c = new Chapter()
{
Id = 1,
Number = "1",
Range = "1",
Files = new List<MangaFile>()
};
@ -340,6 +345,8 @@ public class CacheServiceTests
var c = new Chapter()
{
Id = 1,
Number = "1",
Range = "1",
Files = new List<MangaFile>()
{
new MangaFile()
@ -392,6 +399,8 @@ public class CacheServiceTests
var c = new Chapter()
{
Id = 1,
Number = "1",
Range = "1",
Files = new List<MangaFile>()
{
new MangaFile()
@ -440,6 +449,8 @@ public class CacheServiceTests
var c = new Chapter()
{
Id = 1,
Number = "1",
Range = "1",
Files = new List<MangaFile>()
{
new MangaFile()

View file

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
@ -8,21 +7,16 @@ using System.Threading.Tasks;
using API.Data;
using API.Data.Repositories;
using API.DTOs.Filtering;
using API.DTOs.Settings;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Helpers;
using API.Helpers.Converters;
using API.Services;
using API.Services.Tasks;
using API.SignalR;
using API.Tests.Helpers;
using AutoMapper;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using API.Tests.Helpers.Builders;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
@ -149,6 +143,8 @@ public class CleanupServiceTests : AbstractDbTest
var v = DbFactory.Volume("1");
v.Chapters.Add(new Chapter()
{
Number = "0",
Range = "0",
CoverImage = "v01_c01.jpg"
});
v.CoverImage = "v01_c01.jpg";
@ -161,6 +157,8 @@ public class CleanupServiceTests : AbstractDbTest
v = DbFactory.Volume("1");
v.Chapters.Add(new Chapter()
{
Number = "0",
Range = "0",
CoverImage = "v01_c03.jpg"
});
v.CoverImage = "v01_c03jpg";
@ -200,6 +198,7 @@ public class CleanupServiceTests : AbstractDbTest
s.Metadata.CollectionTags.Add(new CollectionTag()
{
Title = "Something",
NormalizedTitle = "Something".ToNormalized(),
CoverImage = $"{ImageService.GetCollectionTagFormat(1)}.jpg"
});
s.CoverImage = $"{ImageService.GetSeriesFormat(1)}.jpg";
@ -211,6 +210,7 @@ public class CleanupServiceTests : AbstractDbTest
s.Metadata.CollectionTags.Add(new CollectionTag()
{
Title = "Something 2",
NormalizedTitle = "Something 2".ToNormalized(),
CoverImage = $"{ImageService.GetCollectionTagFormat(2)}.jpg"
});
s.CoverImage = $"{ImageService.GetSeriesFormat(3)}.jpg";
@ -250,14 +250,16 @@ public class CleanupServiceTests : AbstractDbTest
new ReadingList()
{
Title = "Something",
NormalizedTitle = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something"),
CoverImage = $"{ImageService.GetReadingListFormat(1)}.jpg"
NormalizedTitle = "Something".ToNormalized(),
CoverImage = $"{ImageService.GetReadingListFormat(1)}.jpg",
AgeRating = AgeRating.Unknown
},
new ReadingList()
{
Title = "Something 2",
NormalizedTitle = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Something 2"),
CoverImage = $"{ImageService.GetReadingListFormat(2)}.jpg"
NormalizedTitle = "Something 2".ToNormalized(),
CoverImage = $"{ImageService.GetReadingListFormat(2)}.jpg",
AgeRating = AgeRating.Unknown
}
}
});
@ -408,22 +410,25 @@ public class CleanupServiceTests : AbstractDbTest
[Fact]
public async Task CleanupDbEntries_CleanupAbandonedChapters()
{
var c = EntityFactory.CreateChapter("1", false, new List<MangaFile>(), 1);
_context.Series.Add(new Series()
var c = new ChapterBuilder("0")
.WithPages(1)
.Build();
var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0")
.WithNumber(1)
.WithChapter(c)
.Build())
.Build();
series.Library = new Library()
{
Name = "Test",
Library = new Library() {
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
c,
}),
}
});
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series);
_context.AppUser.Add(new AppUser()
{
@ -461,25 +466,19 @@ public class CleanupServiceTests : AbstractDbTest
{
var c = new CollectionTag()
{
Title = "Test Tag"
Title = "Test Tag",
NormalizedTitle = "Test Tag".ToNormalized(),
};
var s = new Series()
var s = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadataBuilder().WithCollectionTag(c).Build())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>(),
Metadata = new SeriesMetadata()
{
CollectionTags = new List<CollectionTag>()
{
c
}
}
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(s);
_context.AppUser.Add(new AppUser()
@ -511,19 +510,14 @@ public class CleanupServiceTests : AbstractDbTest
{
await ResetDb();
var s = new Series()
var s = new SeriesBuilder("Test CleanupWantToRead_ShouldRemoveFullyReadSeries")
.WithMetadata(new SeriesMetadataBuilder().WithPublicationStatus(PublicationStatus.Completed).Build())
.Build();
s.Library = new Library()
{
Name = "Test CleanupWantToRead_ShouldRemoveFullyReadSeries",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>(),
Metadata = new SeriesMetadata()
{
PublicationStatus = PublicationStatus.Completed
}
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(s);

View file

@ -2,14 +2,13 @@
using System.Linq;
using System.Threading.Tasks;
using API.Data;
using API.Data.Repositories;
using API.DTOs.CollectionTags;
using API.Entities;
using API.Entities.Enums;
using API.Services;
using API.Services.Tasks.Metadata;
using API.SignalR;
using API.Tests.Helpers;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
@ -87,7 +86,7 @@ public class CollectionTagServiceTests : AbstractDbTest
{
await SeedSeries();
var ids = new[] {1, 2};
await _service.AddTagToSeries(await _unitOfWork.CollectionTagRepository.GetFullTagAsync(1), ids);
await _service.AddTagToSeries(await _unitOfWork.CollectionTagRepository.GetTagAsync(1, CollectionTagIncludes.SeriesMetadata), ids);
var metadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIdsAsync(ids);
Assert.True(metadatas.ElementAt(0).CollectionTags.Any(t => t.Title.Equals("Tag 1")));
@ -99,7 +98,7 @@ public class CollectionTagServiceTests : AbstractDbTest
{
await SeedSeries();
var ids = new[] {1, 2};
var tag = await _unitOfWork.CollectionTagRepository.GetFullTagAsync(2);
var tag = await _unitOfWork.CollectionTagRepository.GetTagAsync(2, CollectionTagIncludes.SeriesMetadata);
await _service.AddTagToSeries(tag, ids);
await _service.RemoveTagFromSeries(tag, new[] {1});

View file

@ -5,7 +5,6 @@ using API.DTOs.Device;
using API.Entities;
using API.Entities.Enums.Device;
using API.Services;
using API.Services.Tasks;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;

View file

@ -152,7 +152,7 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
var files = ds.GetFiles(testDirectory, API.Services.Tasks.Scanner.Parser.Parser.ArchiveFileExtensions).ToList();
Assert.Equal(10, files.Count());
Assert.Equal(10, files.Count);
Assert.All(files, s => fileSystem.Path.GetExtension(s).Equals(".zip"));
}
@ -171,7 +171,7 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
var files = ds.GetFiles(testDirectory).ToList();
Assert.Equal(11, files.Count());
Assert.Equal(11, files.Count);
}
[Fact]
@ -189,7 +189,7 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
var files = ds.GetFiles(testDirectory).ToList();
Assert.Equal(11, files.Count());
Assert.Equal(11, files.Count);
}
[Fact]
@ -207,7 +207,7 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
var files = ds.GetFiles(testDirectory).ToList();
Assert.Equal(10, files.Count());
Assert.Equal(10, files.Count);
}
[Fact]
@ -225,7 +225,7 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
var files = ds.GetFiles(testDirectory).ToList();
Assert.Equal(10, files.Count());
Assert.Equal(10, files.Count);
}
[Fact]
@ -243,7 +243,7 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
var files = ds.GetFiles(testDirectory).ToList();
Assert.Equal(10, files.Count());
Assert.Equal(10, files.Count);
}
[Fact]
@ -325,7 +325,7 @@ public class DirectoryServiceTests
ds.CopyFileToDirectory($"{testDirectory}file/data-0.txt", "/manga/output/");
Assert.True(fileSystem.FileExists("/manga/output/data-0.txt"));
Assert.True(fileSystem.FileExists("/manga/file/data-0.txt"));
Assert.True(fileSystem.FileInfo.FromFileName("/manga/file/data-0.txt").Length == fileSystem.FileInfo.FromFileName("/manga/output/data-0.txt").Length);
Assert.True(fileSystem.FileInfo.New("/manga/file/data-0.txt").Length == fileSystem.FileInfo.New("/manga/output/data-0.txt").Length);
}
#endregion
@ -353,7 +353,7 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
ds.CopyDirectoryToDirectory($"{testDirectory}empty/", "/manga/output/");
Assert.Empty(fileSystem.DirectoryInfo.FromDirectoryName("/manga/output/").GetFiles());
Assert.Empty(fileSystem.DirectoryInfo.New("/manga/output/").GetFiles());
}
[Fact]
@ -427,7 +427,7 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
ds.ExistOrCreate("c:/manga/output/");
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName("c:/manga/output/").Exists);
Assert.True(ds.FileSystem.DirectoryInfo.New("c:/manga/output/").Exists);
}
#endregion
@ -448,9 +448,9 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
ds.ClearAndDeleteDirectory($"{testDirectory}");
Assert.Empty(ds.GetFiles("/manga/", searchOption: SearchOption.AllDirectories));
Assert.Empty(ds.FileSystem.DirectoryInfo.FromDirectoryName("/manga/").GetDirectories());
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName("/manga/").Exists);
Assert.False(ds.FileSystem.DirectoryInfo.FromDirectoryName("/manga/base").Exists);
Assert.Empty(ds.FileSystem.DirectoryInfo.New("/manga/").GetDirectories());
Assert.True(ds.FileSystem.DirectoryInfo.New("/manga/").Exists);
Assert.False(ds.FileSystem.DirectoryInfo.New("/manga/base").Exists);
}
#endregion
@ -470,9 +470,9 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
ds.ClearDirectory($"{testDirectory}file/");
Assert.Empty(ds.FileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}file/").GetDirectories());
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName("/manga/").Exists);
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}file/").Exists);
Assert.Empty(ds.FileSystem.DirectoryInfo.New($"{testDirectory}file/").GetDirectories());
Assert.True(ds.FileSystem.DirectoryInfo.New("/manga/").Exists);
Assert.True(ds.FileSystem.DirectoryInfo.New($"{testDirectory}file/").Exists);
}
[Fact]
@ -487,9 +487,9 @@ public class DirectoryServiceTests
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), fileSystem);
ds.ClearDirectory($"{testDirectory}");
Assert.Empty(ds.FileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}").GetDirectories());
Assert.True(ds.FileSystem.DirectoryInfo.FromDirectoryName(testDirectory).Exists);
Assert.False(ds.FileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}file/").Exists);
Assert.Empty(ds.FileSystem.DirectoryInfo.New($"{testDirectory}").GetDirectories());
Assert.True(ds.FileSystem.DirectoryInfo.New(testDirectory).Exists);
Assert.False(ds.FileSystem.DirectoryInfo.New($"{testDirectory}file/").Exists);
}
#endregion
@ -587,7 +587,7 @@ public class DirectoryServiceTests
ds.CopyFilesToDirectory(new []{MockUnixSupport.Path($"{testDirectory}file.zip")}, "/manga/output/");
ds.CopyFilesToDirectory(new []{MockUnixSupport.Path($"{testDirectory}file.zip")}, "/manga/output/");
var outputFiles = ds.GetFiles("/manga/output/").Select(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath).ToList();
Assert.Equal(4, outputFiles.Count()); // we have 2 already there and 2 copies
Assert.Equal(4, outputFiles.Count); // we have 2 already there and 2 copies
// For some reason, this has C:/ on directory even though everything is emulated (System.IO.Abstractions issue, not changing)
// https://github.com/TestableIO/System.IO.Abstractions/issues/831
Assert.True(outputFiles.Contains(API.Services.Tasks.Scanner.Parser.Parser.NormalizePath("/manga/output/file (3).zip"))
@ -645,10 +645,10 @@ public class DirectoryServiceTests
const string testDirectory = "/manga/";
var fileSystem = new MockFileSystem();
fileSystem.AddDirectory($"{testDirectory}dir1");
var di = fileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}dir1");
var di = fileSystem.DirectoryInfo.New($"{testDirectory}dir1");
di.Attributes |= FileAttributes.System;
fileSystem.AddDirectory($"{testDirectory}dir2");
di = fileSystem.DirectoryInfo.FromDirectoryName($"{testDirectory}dir2");
di = fileSystem.DirectoryInfo.New($"{testDirectory}dir2");
di.Attributes |= FileAttributes.Hidden;
fileSystem.AddDirectory($"{testDirectory}dir3");
fileSystem.AddFile($"{testDirectory}file_0.zip", new MockFileData(""));

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Common;
using System.IO.Abstractions.TestingHelpers;
@ -9,15 +8,13 @@ using API.Data;
using API.Data.Metadata;
using API.Entities;
using API.Entities.Enums;
using API.Extensions;
using API.Parser;
using API.Services;
using API.Services.Tasks.Scanner;
using API.Services.Tasks.Scanner.Parser;
using API.SignalR;
using API.Tests.Helpers;
using AutoMapper;
using DotNet.Globbing;
using Flurl.Util;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@ -254,7 +251,7 @@ public class ParseScannedFilesTests
var foundParsedSeries = new ParsedSeries()
{
Name = parsedFiles.First().Series,
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize(parsedFiles.First().Series),
NormalizedName = parsedFiles.First().Series.ToNormalized(),
Format = parsedFiles.First().Format
};

File diff suppressed because it is too large Load diff

View file

@ -11,10 +11,12 @@ using API.DTOs.ReadingLists;
using API.DTOs.ReadingLists.CBL;
using API.Entities;
using API.Entities.Enums;
using API.Extensions;
using API.Helpers;
using API.Services;
using API.SignalR;
using API.Tests.Helpers;
using API.Tests.Helpers.Builders;
using AutoMapper;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
@ -44,7 +46,7 @@ public class ReadingListServiceTests
var config = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperProfiles>());
var mapper = config.CreateMapper();
_unitOfWork = new UnitOfWork(_context, mapper, null);
_unitOfWork = new UnitOfWork(_context, mapper, null!);
_readingListService = new ReadingListService(_unitOfWork, Substitute.For<ILogger<ReadingListService>>(), Substitute.For<IEventHub>());
}
@ -124,36 +126,26 @@ public class ReadingListServiceTests
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>()),
Volumes = new List<Volume>()
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>()
{
new Volume()
{
Name = "0",
Chapters = new List<Chapter>()
{
new Chapter()
{
Number = "1",
AgeRating = AgeRating.Everyone,
},
new Chapter()
{
Number = "2",
AgeRating = AgeRating.X18Plus
},
new Chapter()
{
Number = "3",
AgeRating = AgeRating.X18Plus
}
}
}
}
}
new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.WithAgeRating(AgeRating.Everyone)
.Build()
)
.WithChapter(new ChapterBuilder("2")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.WithChapter(new ChapterBuilder("3")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.Build()
})
.Build(),
}
},
}
@ -162,8 +154,8 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = new ReadingList();
user.ReadingLists = new List<ReadingList>()
var readingList = DbFactory.ReadingList("test");
user!.ReadingLists = new List<ReadingList>()
{
readingList
};
@ -191,36 +183,26 @@ public class ReadingListServiceTests
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>()),
Volumes = new List<Volume>()
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>()
{
new Volume()
{
Name = "0",
Chapters = new List<Chapter>()
{
new Chapter()
{
Number = "1",
AgeRating = AgeRating.Everyone,
},
new Chapter()
{
Number = "2",
AgeRating = AgeRating.X18Plus
},
new Chapter()
{
Number = "3",
AgeRating = AgeRating.X18Plus
}
}
}
}
}
new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.WithAgeRating(AgeRating.Everyone)
.Build()
)
.WithChapter(new ChapterBuilder("2")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.WithChapter(new ChapterBuilder("3")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.Build()
})
.Build()
}
},
}
@ -229,8 +211,8 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = new ReadingList();
user.ReadingLists = new List<ReadingList>()
var readingList = DbFactory.ReadingList("test");
user!.ReadingLists = new List<ReadingList>()
{
readingList
};
@ -265,36 +247,26 @@ public class ReadingListServiceTests
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>()),
Volumes = new List<Volume>()
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>()
{
new Volume()
{
Name = "0",
Chapters = new List<Chapter>()
{
new Chapter()
{
Number = "1",
AgeRating = AgeRating.Everyone,
},
new Chapter()
{
Number = "2",
AgeRating = AgeRating.X18Plus
},
new Chapter()
{
Number = "3",
AgeRating = AgeRating.X18Plus
}
}
}
}
}
new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.WithAgeRating(AgeRating.Everyone)
.Build()
)
.WithChapter(new ChapterBuilder("2")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.WithChapter(new ChapterBuilder("3")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.Build()
})
.Build()
}
},
}
@ -303,7 +275,7 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = new ReadingList();
var readingList = DbFactory.ReadingList("Test");
user.ReadingLists = new List<ReadingList>()
{
readingList
@ -341,36 +313,26 @@ public class ReadingListServiceTests
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>()),
Volumes = new List<Volume>()
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>()
{
new Volume()
{
Name = "0",
Chapters = new List<Chapter>()
{
new Chapter()
{
Number = "1",
AgeRating = AgeRating.Everyone,
},
new Chapter()
{
Number = "2",
AgeRating = AgeRating.X18Plus
},
new Chapter()
{
Number = "3",
AgeRating = AgeRating.X18Plus
}
}
}
}
}
new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.WithAgeRating(AgeRating.Everyone)
.Build()
)
.WithChapter(new ChapterBuilder("2")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.WithChapter(new ChapterBuilder("3")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.Build()
})
.Build()
}
},
}
@ -379,8 +341,8 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = new ReadingList();
user.ReadingLists = new List<ReadingList>()
var readingList = DbFactory.ReadingList("test");
user!.ReadingLists = new List<ReadingList>()
{
readingList
};
@ -436,31 +398,22 @@ public class ReadingListServiceTests
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>()),
Volumes = new List<Volume>()
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>()
{
new Volume()
{
Name = "0",
Chapters = new List<Chapter>()
{
new Chapter()
{
Number = "1",
AgeRating = AgeRating.Everyone
},
new Chapter()
{
Number = "2",
AgeRating = AgeRating.X18Plus
}
}
}
}
}
new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.WithAgeRating(AgeRating.Everyone)
.Build()
)
.WithChapter(new ChapterBuilder("2")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.Build()
})
.Build(),
}
},
}
@ -469,7 +422,7 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = new ReadingList();
var readingList = DbFactory.ReadingList("Test");
user.ReadingLists = new List<ReadingList>()
{
readingList
@ -508,39 +461,26 @@ public class ReadingListServiceTests
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>()),
Volumes = new List<Volume>()
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>()
{
new Volume()
{
Name = "0",
Chapters = new List<Chapter>()
{
new Chapter()
{
Number = "1",
AgeRating = AgeRating.Everyone,
Pages = 1
},
new Chapter()
{
Number = "2",
AgeRating = AgeRating.X18Plus,
Pages = 1
},
new Chapter()
{
Number = "3",
AgeRating = AgeRating.X18Plus,
Pages = 1
}
}
}
}
}
new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.WithAgeRating(AgeRating.Everyone)
.Build()
)
.WithChapter(new ChapterBuilder("2")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.WithChapter(new ChapterBuilder("3")
.WithAgeRating(AgeRating.X18Plus)
.Build()
)
.Build()
})
.Build()
}
},
}
@ -549,7 +489,7 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists | AppUserIncludes.Progress);
var readingList = new ReadingList();
var readingList = DbFactory.ReadingList("Test");
user.ReadingLists = new List<ReadingList>()
{
readingList
@ -594,29 +534,20 @@ public class ReadingListServiceTests
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>()),
Volumes = new List<Volume>()
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>()
{
new Volume()
{
Name = "0",
Chapters = new List<Chapter>()
{
new Chapter()
{
Number = "1",
},
new Chapter()
{
Number = "2",
}
}
}
}
}
new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.Build()
)
.WithChapter(new ChapterBuilder("2")
.Build()
)
.Build()
})
.Build()
}
},
}
@ -625,8 +556,8 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = new ReadingList();
user.ReadingLists = new List<ReadingList>()
var readingList = DbFactory.ReadingList("Test");
user!.ReadingLists = new List<ReadingList>()
{
readingList
};
@ -645,29 +576,20 @@ public class ReadingListServiceTests
public async Task CalculateAgeRating_ShouldUpdateToMax()
{
await ResetDb();
var s = new Series()
{
Name = "Test",
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>()),
Volumes = new List<Volume>()
var s = new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>()
{
new Volume()
{
Name = "0",
Chapters = new List<Chapter>()
{
new Chapter()
{
Number = "1",
},
new Chapter()
{
Number = "2",
}
}
}
}
};
new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1")
.Build()
)
.WithChapter(new ChapterBuilder("2")
.Build()
)
.Build()
})
.Build();
_context.AppUser.Add(new AppUser()
{
UserName = "majora2007",
@ -691,7 +613,7 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = new ReadingList();
var readingList = DbFactory.ReadingList("Test");
user.ReadingLists = new List<ReadingList>()
{
readingList
@ -1108,33 +1030,53 @@ public class ReadingListServiceTests
var cblReadingList = LoadCblFromPath("Fables.cbl");
// Mock up our series
var fablesSeries = DbFactory.Series("Fables");
var fables2Series = DbFactory.Series("Fables: The Last Castle");
// var fablesSeries = DbFactory.Series("Fables");
// var fables2Series = DbFactory.Series("Fables: The Last Castle");
fablesSeries.Volumes.Add(new Volume()
{
Number = 1,
Name = "2002",
Chapters = new List<Chapter>()
{
EntityFactory.CreateChapter("1", false),
EntityFactory.CreateChapter("2", false),
EntityFactory.CreateChapter("3", false),
var fablesSeries = new SeriesBuilder("Fables")
.WithVolume(new VolumeBuilder("2002")
.WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build())
.WithChapter(new ChapterBuilder("3").Build())
.Build())
.Build();
}
});
fables2Series.Volumes.Add(new Volume()
{
Number = 1,
Name = "2003",
Chapters = new List<Chapter>()
{
EntityFactory.CreateChapter("1", false),
EntityFactory.CreateChapter("2", false),
EntityFactory.CreateChapter("3", false),
var fables2Series = new SeriesBuilder("Fables: The Last Castle")
.WithVolume(new VolumeBuilder("2003")
.WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build())
.WithChapter(new ChapterBuilder("3").Build())
.Build())
.Build();
}
});
// fablesSeries.Volumes.Add(new Volume()
// {
// Number = 1,
// Name = "2002",
// Chapters = new List<Chapter>()
// {
// EntityFactory.CreateChapter("1", false),
// EntityFactory.CreateChapter("2", false),
// EntityFactory.CreateChapter("3", false),
//
// }
// });
// fables2Series.Volumes.Add(new Volume()
// {
// Number = 1,
// Name = "2003",
// Chapters = new List<Chapter>()
// {
// EntityFactory.CreateChapter("1", false),
// EntityFactory.CreateChapter("2", false),
// EntityFactory.CreateChapter("3", false),
//
// }
// });
_context.AppUser.Add(new AppUser()
{

View file

@ -3,10 +3,12 @@ using System.Linq;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Parser;
using API.Services.Tasks;
using API.Services.Tasks.Scanner;
using API.Tests.Helpers;
using API.Tests.Helpers.Builders;
using Xunit;
namespace API.Tests.Services;
@ -23,23 +25,14 @@ public class ScannerServiceTests
var existingSeries = new List<Series>
{
new Series()
{
Name = "Darker Than Black",
LocalizedName = "Darker Than Black",
OriginalName = "Darker Than Black",
Volumes = new List<Volume>()
{
new Volume()
{
Number = 1,
Name = "1"
}
},
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker Than Black"),
Metadata = new SeriesMetadata(),
Format = MangaFormat.Epub
}
new SeriesBuilder("Darker Than Black")
.WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithName("1")
.Build())
.WithLocalizedName("Darker Than Black")
.Build()
};
Assert.Equal(1, ScannerService.FindSeriesNotOnDisk(existingSeries, infos).Count());
@ -56,76 +49,42 @@ public class ScannerServiceTests
var existingSeries = new List<Series>
{
new Series()
{
Name = "Cage of Eden",
LocalizedName = "Cage of Eden",
OriginalName = "Cage of Eden",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Cage of Eden"),
Metadata = new SeriesMetadata(),
Format = MangaFormat.Archive
},
new Series()
{
Name = "Darker Than Black",
LocalizedName = "Darker Than Black",
OriginalName = "Darker Than Black",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Darker Than Black"),
Metadata = new SeriesMetadata(),
Format = MangaFormat.Archive
}
new SeriesBuilder("Cage of Eden")
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithName("1")
.Build())
.WithLocalizedName("Darker Than Black")
.Build(),
new SeriesBuilder("Darker Than Black")
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithName("1")
.Build())
.WithLocalizedName("Darker Than Black")
.Build(),
// new Series()
// {
// Name = "Cage of Eden",
// LocalizedName = "Cage of Eden",
// OriginalName = "Cage of Eden",
// NormalizedName = "Darker Than Black".ToNormalized(),
// Metadata = new SeriesMetadata(),
// Format = MangaFormat.Archive
// },
// new Series()
// {
// Name = "Darker Than Black",
// LocalizedName = "Darker Than Black",
// OriginalName = "Darker Than Black",
// NormalizedName = "Darker Than Black".ToNormalized(),
// Metadata = new SeriesMetadata(),
// Format = MangaFormat.Archive
// }
};
Assert.Empty(ScannerService.FindSeriesNotOnDisk(existingSeries, infos));
}
// TODO: Figure out how to do this with ParseScannedFiles
// [Theory]
// [InlineData(new [] {"Darker than Black"}, "Darker than Black", "Darker than Black")]
// [InlineData(new [] {"Darker than Black"}, "Darker Than Black", "Darker than Black")]
// [InlineData(new [] {"Darker than Black"}, "Darker Than Black!", "Darker than Black")]
// [InlineData(new [] {""}, "Runaway Jack", "Runaway Jack")]
// public void MergeNameTest(string[] existingSeriesNames, string parsedInfoName, string expected)
// {
// var collectedSeries = new ConcurrentDictionary<ParsedSeries, List<ParserInfo>>();
// foreach (var seriesName in existingSeriesNames)
// {
// AddToParsedInfo(collectedSeries, new ParserInfo() {Series = seriesName, Format = MangaFormat.Archive});
// }
//
// var actualName = new ParseScannedFiles(_bookService, _logger).MergeName(collectedSeries, new ParserInfo()
// {
// Series = parsedInfoName,
// Format = MangaFormat.Archive
// });
//
// Assert.Equal(expected, actualName);
// }
// [Fact]
// public void RemoveMissingSeries_Should_RemoveSeries()
// {
// var existingSeries = new List<Series>()
// {
// EntityFactory.CreateSeries("Darker than Black Vol 1"),
// EntityFactory.CreateSeries("Darker than Black"),
// EntityFactory.CreateSeries("Beastars"),
// };
// var missingSeries = new List<Series>()
// {
// EntityFactory.CreateSeries("Darker than Black Vol 1"),
// };
// existingSeries = ScannerService.RemoveMissingSeries(existingSeries, missingSeries, out var removeCount).ToList();
//
// Assert.DoesNotContain(missingSeries[0].Name, existingSeries.Select(s => s.Name));
// Assert.Equal(missingSeries.Count, removeCount);
// }
// TODO: I want a test for UpdateSeries where if I have chapter 10 and now it's mapping into Vol 2 Chapter 10,
// if I can do it without deleting the underlying chapter (aka id change)
}

View file

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using System.Threading.Tasks;
using API.Data;
@ -14,14 +12,10 @@ using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Helpers;
using API.Services;
using API.SignalR;
using API.Tests.Helpers;
using AutoMapper;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using API.Tests.Helpers.Builders;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
@ -93,28 +87,22 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("Omake", true, new List<MangaFile>()),
EntityFactory.CreateChapter("Something SP02", true, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("21", false, new List<MangaFile>()),
EntityFactory.CreateChapter("22", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>()),
EntityFactory.CreateChapter("32", false, new List<MangaFile>()),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("Omake").WithIsSpecial(true).WithTitle("Omake").WithPages(1).Build())
.WithChapter(new ChapterBuilder("Something SP02").WithIsSpecial(true).WithTitle("Something").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -147,28 +135,22 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Manga,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>()),
EntityFactory.CreateChapter("2", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("21", false, new List<MangaFile>()),
EntityFactory.CreateChapter("22", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>()),
EntityFactory.CreateChapter("32", false, new List<MangaFile>()),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -201,26 +183,20 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Manga,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>()),
EntityFactory.CreateChapter("2", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>()),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -253,26 +229,20 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Manga,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>()),
EntityFactory.CreateChapter("2", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>()),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -308,21 +278,16 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -354,21 +319,15 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("Ano Orokamono ni mo Kyakkou wo! - Volume 1.epub", true, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("Ano Orokamono ni mo Kyakkou wo! - Volume 2.epub", false, new List<MangaFile>()),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("Ano Orokamono ni mo Kyakkou wo! - Volume 1.epub", "Ano Orokamono ni mo Kyakkou wo! - Volume 1.epub").WithIsSpecial(true).WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("Ano Orokamono ni mo Kyakkou wo! - Volume 2.epub", "Ano Orokamono ni mo Kyakkou wo! - Volume 2.epub").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -407,25 +366,19 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Manga,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("1.2", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1.2")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -462,17 +415,12 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Manga,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>(), 1),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -516,17 +464,12 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Manga,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>(), 1),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -587,17 +530,12 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Manga,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>(), 1),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -639,17 +577,12 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Manga,
Series = new List<Series>()
{
new Series()
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>(), 1),
}),
}
}
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build())
.Build(),
}
});
@ -678,14 +611,16 @@ public class SeriesServiceTests : AbstractDbTest
public async Task UpdateSeriesMetadata_ShouldCreateEmptyMetadata_IfDoesntExist()
{
await ResetDb();
_context.Series.Add(new Series()
var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library() {
Name = "Test LIb",
Type = LibraryType.Book,
}
});
Name = "Test LIb",
Type = LibraryType.Book,
};
_context.Series.Add(s);
await _context.SaveChangesAsync();
var success = await _seriesService.UpdateSeriesMetadata(new UpdateSeriesMetadataDto()
@ -710,14 +645,16 @@ public class SeriesServiceTests : AbstractDbTest
public async Task UpdateSeriesMetadata_ShouldCreateNewTags_IfNoneExist()
{
await ResetDb();
_context.Series.Add(new Series()
var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library() {
Name = "Test LIb",
Type = LibraryType.Book,
}
});
Name = "Test LIb",
Type = LibraryType.Book,
};
_context.Series.Add(s);
await _context.SaveChangesAsync();
var success = await _seriesService.UpdateSeriesMetadata(new UpdateSeriesMetadataDto()
@ -752,16 +689,15 @@ public class SeriesServiceTests : AbstractDbTest
public async Task UpdateSeriesMetadata_ShouldRemoveExistingTags()
{
await ResetDb();
var s = new Series()
var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Book,
},
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>())
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Genre("Existing Genre");
s.Metadata.Genres = new List<Genre>() {g};
_context.Series.Add(s);
@ -791,16 +727,15 @@ public class SeriesServiceTests : AbstractDbTest
public async Task UpdateSeriesMetadata_ShouldAddNewPerson_NoExistingPeople()
{
await ResetDb();
var s = new Series()
var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Book,
},
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>())
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Person("Existing Person", PersonRole.Publisher);
_context.Series.Add(s);
@ -829,15 +764,13 @@ public class SeriesServiceTests : AbstractDbTest
public async Task UpdateSeriesMetadata_ShouldAddNewPerson_ExistingPeople()
{
await ResetDb();
var s = new Series()
var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Book,
},
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>())
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Person("Existing Person", PersonRole.Publisher);
s.Metadata.People = new List<Person>() {DbFactory.Person("Existing Writer", PersonRole.Writer),
@ -871,15 +804,13 @@ public class SeriesServiceTests : AbstractDbTest
public async Task UpdateSeriesMetadata_ShouldRemoveExistingPerson()
{
await ResetDb();
var s = new Series()
var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Book,
},
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>())
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Person("Existing Person", PersonRole.Publisher);
_context.Series.Add(s);
@ -908,15 +839,13 @@ public class SeriesServiceTests : AbstractDbTest
public async Task UpdateSeriesMetadata_ShouldLockIfTold()
{
await ResetDb();
var s = new Series()
var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Book,
},
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>())
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Genre("Existing Genre");
s.Metadata.Genres = new List<Genre>() {g};
@ -949,15 +878,13 @@ public class SeriesServiceTests : AbstractDbTest
public async Task UpdateSeriesMetadata_ShouldNotUpdateReleaseYear_IfLessThan1000()
{
await ResetDb();
var s = new Series()
var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build())
.Build();
s.Library = new Library()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Book,
},
Metadata = DbFactory.SeriesMetadata(new List<CollectionTag>())
Name = "Test LIb",
Type = LibraryType.Book,
};
_context.Series.Add(s);
await _context.SaveChangesAsync();
@ -986,43 +913,37 @@ public class SeriesServiceTests : AbstractDbTest
private static Series CreateSeriesMock()
{
var files = new List<MangaFile>()
var file = EntityFactory.CreateMangaFile("Test.cbz", MangaFormat.Archive, 1);
var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("A Special Case").WithIsSpecial(true).WithFile(file).WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).WithFile(file).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("22").WithPages(1).WithFile(file).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).WithFile(file).Build())
.Build())
.Build();
series.Library = new Library()
{
EntityFactory.CreateMangaFile("Test.cbz", MangaFormat.Archive, 1)
};
return new Series()
{
Name = "Test",
Library = new Library()
{
Name = "Test LIb",
Type = LibraryType.Manga,
},
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, files, 1),
EntityFactory.CreateChapter("96", false, files, 1),
EntityFactory.CreateChapter("A Special Case", true, files, 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, files, 1),
EntityFactory.CreateChapter("2", false, files, 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("21", false, files, 1),
EntityFactory.CreateChapter("22", false, files, 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, files, 1),
EntityFactory.CreateChapter("32", false, files, 1),
}),
}
Name = "Test LIb",
Type = LibraryType.Manga,
};
return series;
}
[Fact]
@ -1082,21 +1003,9 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test Series",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Prequels",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Sequels",
Volumes = new List<Volume>(){}
}
new SeriesBuilder("Test Series").Build(),
new SeriesBuilder("Test Series Prequels").Build(),
new SeriesBuilder("Test Series Sequels").Build(),
}
});
@ -1129,21 +1038,9 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test Series",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Prequels",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Sequels",
Volumes = new List<Volume>(){}
}
DbFactory.Series("Test Series"),
DbFactory.Series("Test Series Prequels"),
DbFactory.Series("Test Series Sequels"),
}
});
@ -1183,16 +1080,8 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Series A",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Series B",
Volumes = new List<Volume>(){}
},
DbFactory.Series("Series A"),
DbFactory.Series("Series B"),
}
});
@ -1236,16 +1125,8 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Series A",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Series B",
Volumes = new List<Volume>(){}
},
DbFactory.Series("Series A"),
DbFactory.Series("Series B"),
}
});
@ -1289,16 +1170,8 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test Series",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Prequels",
Volumes = new List<Volume>(){}
}
DbFactory.Series("Test Series"),
DbFactory.Series("Test Series Prequels"),
}
});
@ -1342,31 +1215,11 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test Series",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Editions",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Prequels",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Sequels",
Volumes = new List<Volume>(){}
},
new Series()
{
Name = "Test Series Adaption",
Volumes = new List<Volume>(){}
}
DbFactory.Series("Test Series"),
DbFactory.Series("Test Series Editions"),
DbFactory.Series("Test Series Prequels"),
DbFactory.Series("Test Series Sequels"),
DbFactory.Series("Test Series Adaption"),
}
});
await _context.SaveChangesAsync();
@ -1403,21 +1256,9 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test Series",
Volumes = new List<Volume>() { }
},
new Series()
{
Name = "Test Series Prequels",
Volumes = new List<Volume>() { }
},
new Series()
{
Name = "Test Series Sequels",
Volumes = new List<Volume>() { }
}
DbFactory.Series("Test Series"),
DbFactory.Series("Test Series Prequels"),
DbFactory.Series("Test Series Sequels"),
}
};
_context.Library.Add(lib);
@ -1463,40 +1304,17 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test Series",
Volumes = new List<Volume>()
{
new Volume()
new SeriesBuilder("Test Series")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithFile(new MangaFile()
{
Chapters = new List<Chapter>()
{
new Chapter()
{
Files = new List<MangaFile>()
{
new MangaFile()
{
Pages = 1,
FilePath = "fake file"
}
}
}
}
}
}
},
new Series()
{
Name = "Test Series Prequels",
Volumes = new List<Volume>() { }
},
new Series()
{
Name = "Test Series Sequels",
Volumes = new List<Volume>() { }
}
Pages = 1,
FilePath = "fake file"
}).Build())
.Build())
.Build(),
new SeriesBuilder("Test Series Prequels").Build(),
new SeriesBuilder("Test Series Sequels").Build(),
}
};
_context.Library.Add(lib1);
@ -1513,21 +1331,9 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book,
Series = new List<Series>()
{
new Series()
{
Name = "Test Series 2",
Volumes = new List<Volume>() { }
},
new Series()
{
Name = "Test Series Prequels 2",
Volumes = new List<Volume>() { }
},
new Series()
{
Name = "Test Series Sequels 2",
Volumes = new List<Volume>() { }
}
DbFactory.Series("Test Series 2"),
DbFactory.Series("Test Series Prequels 2"),
DbFactory.Series("Test Series Prequels 2"),
}
};
_context.Library.Add(lib2);

View file

@ -1,138 +1,71 @@
using System.Collections.Generic;
using System.Data.Common;
using System.IO.Abstractions.TestingHelpers;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using System.Threading.Tasks;
using API.Data;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Enums.Theme;
using API.Entities.Enums.UserPreferences;
using API.Helpers;
using API.Extensions;
using API.Services;
using API.Services.Tasks;
using API.SignalR;
using AutoMapper;
using Kavita.Common;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
using Xunit.Abstractions;
namespace API.Tests.Services;
public class SiteThemeServiceTests
public abstract class SiteThemeServiceTest : AbstractDbTest
{
private readonly ILogger<ThemeService> _logger = Substitute.For<ILogger<ThemeService>>();
private readonly ITestOutputHelper _testOutputHelper;
private readonly IEventHub _messageHub = Substitute.For<IEventHub>();
private readonly DbConnection _connection;
private readonly DataContext _context;
private readonly IUnitOfWork _unitOfWork;
private const string CacheDirectory = "C:/kavita/config/cache/";
private const string CoverImageDirectory = "C:/kavita/config/covers/";
private const string BackupDirectory = "C:/kavita/config/backups/";
private const string BookmarkDirectory = "C:/kavita/config/bookmarks/";
private const string SiteThemeDirectory = "C:/kavita/config/themes/";
public SiteThemeServiceTests()
protected SiteThemeServiceTest(ITestOutputHelper testOutputHelper) : base()
{
var contextOptions = new DbContextOptionsBuilder()
.UseSqlite(CreateInMemoryDatabase())
.Options;
_connection = RelationalOptionsExtension.Extract(contextOptions).Connection;
_context = new DataContext(contextOptions);
Task.Run(SeedDb).GetAwaiter().GetResult();
var config = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperProfiles>());
var mapper = config.CreateMapper();
_unitOfWork = new UnitOfWork(_context, mapper, null);
_testOutputHelper = testOutputHelper;
}
#region Setup
private static DbConnection CreateInMemoryDatabase()
{
var connection = new SqliteConnection("Filename=:memory:");
connection.Open();
return connection;
}
private async Task<bool> SeedDb()
{
await _context.Database.MigrateAsync();
var filesystem = CreateFileSystem();
await Seed.SeedSettings(_context, new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem));
var setting = await _context.ServerSetting.Where(s => s.Key == ServerSettingKey.CacheDirectory).SingleAsync();
setting.Value = CacheDirectory;
setting = await _context.ServerSetting.Where(s => s.Key == ServerSettingKey.BackupDirectory).SingleAsync();
setting.Value = BackupDirectory;
setting = await _context.ServerSetting.Where(s => s.Key == ServerSettingKey.BookmarkDirectory).SingleAsync();
setting.Value = BookmarkDirectory;
_context.ServerSetting.Update(setting);
_context.AppUser.Add(new AppUser()
{
UserName = "Joe",
UserPreferences = new AppUserPreferences
{
Theme = Seed.DefaultThemes[0]
}
});
_context.Library.Add(new Library()
{
Name = "Manga",
Folders = new List<FolderPath>()
{
new FolderPath()
{
Path = "C:/data/"
}
}
});
return await _context.SaveChangesAsync() > 0;
}
private static MockFileSystem CreateFileSystem()
{
var fileSystem = new MockFileSystem();
fileSystem.Directory.SetCurrentDirectory("C:/kavita/");
fileSystem.AddDirectory("C:/kavita/config/");
fileSystem.AddDirectory(CacheDirectory);
fileSystem.AddDirectory(CoverImageDirectory);
fileSystem.AddDirectory(BackupDirectory);
fileSystem.AddDirectory(BookmarkDirectory);
fileSystem.AddDirectory(SiteThemeDirectory);
fileSystem.AddDirectory("C:/data/");
return fileSystem;
}
private async Task ResetDb()
protected override async Task ResetDb()
{
_context.SiteTheme.RemoveRange(_context.SiteTheme);
await _context.SaveChangesAsync();
// Recreate defaults
await Seed.SeedThemes(_context);
}
#endregion
[Fact]
public async Task UpdateDefault_ShouldThrowOnInvalidId()
{
await ResetDb();
_testOutputHelper.WriteLine($"[UpdateDefault_ShouldThrowOnInvalidId] All Themes: {(await _unitOfWork.SiteThemeRepository.GetThemes()).Count(t => t.IsDefault)}");
var filesystem = CreateFileSystem();
filesystem.AddFile($"{SiteThemeDirectory}custom.css", new MockFileData("123"));
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem);
var siteThemeService = new ThemeService(ds, _unitOfWork, _messageHub);
_context.SiteTheme.Add(new SiteTheme()
{
Name = "Custom",
NormalizedName = "Custom".ToNormalized(),
Provider = ThemeProvider.User,
FileName = "custom.css",
IsDefault = false
});
await _context.SaveChangesAsync();
var ex = await Assert.ThrowsAsync<KavitaException>(async () => await siteThemeService.UpdateDefault(10));
Assert.Equal("Theme file missing or invalid", ex.Message);
}
[Fact]
public async Task Scan_ShouldFindCustomFile()
{
await ResetDb();
_testOutputHelper.WriteLine($"[Scan_ShouldOnlyInsertOnceOnSecondScan] All Themes: {(await _unitOfWork.SiteThemeRepository.GetThemes()).Count(t => t.IsDefault)}");
var filesystem = CreateFileSystem();
filesystem.AddFile($"{SiteThemeDirectory}custom.css", new MockFileData(""));
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem);
@ -146,6 +79,8 @@ public class SiteThemeServiceTests
public async Task Scan_ShouldOnlyInsertOnceOnSecondScan()
{
await ResetDb();
_testOutputHelper.WriteLine(
$"[Scan_ShouldOnlyInsertOnceOnSecondScan] All Themes: {(await _unitOfWork.SiteThemeRepository.GetThemes()).Count(t => t.IsDefault)}");
var filesystem = CreateFileSystem();
filesystem.AddFile($"{SiteThemeDirectory}custom.css", new MockFileData(""));
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem);
@ -157,7 +92,8 @@ public class SiteThemeServiceTests
await siteThemeService.Scan();
var customThemes = (await _unitOfWork.SiteThemeRepository.GetThemeDtos()).Where(t =>
API.Services.Tasks.Scanner.Parser.Parser.Normalize(t.Name).Equals(API.Services.Tasks.Scanner.Parser.Parser.Normalize("custom")));
t.Name.ToNormalized().Equals("custom".ToNormalized()));
Assert.Single(customThemes);
}
@ -165,6 +101,7 @@ public class SiteThemeServiceTests
public async Task Scan_ShouldDeleteWhenFileDoesntExistOnSecondScan()
{
await ResetDb();
_testOutputHelper.WriteLine($"[Scan_ShouldDeleteWhenFileDoesntExistOnSecondScan] All Themes: {(await _unitOfWork.SiteThemeRepository.GetThemes()).Count(t => t.IsDefault)}");
var filesystem = CreateFileSystem();
filesystem.AddFile($"{SiteThemeDirectory}custom.css", new MockFileData(""));
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem);
@ -176,16 +113,17 @@ public class SiteThemeServiceTests
filesystem.RemoveFile($"{SiteThemeDirectory}custom.css");
await siteThemeService.Scan();
var customThemes = (await _unitOfWork.SiteThemeRepository.GetThemeDtos()).Where(t =>
API.Services.Tasks.Scanner.Parser.Parser.Normalize(t.Name).Equals(API.Services.Tasks.Scanner.Parser.Parser.Normalize("custom")));
var themes = (await _unitOfWork.SiteThemeRepository.GetThemeDtos());
Assert.Empty(customThemes);
Assert.Equal(0, themes.Count(t =>
t.Name.ToNormalized().Equals("custom".ToNormalized())));
}
[Fact]
public async Task GetContent_ShouldReturnContent()
{
await ResetDb();
_testOutputHelper.WriteLine($"[GetContent_ShouldReturnContent] All Themes: {(await _unitOfWork.SiteThemeRepository.GetThemes()).Count(t => t.IsDefault)}");
var filesystem = CreateFileSystem();
filesystem.AddFile($"{SiteThemeDirectory}custom.css", new MockFileData("123"));
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem);
@ -194,7 +132,7 @@ public class SiteThemeServiceTests
_context.SiteTheme.Add(new SiteTheme()
{
Name = "Custom",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Custom"),
NormalizedName = "Custom".ToNormalized(),
Provider = ThemeProvider.User,
FileName = "custom.css",
IsDefault = false
@ -211,6 +149,7 @@ public class SiteThemeServiceTests
public async Task UpdateDefault_ShouldHaveOneDefault()
{
await ResetDb();
_testOutputHelper.WriteLine($"[UpdateDefault_ShouldHaveOneDefault] All Themes: {(await _unitOfWork.SiteThemeRepository.GetThemes()).Count(t => t.IsDefault)}");
var filesystem = CreateFileSystem();
filesystem.AddFile($"{SiteThemeDirectory}custom.css", new MockFileData("123"));
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem);
@ -219,7 +158,7 @@ public class SiteThemeServiceTests
_context.SiteTheme.Add(new SiteTheme()
{
Name = "Custom",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Custom"),
NormalizedName = "Custom".ToNormalized(),
Provider = ThemeProvider.User,
FileName = "custom.css",
IsDefault = false
@ -228,6 +167,7 @@ public class SiteThemeServiceTests
var customTheme = (await _unitOfWork.SiteThemeRepository.GetThemeDtoByName("Custom"));
Assert.NotNull(customTheme);
await siteThemeService.UpdateDefault(customTheme.Id);
@ -235,31 +175,5 @@ public class SiteThemeServiceTests
Assert.Equal(customTheme.Id, (await _unitOfWork.SiteThemeRepository.GetDefaultTheme()).Id);
}
[Fact]
public async Task UpdateDefault_ShouldThrowOnInvalidId()
{
await ResetDb();
var filesystem = CreateFileSystem();
filesystem.AddFile($"{SiteThemeDirectory}custom.css", new MockFileData("123"));
var ds = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), filesystem);
var siteThemeService = new ThemeService(ds, _unitOfWork, _messageHub);
_context.SiteTheme.Add(new SiteTheme()
{
Name = "Custom",
NormalizedName = API.Services.Tasks.Scanner.Parser.Parser.Normalize("Custom"),
Provider = ThemeProvider.User,
FileName = "custom.css",
IsDefault = false
});
await _context.SaveChangesAsync();
var ex = await Assert.ThrowsAsync<KavitaException>(async () => await siteThemeService.UpdateDefault(10));
Assert.Equal("Theme file missing or invalid", ex.Message);
}
}

View file

@ -1,4 +1,7 @@
namespace API.Tests.Services;
using API.Extensions;
using API.Tests.Helpers.Builders;
namespace API.Tests.Services;
using System.Collections.Generic;
using System.Data.Common;
using System.IO.Abstractions.TestingHelpers;
@ -111,33 +114,25 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", true, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("3", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("4", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("32", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithIsSpecial(true).WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("3").WithPages(1).Build())
.WithChapter(new ChapterBuilder("4").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -169,33 +164,25 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", true, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("3", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("4", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("32", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithIsSpecial(true).WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("3").WithPages(1).Build())
.WithChapter(new ChapterBuilder("4").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -233,33 +220,25 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("21", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("23", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("32", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.WithChapter(new ChapterBuilder("22").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -296,33 +275,25 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", true, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("21", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("23", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("32", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithIsSpecial(true).WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.WithChapter(new ChapterBuilder("22").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -360,26 +331,19 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>(), 199),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>(), 192),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("0", false, new List<MangaFile>(), 255),
}),
},
Pages = 646
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("0").WithPages(199).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("0").WithPages(192).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("0").WithPages(255).Build())
.Build())
.WithPages(646)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -418,31 +382,23 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1997", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2002", new List<Chapter>()
{
EntityFactory.CreateChapter("2", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2005", new List<Chapter>()
{
EntityFactory.CreateChapter("3", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1997")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2002")
.WithChapter(new ChapterBuilder("2").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2005")
.WithChapter(new ChapterBuilder("3").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -485,33 +441,25 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", true, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("3", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("4", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("32", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithIsSpecial(true).WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("3").WithPages(1).Build())
.WithChapter(new ChapterBuilder("4").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -542,33 +490,25 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", true, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("3", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("4", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("32", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithIsSpecial(true).WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("3").WithPages(1).Build())
.WithChapter(new ChapterBuilder("4").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -606,33 +546,25 @@ public class TachiyomiServiceTests
{
await ResetDb();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("21", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("23", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("32", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.WithChapter(new ChapterBuilder("23").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var library = new Library()
{
Name = "Test LIb",
@ -668,34 +600,25 @@ public class TachiyomiServiceTests
public async Task MarkChaptersUntilAsRead_ShouldReturnEncodedVolume_Progress()
{
await ResetDb();
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithIsSpecial(true).WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.WithChapter(new ChapterBuilder("23").WithPages(1).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build())
.WithPages(7)
.Build();
var series = new Series
{
Name = "Test",
Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>()
{
EntityFactory.CreateChapter("95", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("96", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("1", true, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("2", new List<Chapter>()
{
EntityFactory.CreateChapter("21", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("23", false, new List<MangaFile>(), 1),
}),
EntityFactory.CreateVolume("3", new List<Chapter>()
{
EntityFactory.CreateChapter("31", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("32", false, new List<MangaFile>(), 1),
}),
},
Pages = 7
};
var library = new Library()
{
Name = "Test LIb",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Before After
Before After

View file

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using System.Threading.Tasks;
using API.Entities;