* Updated number inputs with a more mobile friendly control

* Started writing lots of unit tests on PersonHelper to try and hammer out foreign constraint

* Fixes side-nav actionable alignment

* Added some unit tests

* Buffed out the unit tests

* Applied input modes throughout the app

* Fixed a small bug in refresh token validation to make it work correctly

* Try out a new way to block multithreading from interacting with people during series metadata update.

* Fixed the lock code to properly lock, which should help with any constraint issues.

* Locking notes

* Tweaked locking on people to prevent a constraint issue. This slows down the scanner a bit, but not much. Will tweak after validating on a user's server.

* Replaced all DBFactory.Series with SeriesBuilder.

* Replaced all DBFactory.Volume() with VolumeBuilder

* Replaced SeriesMetadata with Builder

* Replaced DBFactory.CollectionTag

* Lots of refactoring to streamline entity creation

* Fixed one of the unit tests

* Refactored all of new Library()

* Removed tag and genre

* Removed new SeriesMetadata

* Refactored new Volume()

* MangaFile()

* ReadingList()

* Refactored all of Chapter and ReadingList

* Add title to all event widget flows

* Updated Base Url to inform user it doesn't work for docker users with non-root user.

* Added unit test coverage to FormatChapterTitle and FormatChapterName.

* Started on Unit test for scanner, but need to finish it later.

---------

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2023-03-19 12:52:44 -05:00 committed by GitHub
parent eec03d7e96
commit 385f61f9f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
105 changed files with 2257 additions and 2660 deletions

View File

@ -348,7 +348,7 @@ jobs:
context: . context: .
platforms: linux/amd64,linux/arm/v7,linux/arm64 platforms: linux/amd64,linux/arm/v7,linux/arm64
push: true push: true
tags: kizaing/kavita:latest, kizaing/kavita:${{ steps.parse-version.outputs.VERSION }}, ghcr.io/${{ github.repository_owner }}/kavita:latest, ghcr.io/${{ github.repository_owner }}/kavita:${{ steps.parse-version.outputs.VERSION }} tags: kizaing/kavita:latest, kizaing/kavita:${{ steps.parse-version.outputs.VERSION }}, ghcr.io/kareadita/kavita:latest, ghcr.io/kareadita/kavita:${{ steps.parse-version.outputs.VERSION }}
- name: Image digest - name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }} run: echo ${{ steps.docker_build.outputs.digest }}

View File

@ -7,6 +7,7 @@ using API.Data;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using API.Services; using API.Services;
using AutoMapper; using AutoMapper;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
@ -78,18 +79,9 @@ public abstract class AbstractDbTest
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Manga")
{ .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
Name = "Manga", .Build());
Folders = new List<FolderPath>()
{
new FolderPath()
{
Path = "C:/data/"
}
},
Series = new List<Series>()
});
return await _context.SaveChangesAsync() > 0; return await _context.SaveChangesAsync() > 0;
} }

View File

@ -1,27 +0,0 @@
using API.Data;
using API.Extensions;
using Xunit;
namespace API.Tests.Entities;
/// <summary>
/// Tests for <see cref="API.Entities.Series"/>
/// </summary>
public class SeriesTest
{
[Theory]
[InlineData("Darker than Black")]
public void CreateSeries(string name)
{
var key = name.ToNormalized();
var series = DbFactory.Series(name);
Assert.Equal(0, series.Id);
Assert.Equal(0, series.Pages);
Assert.Equal(name, series.Name);
Assert.Null(series.CoverImage);
Assert.Equal(name, series.LocalizedName);
Assert.Equal(name, series.SortName);
Assert.Equal(name, series.OriginalName);
Assert.Equal(key, series.NormalizedName);
}
}

View File

@ -4,7 +4,8 @@ using System.Linq;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Parser; using API.Helpers.Builders;
using API.Services.Tasks.Scanner.Parser;
using Xunit; using Xunit;
namespace API.Tests.Extensions; namespace API.Tests.Extensions;
@ -13,22 +14,15 @@ public class ChapterListExtensionsTests
{ {
private static Chapter CreateChapter(string range, string number, MangaFile file, bool isSpecial) private static Chapter CreateChapter(string range, string number, MangaFile file, bool isSpecial)
{ {
return new Chapter() return new ChapterBuilder(number, range)
{ .WithIsSpecial(isSpecial)
Range = range, .WithFile(file)
Number = number, .Build();
Files = new List<MangaFile>() {file},
IsSpecial = isSpecial
};
} }
private static MangaFile CreateFile(string file, MangaFormat format) private static MangaFile CreateFile(string file, MangaFormat format)
{ {
return new MangaFile() return new MangaFileBuilder(file, format).Build();
{
FilePath = file,
Format = format
};
} }
[Fact] [Fact]

View File

@ -3,7 +3,7 @@ using System.IO.Abstractions.TestingHelpers;
using System.Linq; using System.Linq;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Parser; using API.Helpers.Builders;
using API.Services; using API.Services;
using API.Services.Tasks.Scanner.Parser; using API.Services.Tasks.Scanner.Parser;
using API.Tests.Helpers; using API.Tests.Helpers;
@ -45,8 +45,10 @@ public class ParserInfoListExtensions
string.Empty)); string.Empty));
} }
var files = inputChapters.Select(s => EntityFactory.CreateMangaFile(s, MangaFormat.Archive, 199)).ToList(); var files = inputChapters.Select(s => new MangaFileBuilder(s, MangaFormat.Archive, 199).Build()).ToList();
var chapter = EntityFactory.CreateChapter("0-6", false, files); var chapter = new ChapterBuilder("0-6")
.WithFiles(files)
.Build();
Assert.Equal(expectedHasInfo, infos.HasInfo(chapter)); Assert.Equal(expectedHasInfo, infos.HasInfo(chapter));
} }

View File

@ -22,22 +22,13 @@ public class QueryableExtensionsTests
var items = new List<Series>() var items = new List<Series>()
{ {
new SeriesBuilder("Test 1") new SeriesBuilder("Test 1")
.WithMetadata( new SeriesMetadata() .WithMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
{
AgeRating = AgeRating.Teen,
})
.Build(), .Build(),
new SeriesBuilder("Test 2") new SeriesBuilder("Test 2")
.WithMetadata( new SeriesMetadata() .WithMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Unknown).Build())
{
AgeRating = AgeRating.Unknown,
})
.Build(), .Build(),
new SeriesBuilder("Test 3") new SeriesBuilder("Test 3")
.WithMetadata( new SeriesMetadata() .WithMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.X18Plus).Build())
{
AgeRating = AgeRating.X18Plus,
})
.Build() .Build()
}; };
@ -56,46 +47,16 @@ public class QueryableExtensionsTests
{ {
var items = new List<CollectionTag>() var items = new List<CollectionTag>()
{ {
new CollectionTag() new CollectionTagBuilder("Test")
{ .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
Title = "Test", .Build(),
NormalizedTitle = "Test".ToNormalized(), new CollectionTagBuilder("Test 2")
SeriesMetadatas = new List<SeriesMetadata>() .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Unknown).Build())
{ .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
new SeriesMetadata() .Build(),
{ new CollectionTagBuilder("Test 3")
AgeRating = AgeRating.Teen, .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.X18Plus).Build())
} .Build(),
}
},
new CollectionTag()
{
Title = "Test",
NormalizedTitle = "Test".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
{
AgeRating = AgeRating.Unknown,
},
new SeriesMetadata()
{
AgeRating = AgeRating.Teen,
}
}
},
new CollectionTag()
{
Title = "Test",
NormalizedTitle = "Test".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
{
AgeRating = AgeRating.X18Plus,
}
}
},
}; };
var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction() var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction()
@ -113,46 +74,16 @@ public class QueryableExtensionsTests
{ {
var items = new List<Genre>() var items = new List<Genre>()
{ {
new Genre() new GenreBuilder("A")
{ .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
Title = "A", .Build(),
NormalizedTitle = "A".ToNormalized(), new GenreBuilder("B")
SeriesMetadatas = new List<SeriesMetadata>() .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Unknown).Build())
{ .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
new SeriesMetadata() .Build(),
{ new GenreBuilder("C")
AgeRating = AgeRating.Teen, .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.X18Plus).Build())
} .Build(),
}
},
new Genre()
{
Title = "B",
NormalizedTitle = "B".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
{
AgeRating = AgeRating.Unknown,
},
new SeriesMetadata()
{
AgeRating = AgeRating.Teen,
}
}
},
new Genre()
{
Title = "C",
NormalizedTitle = "C".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
{
AgeRating = AgeRating.X18Plus,
}
}
},
}; };
var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction() var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction()
@ -170,46 +101,16 @@ public class QueryableExtensionsTests
{ {
var items = new List<Tag>() var items = new List<Tag>()
{ {
new Tag() new TagBuilder("Test 1")
{ .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
Title = "Test 1", .Build(),
NormalizedTitle = "Test 1".ToNormalized(), new TagBuilder("Test 2")
SeriesMetadatas = new List<SeriesMetadata>() .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Unknown).Build())
{ .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
new SeriesMetadata() .Build(),
{ new TagBuilder("Test 3")
AgeRating = AgeRating.Teen, .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.X18Plus).Build())
} .Build(),
}
},
new Tag()
{
Title = "Test 2",
NormalizedTitle = "Test 2".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
{
AgeRating = AgeRating.Unknown,
},
new SeriesMetadata()
{
AgeRating = AgeRating.Teen,
}
}
},
new Tag()
{
Title = "Test 3",
NormalizedTitle = "Test 3".ToNormalized(),
SeriesMetadatas = new List<SeriesMetadata>()
{
new SeriesMetadata()
{
AgeRating = AgeRating.X18Plus,
}
}
},
}; };
var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction() var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction()
@ -228,26 +129,14 @@ public class QueryableExtensionsTests
var items = new List<Person>() var items = new List<Person>()
{ {
new PersonBuilder("Test", PersonRole.Character) new PersonBuilder("Test", PersonRole.Character)
.WithSeriesMetadata(new SeriesMetadata() .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
{
AgeRating = AgeRating.Teen,
})
.Build(), .Build(),
new PersonBuilder("Test", PersonRole.Character) new PersonBuilder("Test", PersonRole.Character)
.WithSeriesMetadata(new SeriesMetadata() .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Unknown).Build())
{ .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.Teen).Build())
AgeRating = AgeRating.Unknown,
})
.WithSeriesMetadata(new SeriesMetadata()
{
AgeRating = AgeRating.Teen,
})
.Build(), .Build(),
new PersonBuilder("Test", PersonRole.Character) new PersonBuilder("Test", PersonRole.Character)
.WithSeriesMetadata(new SeriesMetadata() .WithSeriesMetadata(new SeriesMetadataBuilder().WithAgeRating(AgeRating.X18Plus).Build())
{
AgeRating = AgeRating.X18Plus,
})
.Build(), .Build(),
}; };
@ -267,9 +156,9 @@ public class QueryableExtensionsTests
var items = new List<ReadingList>() var items = new List<ReadingList>()
{ {
DbFactory.ReadingList("Test List", null, false, AgeRating.Teen), new ReadingListBuilder("Test List").WithRating(AgeRating.Teen).Build(),
DbFactory.ReadingList("Test List", null, false, AgeRating.Unknown), new ReadingListBuilder("Test List").WithRating(AgeRating.Unknown).Build(),
DbFactory.ReadingList("Test List", null, false, AgeRating.X18Plus), new ReadingListBuilder("Test List").WithRating(AgeRating.X18Plus).Build(),
}; };
var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction() var filtered = items.AsQueryable().RestrictAgainstAgeRestriction(new AgeRestriction()

View File

@ -2,6 +2,7 @@
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Helpers.Builders;
using API.Tests.Helpers; using API.Tests.Helpers;
using Xunit; using Xunit;
@ -16,16 +17,14 @@ public class VolumeListExtensionsTests
{ {
var volumes = new List<Volume>() var volumes = new List<Volume>()
{ {
EntityFactory.CreateVolume("1", new List<Chapter>() new VolumeBuilder("1")
{ .WithChapter(new ChapterBuilder("3").Build())
EntityFactory.CreateChapter("3", false), .WithChapter(new ChapterBuilder("4").Build())
EntityFactory.CreateChapter("4", false), .Build(),
}), new VolumeBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
EntityFactory.CreateVolume("0", new List<Chapter>() .WithChapter(new ChapterBuilder("1").Build())
{ .WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter).WithIsSpecial(true).Build())
EntityFactory.CreateChapter("1", false), .Build(),
EntityFactory.CreateChapter("0", true),
}),
}; };
Assert.Equal(volumes[0].Number, volumes.GetCoverImage(MangaFormat.Archive).Number); Assert.Equal(volumes[0].Number, volumes.GetCoverImage(MangaFormat.Archive).Number);
@ -36,16 +35,14 @@ public class VolumeListExtensionsTests
{ {
var volumes = new List<Volume>() var volumes = new List<Volume>()
{ {
EntityFactory.CreateVolume("1", new List<Chapter>() new VolumeBuilder("1")
{ .WithChapter(new ChapterBuilder("3").Build())
EntityFactory.CreateChapter("3", false), .WithChapter(new ChapterBuilder("4").Build())
EntityFactory.CreateChapter("4", false), .Build(),
}), new VolumeBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
EntityFactory.CreateVolume("0", new List<Chapter>() .WithChapter(new ChapterBuilder("1").Build())
{ .WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter).WithIsSpecial(true).Build())
EntityFactory.CreateChapter("1", false), .Build(),
EntityFactory.CreateChapter("0", true),
}),
}; };
Assert.Equal(volumes[1].Name, volumes.GetCoverImage(MangaFormat.Epub).Name); Assert.Equal(volumes[1].Name, volumes.GetCoverImage(MangaFormat.Epub).Name);
@ -56,16 +53,14 @@ public class VolumeListExtensionsTests
{ {
var volumes = new List<Volume>() var volumes = new List<Volume>()
{ {
EntityFactory.CreateVolume("1", new List<Chapter>() new VolumeBuilder("1")
{ .WithChapter(new ChapterBuilder("3").Build())
EntityFactory.CreateChapter("3", false), .WithChapter(new ChapterBuilder("4").Build())
EntityFactory.CreateChapter("4", false), .Build(),
}), new VolumeBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
EntityFactory.CreateVolume("0", new List<Chapter>() .WithChapter(new ChapterBuilder("1").Build())
{ .WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter).WithIsSpecial(true).Build())
EntityFactory.CreateChapter("1", false), .Build(),
EntityFactory.CreateChapter("0", true),
}),
}; };
Assert.Equal(volumes[1].Name, volumes.GetCoverImage(MangaFormat.Pdf).Name); Assert.Equal(volumes[1].Name, volumes.GetCoverImage(MangaFormat.Pdf).Name);
@ -76,16 +71,14 @@ public class VolumeListExtensionsTests
{ {
var volumes = new List<Volume>() var volumes = new List<Volume>()
{ {
EntityFactory.CreateVolume("1", new List<Chapter>() new VolumeBuilder("1")
{ .WithChapter(new ChapterBuilder("3").Build())
EntityFactory.CreateChapter("3", false), .WithChapter(new ChapterBuilder("4").Build())
EntityFactory.CreateChapter("4", false), .Build(),
}), new VolumeBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultVolume)
EntityFactory.CreateVolume("0", new List<Chapter>() .WithChapter(new ChapterBuilder("1").Build())
{ .WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter).WithIsSpecial(true).Build())
EntityFactory.CreateChapter("1", false), .Build(),
EntityFactory.CreateChapter("0", true),
}),
}; };
Assert.Equal(volumes[0].Name, volumes.GetCoverImage(MangaFormat.Image).Name); Assert.Equal(volumes[0].Name, volumes.GetCoverImage(MangaFormat.Image).Name);
@ -96,16 +89,14 @@ public class VolumeListExtensionsTests
{ {
var volumes = new List<Volume>() var volumes = new List<Volume>()
{ {
EntityFactory.CreateVolume("2", new List<Chapter>() new VolumeBuilder("2")
{ .WithChapter(new ChapterBuilder("3").Build())
EntityFactory.CreateChapter("3", false), .WithChapter(new ChapterBuilder("4").Build())
EntityFactory.CreateChapter("4", false), .Build(),
}), new VolumeBuilder("1")
EntityFactory.CreateVolume("1", new List<Chapter>() .WithChapter(new ChapterBuilder("1").Build())
{ .WithChapter(new ChapterBuilder(API.Services.Tasks.Scanner.Parser.Parser.DefaultChapter).Build())
EntityFactory.CreateChapter("1", false), .Build(),
EntityFactory.CreateChapter("0", true),
}),
}; };
Assert.Equal(volumes[1].Name, volumes.GetCoverImage(MangaFormat.Image).Name); Assert.Equal(volumes[1].Name, volumes.GetCoverImage(MangaFormat.Image).Name);

View File

@ -3,7 +3,9 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Abstractions.TestingHelpers; using System.IO.Abstractions.TestingHelpers;
using API.Entities; using API.Entities;
using API.Entities.Enums;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using API.Services; using API.Services;
using Xunit; using Xunit;
@ -51,11 +53,10 @@ public class CacheHelperTests
[Fact] [Fact]
public void ShouldUpdateCoverImage_OnFirstRun() public void ShouldUpdateCoverImage_OnFirstRun()
{ {
var file = new MangaFile()
{ var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
FilePath = TestCoverArchive, .WithLastModified(DateTime.Now)
LastModified = DateTime.Now .Build();
};
Assert.True(_cacheHelper.ShouldUpdateCoverImage(null, file, DateTime.Now.Subtract(TimeSpan.FromMinutes(1)), Assert.True(_cacheHelper.ShouldUpdateCoverImage(null, file, DateTime.Now.Subtract(TimeSpan.FromMinutes(1)),
false, false)); false, false));
} }
@ -64,11 +65,9 @@ public class CacheHelperTests
public void ShouldUpdateCoverImage_ShouldNotUpdateOnSecondRunWithCoverImageSetNotLocked() public void ShouldUpdateCoverImage_ShouldNotUpdateOnSecondRunWithCoverImageSetNotLocked()
{ {
// Represents first run // Represents first run
var file = new MangaFile() var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
{ .WithLastModified(DateTime.Now)
FilePath = TestCoverArchive, .Build();
LastModified = DateTime.Now
};
Assert.False(_cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, DateTime.Now.Subtract(TimeSpan.FromMinutes(1)), Assert.False(_cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, DateTime.Now.Subtract(TimeSpan.FromMinutes(1)),
false, false)); false, false));
} }
@ -77,11 +76,9 @@ public class CacheHelperTests
public void ShouldUpdateCoverImage_ShouldNotUpdateOnSecondRunWithCoverImageSetNotLocked_2() public void ShouldUpdateCoverImage_ShouldNotUpdateOnSecondRunWithCoverImageSetNotLocked_2()
{ {
// Represents first run // Represents first run
var file = new MangaFile() var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
{ .WithLastModified(DateTime.Now)
FilePath = TestCoverArchive, .Build();
LastModified = DateTime.Now
};
Assert.False(_cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, DateTime.Now, Assert.False(_cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, DateTime.Now,
false, false)); false, false));
} }
@ -90,11 +87,9 @@ public class CacheHelperTests
public void ShouldUpdateCoverImage_ShouldNotUpdateOnSecondRunWithCoverImageSetLocked() public void ShouldUpdateCoverImage_ShouldNotUpdateOnSecondRunWithCoverImageSetLocked()
{ {
// Represents first run // Represents first run
var file = new MangaFile() var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
{ .WithLastModified(DateTime.Now)
FilePath = TestCoverArchive, .Build();
LastModified = DateTime.Now
};
Assert.False(_cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, DateTime.Now.Subtract(TimeSpan.FromMinutes(1)), Assert.False(_cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, DateTime.Now.Subtract(TimeSpan.FromMinutes(1)),
false, true)); false, true));
} }
@ -103,11 +98,9 @@ public class CacheHelperTests
public void ShouldUpdateCoverImage_ShouldNotUpdateOnSecondRunWithCoverImageSetLocked_Modified() public void ShouldUpdateCoverImage_ShouldNotUpdateOnSecondRunWithCoverImageSetLocked_Modified()
{ {
// Represents first run // Represents first run
var file = new MangaFile() var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
{ .WithLastModified(DateTime.Now)
FilePath = TestCoverArchive, .Build();
LastModified = DateTime.Now
};
Assert.False(_cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, DateTime.Now.Subtract(TimeSpan.FromMinutes(1)), Assert.False(_cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, DateTime.Now.Subtract(TimeSpan.FromMinutes(1)),
false, true)); false, true));
} }
@ -129,11 +122,10 @@ public class CacheHelperTests
var cacheHelper = new CacheHelper(fileService); var cacheHelper = new CacheHelper(fileService);
var created = DateTime.Now.Subtract(TimeSpan.FromHours(1)); var created = DateTime.Now.Subtract(TimeSpan.FromHours(1));
var file = new MangaFile() var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
{ .WithLastModified(DateTime.Now.Subtract(TimeSpan.FromMinutes(1)))
FilePath = TestCoverArchive, .Build();
LastModified = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))
};
Assert.True(cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, created, Assert.True(cacheHelper.ShouldUpdateCoverImage(_testCoverPath, file, created,
false, false)); false, false));
} }
@ -154,19 +146,14 @@ public class CacheHelperTests
var fileService = new FileService(fileSystem); var fileService = new FileService(fileSystem);
var cacheHelper = new CacheHelper(fileService); var cacheHelper = new CacheHelper(fileService);
var chapter = new Chapter() var chapter = new ChapterBuilder("1")
{ .WithLastModified(filesystemFile.LastWriteTime.DateTime)
Number = "1", .WithCreated(filesystemFile.LastWriteTime.DateTime)
Range = "1", .Build();
Created = filesystemFile.LastWriteTime.DateTime,
LastModified = filesystemFile.LastWriteTime.DateTime
};
var file = new MangaFile() var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
{ .WithLastModified(filesystemFile.LastWriteTime.DateTime)
FilePath = TestCoverArchive, .Build();
LastModified = filesystemFile.LastWriteTime.DateTime
};
Assert.True(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, file)); Assert.True(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, file));
} }
@ -186,19 +173,15 @@ public class CacheHelperTests
var fileService = new FileService(fileSystem); var fileService = new FileService(fileSystem);
var cacheHelper = new CacheHelper(fileService); var cacheHelper = new CacheHelper(fileService);
var chapter = new Chapter() var chapter = new ChapterBuilder("1")
{ .WithLastModified(filesystemFile.LastWriteTime.DateTime)
Number = "1", .WithCreated(filesystemFile.LastWriteTime.DateTime)
Range = "1", .Build();
Created = filesystemFile.LastWriteTime.DateTime,
LastModified = filesystemFile.LastWriteTime.DateTime var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
}; .WithLastModified(filesystemFile.LastWriteTime.DateTime)
.Build();
var file = new MangaFile()
{
FilePath = TestCoverArchive,
LastModified = filesystemFile.LastWriteTime.DateTime
};
Assert.True(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, file)); Assert.True(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, file));
} }
@ -218,19 +201,14 @@ public class CacheHelperTests
var fileService = new FileService(fileSystem); var fileService = new FileService(fileSystem);
var cacheHelper = new CacheHelper(fileService); var cacheHelper = new CacheHelper(fileService);
var chapter = new Chapter() var chapter = new ChapterBuilder("1")
{ .WithLastModified(filesystemFile.LastWriteTime.DateTime)
Number = "1", .WithCreated(filesystemFile.LastWriteTime.DateTime)
Range = "1", .Build();
Created = filesystemFile.LastWriteTime.DateTime,
LastModified = filesystemFile.LastWriteTime.DateTime
};
var file = new MangaFile() var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
{ .WithLastModified(filesystemFile.LastWriteTime.DateTime)
FilePath = TestCoverArchive, .Build();
LastModified = filesystemFile.LastWriteTime.DateTime
};
Assert.False(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, true, file)); Assert.False(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, true, file));
} }
@ -251,19 +229,14 @@ public class CacheHelperTests
var fileService = new FileService(fileSystem); var fileService = new FileService(fileSystem);
var cacheHelper = new CacheHelper(fileService); var cacheHelper = new CacheHelper(fileService);
var chapter = new Chapter() var chapter = new ChapterBuilder("1")
{ .WithLastModified(DateTime.Now.Subtract(TimeSpan.FromMinutes(10)))
Number = "1", .WithCreated(DateTime.Now.Subtract(TimeSpan.FromMinutes(10)))
Range = "1", .Build();
Created = DateTime.Now.Subtract(TimeSpan.FromMinutes(10)),
LastModified = DateTime.Now.Subtract(TimeSpan.FromMinutes(10))
};
var file = new MangaFile() var file = new MangaFileBuilder(TestCoverArchive, MangaFormat.Archive)
{ .WithLastModified(filesystemFile.LastWriteTime.DateTime)
FilePath = Path.Join(TestCoverImageDirectory, TestCoverArchive), .Build();
LastModified = filesystemFile.LastWriteTime.DateTime
};
Assert.False(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, file)); Assert.False(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, file));
} }
@ -283,19 +256,15 @@ public class CacheHelperTests
var fileService = new FileService(fileSystem); var fileService = new FileService(fileSystem);
var cacheHelper = new CacheHelper(fileService); var cacheHelper = new CacheHelper(fileService);
var chapter = new Chapter() var chapter = new ChapterBuilder("1")
{ .WithLastModified(DateTime.Now)
Number = "1", .WithCreated(DateTime.Now.Subtract(TimeSpan.FromMinutes(10)))
Range = "1", .Build();
Created = DateTime.Now.Subtract(TimeSpan.FromMinutes(10)),
LastModified = DateTime.Now var file = new MangaFileBuilder(Path.Join(TestCoverImageDirectory, TestCoverArchive), MangaFormat.Archive)
}; .WithLastModified(filesystemFile.LastWriteTime.DateTime)
.Build();
var file = new MangaFile()
{
FilePath = Path.Join(TestCoverImageDirectory, TestCoverArchive),
LastModified = filesystemFile.LastWriteTime.DateTime
};
Assert.False(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, file)); Assert.False(cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, file));
} }

View File

@ -1,74 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using API.Data;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
namespace API.Tests.Helpers;
/// <summary>
/// Used to help quickly create DB entities for Unit Testing
/// </summary>
public static class EntityFactory
{
public static Series CreateSeries(string name)
{
return new Series()
{
Name = name,
SortName = name,
LocalizedName = name,
NormalizedName = name.ToNormalized(),
OriginalName = name,
NormalizedLocalizedName = name.ToNormalized(),
Volumes = new List<Volume>(),
Metadata = new SeriesMetadata()
};
}
public static Volume CreateVolume(string volumeNumber, List<Chapter> chapters = null)
{
var chaps = chapters ?? new List<Chapter>();
var pages = chaps.Count > 0 ? chaps.Max(c => c.Pages) : 0;
return new Volume()
{
Name = volumeNumber,
Number = (int) API.Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(volumeNumber),
Pages = pages,
Chapters = chaps
};
}
public static Chapter CreateChapter(string range, bool isSpecial, List<MangaFile> files = null, int pageCount = 0, string title = null)
{
return new Chapter()
{
IsSpecial = isSpecial,
Range = range,
Number = API.Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(range) + string.Empty,
Files = files ?? new List<MangaFile>(),
Pages = pageCount,
Title = title ?? range
};
}
public static MangaFile CreateMangaFile(string filename, MangaFormat format, int pages)
{
return new MangaFile()
{
FilePath = filename,
Format = format,
Pages = pages
};
}
public static CollectionTag CreateCollectionTag(int id, string title, string summary, bool promoted)
{
return DbFactory.CollectionTag(id, title, summary, promoted);
}
}

View File

@ -2,6 +2,7 @@
using API.Data; using API.Data;
using API.Entities; using API.Entities;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using Xunit; using Xunit;
namespace API.Tests.Helpers; namespace API.Tests.Helpers;
@ -13,9 +14,9 @@ public class GenreHelperTests
{ {
var allGenres = new List<Genre> var allGenres = new List<Genre>
{ {
DbFactory.Genre("Action"), new GenreBuilder("Action").Build(),
DbFactory.Genre("action"), new GenreBuilder("action").Build(),
DbFactory.Genre("Sci-fi"), new GenreBuilder("Sci-fi").Build(),
}; };
var genreAdded = new List<Genre>(); var genreAdded = new List<Genre>();
@ -33,9 +34,9 @@ public class GenreHelperTests
{ {
var allGenres = new List<Genre> var allGenres = new List<Genre>
{ {
DbFactory.Genre("Action"), new GenreBuilder("Action").Build(),
DbFactory.Genre("action"), new GenreBuilder("action").Build(),
DbFactory.Genre("Sci-fi"), new GenreBuilder("Sci-fi").Build(),
}; };
var genreAdded = new List<Genre>(); var genreAdded = new List<Genre>();
@ -54,19 +55,19 @@ public class GenreHelperTests
{ {
var existingGenres = new List<Genre> var existingGenres = new List<Genre>
{ {
DbFactory.Genre("Action"), new GenreBuilder("Action").Build(),
DbFactory.Genre("action"), new GenreBuilder("action").Build(),
DbFactory.Genre("Sci-fi"), new GenreBuilder("Sci-fi").Build(),
}; };
GenreHelper.AddGenreIfNotExists(existingGenres, DbFactory.Genre("Action")); GenreHelper.AddGenreIfNotExists(existingGenres, new GenreBuilder("Action").Build());
Assert.Equal(3, existingGenres.Count); Assert.Equal(3, existingGenres.Count);
GenreHelper.AddGenreIfNotExists(existingGenres, DbFactory.Genre("action")); GenreHelper.AddGenreIfNotExists(existingGenres, new GenreBuilder("action").Build());
Assert.Equal(3, existingGenres.Count); Assert.Equal(3, existingGenres.Count);
GenreHelper.AddGenreIfNotExists(existingGenres, DbFactory.Genre("Shonen")); GenreHelper.AddGenreIfNotExists(existingGenres, new GenreBuilder("Shonen").Build());
Assert.Equal(4, existingGenres.Count); Assert.Equal(4, existingGenres.Count);
} }
@ -75,13 +76,13 @@ public class GenreHelperTests
{ {
var existingGenres = new List<Genre> var existingGenres = new List<Genre>
{ {
DbFactory.Genre("Action"), new GenreBuilder("Action").Build(),
DbFactory.Genre("Sci-fi"), new GenreBuilder("Sci-fi").Build(),
}; };
var peopleFromChapters = new List<Genre> var peopleFromChapters = new List<Genre>
{ {
DbFactory.Genre("Action"), new GenreBuilder("Action").Build(),
}; };
var genreRemoved = new List<Genre>(); var genreRemoved = new List<Genre>();
@ -99,8 +100,8 @@ public class GenreHelperTests
{ {
var existingGenres = new List<Genre> var existingGenres = new List<Genre>
{ {
DbFactory.Genre("Action"), new GenreBuilder("Action").Build(),
DbFactory.Genre("Sci-fi"), new GenreBuilder("Sci-fi").Build(),
}; };
var peopleFromChapters = new List<Genre>(); var peopleFromChapters = new List<Genre>();

View File

@ -4,8 +4,8 @@ using System.IO;
using System.Linq; using System.Linq;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Parser;
using API.Services.Tasks.Scanner; using API.Services.Tasks.Scanner;
using API.Services.Tasks.Scanner.Parser;
namespace API.Tests.Helpers; namespace API.Tests.Helpers;

View File

@ -5,8 +5,8 @@ using API.Entities.Metadata;
using API.Extensions; using API.Extensions;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders; using API.Helpers.Builders;
using API.Parser;
using API.Services.Tasks.Scanner; using API.Services.Tasks.Scanner;
using API.Services.Tasks.Scanner.Parser;
using Xunit; using Xunit;
namespace API.Tests.Helpers; namespace API.Tests.Helpers;
@ -25,7 +25,6 @@ public class ParserInfoHelperTests
var series = new SeriesBuilder("Darker Than Black") var series = new SeriesBuilder("Darker Than Black")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithName("1") .WithName("1")
.Build()) .Build())
@ -46,7 +45,6 @@ public class ParserInfoHelperTests
var series = new SeriesBuilder("Darker Than Black") var series = new SeriesBuilder("Darker Than Black")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithName("1") .WithName("1")
.Build()) .Build())

View File

@ -1,8 +1,12 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq;
using API.Data; using API.Data;
using API.DTOs;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using Xunit; using Xunit;
namespace API.Tests.Helpers; namespace API.Tests.Helpers;
@ -15,8 +19,8 @@ public class PersonHelperTests
{ {
var allPeople = new List<Person> var allPeople = new List<Person>
{ {
DbFactory.Person("Joe Shmo", PersonRole.CoverArtist), new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build(),
DbFactory.Person("Joe Shmo", PersonRole.Writer) new PersonBuilder("Joe Shmo", PersonRole.Writer).Build(),
}; };
var peopleAdded = new List<Person>(); var peopleAdded = new List<Person>();
@ -34,9 +38,9 @@ public class PersonHelperTests
{ {
var allPeople = new List<Person> var allPeople = new List<Person>
{ {
DbFactory.Person("Joe Shmo", PersonRole.CoverArtist), new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build(),
DbFactory.Person("Joe Shmo", PersonRole.Writer), new PersonBuilder("Joe Shmo", PersonRole.Writer).Build(),
DbFactory.Person("Sally Ann", PersonRole.CoverArtist), new PersonBuilder("Sally Ann", PersonRole.CoverArtist).Build(),
}; };
var peopleAdded = new List<Person>(); var peopleAdded = new List<Person>();
@ -52,6 +56,150 @@ public class PersonHelperTests
#region UpdatePeopleList #region UpdatePeopleList
[Fact]
public void UpdatePeopleList_NullTags_NoChanges()
{
// Arrange
ICollection<PersonDto> tags = null;
var series = new SeriesBuilder("Test Series").Build();
var allTags = new List<Person>();
var handleAddCalled = false;
var onModifiedCalled = false;
// Act
PersonHelper.UpdatePeopleList(PersonRole.Writer, tags, series, allTags, p => handleAddCalled = true, () => onModifiedCalled = true);
// Assert
Assert.False(handleAddCalled);
Assert.False(onModifiedCalled);
}
[Fact]
public void UpdatePeopleList_AddNewTag_TagAddedAndOnModifiedCalled()
{
// Arrange
const PersonRole role = PersonRole.Writer;
var tags = new List<PersonDto>
{
new PersonDto { Id = 1, Name = "John Doe", Role = role }
};
var series = new SeriesBuilder("Test Series").Build();
var allTags = new List<Person>();
var handleAddCalled = false;
var onModifiedCalled = false;
// Act
PersonHelper.UpdatePeopleList(role, tags, series, allTags, p =>
{
handleAddCalled = true;
series.Metadata.People.Add(p);
}, () => onModifiedCalled = true);
// Assert
Assert.True(handleAddCalled);
Assert.True(onModifiedCalled);
Assert.Single(series.Metadata.People);
Assert.Equal("John Doe", series.Metadata.People.First().Name);
}
[Fact]
public void UpdatePeopleList_RemoveExistingTag_TagRemovedAndOnModifiedCalled()
{
// Arrange
const PersonRole role = PersonRole.Writer;
var tags = new List<PersonDto>();
var series = new SeriesBuilder("Test Series").Build();
var person = new PersonBuilder("John Doe", role).Build();
person.Id = 1;
series.Metadata.People.Add(person);
var allTags = new List<Person>
{
person
};
var handleAddCalled = false;
var onModifiedCalled = false;
// Act
PersonHelper.UpdatePeopleList(role, tags, series, allTags, p =>
{
handleAddCalled = true;
series.Metadata.People.Add(p);
}, () => onModifiedCalled = true);
// Assert
Assert.False(handleAddCalled);
Assert.True(onModifiedCalled);
Assert.Empty(series.Metadata.People);
}
[Fact]
public void UpdatePeopleList_UpdateExistingTag_OnModifiedCalled()
{
// Arrange
const PersonRole role = PersonRole.Writer;
var tags = new List<PersonDto>
{
new PersonDto { Id = 1, Name = "John Doe", Role = role }
};
var series = new SeriesBuilder("Test Series").Build();
var person = new PersonBuilder("John Doe", role).Build();
person.Id = 1;
series.Metadata.People.Add(person);
var allTags = new List<Person>
{
person
};
var handleAddCalled = false;
var onModifiedCalled = false;
// Act
PersonHelper.UpdatePeopleList(role, tags, series, allTags, p =>
{
handleAddCalled = true;
series.Metadata.People.Add(p);
}, () => onModifiedCalled = true);
// Assert
Assert.False(handleAddCalled);
Assert.False(onModifiedCalled);
Assert.Single(series.Metadata.People);
Assert.Equal("John Doe", series.Metadata.People.First().Name);
}
[Fact]
public void UpdatePeopleList_NoChanges_HandleAddAndOnModifiedNotCalled()
{
// Arrange
const PersonRole role = PersonRole.Writer;
var tags = new List<PersonDto>
{
new PersonDto { Id = 1, Name = "John Doe", Role = role }
};
var series = new SeriesBuilder("Test Series").Build();
var person = new PersonBuilder("John Doe", role).Build();
person.Id = 1;
series.Metadata.People.Add(person);
var allTags = new List<Person>
{
new PersonBuilder("John Doe", role).Build()
};
var handleAddCalled = false;
var onModifiedCalled = false;
// Act
PersonHelper.UpdatePeopleList(role, tags, series, allTags, p =>
{
handleAddCalled = true;
series.Metadata.People.Add(p);
}, () => onModifiedCalled = true);
// Assert
Assert.False(handleAddCalled);
Assert.False(onModifiedCalled);
Assert.Single(series.Metadata.People);
Assert.Equal("John Doe", series.Metadata.People.First().Name);
}
#endregion #endregion
@ -62,8 +210,8 @@ public class PersonHelperTests
{ {
var existingPeople = new List<Person> var existingPeople = new List<Person>
{ {
DbFactory.Person("Joe Shmo", PersonRole.CoverArtist), new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build(),
DbFactory.Person("Joe Shmo", PersonRole.Writer) new PersonBuilder("Joe Shmo", PersonRole.Writer).Build(),
}; };
var peopleRemoved = new List<Person>(); var peopleRemoved = new List<Person>();
PersonHelper.RemovePeople(existingPeople, new[] {"Joe Shmo", "Sally Ann"}, PersonRole.Writer, person => PersonHelper.RemovePeople(existingPeople, new[] {"Joe Shmo", "Sally Ann"}, PersonRole.Writer, person =>
@ -80,8 +228,8 @@ public class PersonHelperTests
{ {
var existingPeople = new List<Person> var existingPeople = new List<Person>
{ {
DbFactory.Person("Joe Shmo", PersonRole.CoverArtist), new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build(),
DbFactory.Person("Joe Shmo", PersonRole.Writer) new PersonBuilder("Joe Shmo", PersonRole.Writer).Build(),
}; };
var peopleRemoved = new List<Person>(); var peopleRemoved = new List<Person>();
PersonHelper.RemovePeople(existingPeople, new[] {"Joe Shmo", "Sally Ann"}, PersonRole.Writer, person => PersonHelper.RemovePeople(existingPeople, new[] {"Joe Shmo", "Sally Ann"}, PersonRole.Writer, person =>
@ -106,9 +254,9 @@ public class PersonHelperTests
{ {
var existingPeople = new List<Person> var existingPeople = new List<Person>
{ {
DbFactory.Person("Joe Shmo", PersonRole.Writer), new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build(),
DbFactory.Person("Joe Shmo", PersonRole.Writer), new PersonBuilder("Joe Shmo", PersonRole.Writer).Build(),
DbFactory.Person("Joe Shmo", PersonRole.CoverArtist) new PersonBuilder("Joe Shmo", PersonRole.Writer).Build(),
}; };
var peopleRemoved = new List<Person>(); var peopleRemoved = new List<Person>();
PersonHelper.RemovePeople(existingPeople, new List<string>(), PersonRole.Writer, person => PersonHelper.RemovePeople(existingPeople, new List<string>(), PersonRole.Writer, person =>
@ -129,14 +277,14 @@ public class PersonHelperTests
{ {
var existingPeople = new List<Person> var existingPeople = new List<Person>
{ {
DbFactory.Person("Joe Shmo", PersonRole.CoverArtist), new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build(),
DbFactory.Person("Joe Shmo", PersonRole.Writer), new PersonBuilder("Joe Shmo", PersonRole.Writer).Build(),
DbFactory.Person("Sally", PersonRole.Writer), new PersonBuilder("Sally", PersonRole.Writer).Build(),
}; };
var peopleFromChapters = new List<Person> var peopleFromChapters = new List<Person>
{ {
DbFactory.Person("Joe Shmo", PersonRole.CoverArtist), new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build(),
}; };
var peopleRemoved = new List<Person>(); var peopleRemoved = new List<Person>();
@ -152,24 +300,113 @@ public class PersonHelperTests
#region AddPeople #region AddPeople
[Fact]
public void AddPersonIfNotExists_ShouldAddPerson_WhenPersonDoesNotExist()
{
// Arrange
var metadataPeople = new List<Person>();
var person = new PersonBuilder("John Smith", PersonRole.Character).Build();
// Act
PersonHelper.AddPersonIfNotExists(metadataPeople, person);
// Assert
Assert.Single(metadataPeople);
Assert.Contains(person, metadataPeople);
}
[Fact]
public void AddPersonIfNotExists_ShouldNotAddPerson_WhenPersonAlreadyExists()
{
// Arrange
var metadataPeople = new List<Person>
{
new PersonBuilder("John Smith", PersonRole.Character)
.WithId(1)
.Build()
};
var person = new PersonBuilder("John Smith", PersonRole.Character).Build();
// Act
PersonHelper.AddPersonIfNotExists(metadataPeople, person);
// Assert
Assert.Single(metadataPeople);
Assert.NotNull(metadataPeople.SingleOrDefault(p =>
p.Name.Equals(person.Name) && p.Role == person.Role && p.NormalizedName == person.NormalizedName));
Assert.Equal(1, metadataPeople.First().Id);
}
[Fact]
public void AddPersonIfNotExists_ShouldNotAddPerson_WhenPersonNameIsNullOrEmpty()
{
// Arrange
var metadataPeople = new List<Person>();
var person2 = new PersonBuilder(string.Empty, PersonRole.Character).Build();
// Act
PersonHelper.AddPersonIfNotExists(metadataPeople, person2);
// Assert
Assert.Empty(metadataPeople);
}
[Fact]
public void AddPersonIfNotExists_ShouldAddPerson_WhenPersonNameIsDifferentButRoleIsSame()
{
// Arrange
var metadataPeople = new List<Person>
{
new PersonBuilder("John Smith", PersonRole.Character).Build()
};
var person = new PersonBuilder("John Doe", PersonRole.Character).Build();
// Act
PersonHelper.AddPersonIfNotExists(metadataPeople, person);
// Assert
Assert.Equal(2, metadataPeople.Count);
Assert.Contains(person, metadataPeople);
}
[Fact]
public void AddPersonIfNotExists_ShouldAddPerson_WhenPersonNameIsSameButRoleIsDifferent()
{
// Arrange
var metadataPeople = new List<Person>
{
new PersonBuilder("John Doe", PersonRole.Writer).Build()
};
var person = new PersonBuilder("John Smith", PersonRole.Character).Build();
// Act
PersonHelper.AddPersonIfNotExists(metadataPeople, person);
// Assert
Assert.Equal(2, metadataPeople.Count);
Assert.Contains(person, metadataPeople);
}
[Fact] [Fact]
public void AddPeople_ShouldAddOnlyNonExistingPeople() public void AddPeople_ShouldAddOnlyNonExistingPeople()
{ {
var existingPeople = new List<Person> var existingPeople = new List<Person>
{ {
DbFactory.Person("Joe Shmo", PersonRole.CoverArtist), new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build(),
DbFactory.Person("Joe Shmo", PersonRole.Writer), new PersonBuilder("Joe Shmo", PersonRole.Writer).Build(),
DbFactory.Person("Sally", PersonRole.Writer), new PersonBuilder("Sally", PersonRole.Writer).Build(),
}; };
PersonHelper.AddPersonIfNotExists(existingPeople, DbFactory.Person("Joe Shmo", PersonRole.CoverArtist)); PersonHelper.AddPersonIfNotExists(existingPeople, new PersonBuilder("Joe Shmo", PersonRole.CoverArtist).Build());
Assert.Equal(3, existingPeople.Count); Assert.Equal(3, existingPeople.Count);
PersonHelper.AddPersonIfNotExists(existingPeople, DbFactory.Person("Joe Shmo", PersonRole.Writer)); PersonHelper.AddPersonIfNotExists(existingPeople, new PersonBuilder("Joe Shmo", PersonRole.Writer).Build());
Assert.Equal(3, existingPeople.Count); Assert.Equal(3, existingPeople.Count);
PersonHelper.AddPersonIfNotExists(existingPeople, DbFactory.Person("Joe Shmo Two", PersonRole.CoverArtist)); PersonHelper.AddPersonIfNotExists(existingPeople, new PersonBuilder("Joe Shmo Two", PersonRole.CoverArtist).Build());
Assert.Equal(4, existingPeople.Count); Assert.Equal(4, existingPeople.Count);
} }

View File

@ -5,6 +5,7 @@ using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using API.Services.Tasks.Scanner; using API.Services.Tasks.Scanner;
using Xunit; using Xunit;
@ -16,7 +17,7 @@ public class SeriesHelperTests
[Fact] [Fact]
public void FindSeries_ShouldFind_SameFormat() public void FindSeries_ShouldFind_SameFormat()
{ {
var series = DbFactory.Series("Darker than Black"); var series = new SeriesBuilder("Darker than Black").Build();
series.OriginalName = "Something Random"; series.OriginalName = "Something Random";
series.Format = MangaFormat.Archive; series.Format = MangaFormat.Archive;
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries() Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
@ -44,7 +45,7 @@ public class SeriesHelperTests
[Fact] [Fact]
public void FindSeries_ShouldFind_NullName() public void FindSeries_ShouldFind_NullName()
{ {
var series = DbFactory.Series("Darker than Black"); var series = new SeriesBuilder("Darker than Black").Build();
series.OriginalName = null; series.OriginalName = null;
series.Format = MangaFormat.Archive; series.Format = MangaFormat.Archive;
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries() Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
@ -58,7 +59,7 @@ public class SeriesHelperTests
[Fact] [Fact]
public void FindSeries_ShouldNotFind_WrongFormat() public void FindSeries_ShouldNotFind_WrongFormat()
{ {
var series = DbFactory.Series("Darker than Black"); var series = new SeriesBuilder("Darker than Black").Build();
series.OriginalName = "Something Random"; series.OriginalName = "Something Random";
series.Format = MangaFormat.Archive; series.Format = MangaFormat.Archive;
Assert.False(SeriesHelper.FindSeries(series, new ParsedSeries() Assert.False(SeriesHelper.FindSeries(series, new ParsedSeries()
@ -86,7 +87,7 @@ public class SeriesHelperTests
[Fact] [Fact]
public void FindSeries_ShouldFind_UsingOriginalName() public void FindSeries_ShouldFind_UsingOriginalName()
{ {
var series = DbFactory.Series("Darker than Black"); var series = new SeriesBuilder("Darker than Black").Build();
series.OriginalName = "Something Random"; series.OriginalName = "Something Random";
series.Format = MangaFormat.Image; series.Format = MangaFormat.Image;
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries() Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
@ -121,7 +122,7 @@ public class SeriesHelperTests
[Fact] [Fact]
public void FindSeries_ShouldFind_UsingLocalizedName() public void FindSeries_ShouldFind_UsingLocalizedName()
{ {
var series = DbFactory.Series("Darker than Black"); var series = new SeriesBuilder("Darker than Black").Build();
series.LocalizedName = "Something Random"; series.LocalizedName = "Something Random";
series.Format = MangaFormat.Image; series.Format = MangaFormat.Image;
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries() Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
@ -156,7 +157,7 @@ public class SeriesHelperTests
[Fact] [Fact]
public void FindSeries_ShouldFind_UsingLocalizedName_2() public void FindSeries_ShouldFind_UsingLocalizedName_2()
{ {
var series = DbFactory.Series("My Dress-Up Darling"); var series = new SeriesBuilder("My Dress-Up Darling").Build();
series.LocalizedName = "Sono Bisque Doll wa Koi wo Suru"; series.LocalizedName = "Sono Bisque Doll wa Koi wo Suru";
series.Format = MangaFormat.Archive; series.Format = MangaFormat.Archive;
Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries() Assert.True(SeriesHelper.FindSeries(series, new ParsedSeries()
@ -180,13 +181,13 @@ public class SeriesHelperTests
{ {
var existingSeries = new List<Series>() var existingSeries = new List<Series>()
{ {
EntityFactory.CreateSeries("Darker than Black Vol 1"), new SeriesBuilder("Darker than Black Vol 1").Build(),
EntityFactory.CreateSeries("Darker than Black"), new SeriesBuilder("Darker than Black").Build(),
EntityFactory.CreateSeries("Beastars"), new SeriesBuilder("Beastars").Build(),
}; };
var missingSeries = new List<Series>() var missingSeries = new List<Series>()
{ {
EntityFactory.CreateSeries("Darker than Black Vol 1"), new SeriesBuilder("Darker than Black Vol 1").Build(),
}; };
existingSeries = SeriesHelper.RemoveMissingSeries(existingSeries, missingSeries, out var removeCount).ToList(); existingSeries = SeriesHelper.RemoveMissingSeries(existingSeries, missingSeries, out var removeCount).ToList();

View File

@ -2,6 +2,7 @@
using API.Data; using API.Data;
using API.Entities; using API.Entities;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using Xunit; using Xunit;
namespace API.Tests.Helpers; namespace API.Tests.Helpers;
@ -13,9 +14,9 @@ public class TagHelperTests
{ {
var allTags = new List<Tag> var allTags = new List<Tag>
{ {
DbFactory.Tag("Action"), new TagBuilder("Action").Build(),
DbFactory.Tag("action"), new TagBuilder("action").Build(),
DbFactory.Tag("Sci-fi"), new TagBuilder("Sci-fi").Build(),
}; };
var tagAdded = new List<Tag>(); var tagAdded = new List<Tag>();
@ -37,9 +38,9 @@ public class TagHelperTests
{ {
var allTags = new List<Tag> var allTags = new List<Tag>
{ {
DbFactory.Tag("Action"), new TagBuilder("Action").Build(),
DbFactory.Tag("action"), new TagBuilder("action").Build(),
DbFactory.Tag("Sci-fi"), new TagBuilder("Sci-fi").Build(),
}; };
var tagAdded = new List<Tag>(); var tagAdded = new List<Tag>();
@ -62,19 +63,19 @@ public class TagHelperTests
{ {
var existingTags = new List<Tag> var existingTags = new List<Tag>
{ {
DbFactory.Tag("Action"), new TagBuilder("Action").Build(),
DbFactory.Tag("action"), new TagBuilder("action").Build(),
DbFactory.Tag("Sci-fi"), new TagBuilder("Sci-fi").Build(),
}; };
TagHelper.AddTagIfNotExists(existingTags, DbFactory.Tag("Action")); TagHelper.AddTagIfNotExists(existingTags, new TagBuilder("Action").Build());
Assert.Equal(3, existingTags.Count); Assert.Equal(3, existingTags.Count);
TagHelper.AddTagIfNotExists(existingTags, DbFactory.Tag("action")); TagHelper.AddTagIfNotExists(existingTags, new TagBuilder("action").Build());
Assert.Equal(3, existingTags.Count); Assert.Equal(3, existingTags.Count);
TagHelper.AddTagIfNotExists(existingTags, DbFactory.Tag("Shonen")); TagHelper.AddTagIfNotExists(existingTags, new TagBuilder("Shonen").Build());
Assert.Equal(4, existingTags.Count); Assert.Equal(4, existingTags.Count);
} }
@ -83,13 +84,13 @@ public class TagHelperTests
{ {
var existingTags = new List<Tag> var existingTags = new List<Tag>
{ {
DbFactory.Tag("Action"), new TagBuilder("Action").Build(),
DbFactory.Tag("Sci-fi"), new TagBuilder("Sci-fi").Build(),
}; };
var peopleFromChapters = new List<Tag> var peopleFromChapters = new List<Tag>
{ {
DbFactory.Tag("Action"), new TagBuilder("Action").Build(),
}; };
var tagRemoved = new List<Tag>(); var tagRemoved = new List<Tag>();
@ -107,8 +108,8 @@ public class TagHelperTests
{ {
var existingTags = new List<Tag> var existingTags = new List<Tag>
{ {
DbFactory.Tag("Action"), new TagBuilder("Action").Build(),
DbFactory.Tag("Sci-fi"), new TagBuilder("Sci-fi").Build(),
}; };
var peopleFromChapters = new List<Tag>(); var peopleFromChapters = new List<Tag>();

View File

@ -1,7 +1,8 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.IO.Abstractions.TestingHelpers; using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using API.Entities.Enums; using API.Entities.Enums;
using API.Parser;
using API.Services; using API.Services;
using API.Services.Tasks.Scanner.Parser; using API.Services.Tasks.Scanner.Parser;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -100,6 +101,14 @@ public class DefaultParserTests
#region Parse #region Parse
[Fact]
public void Parse_MangaLibrary_JustCover_ShouldReturnNull()
{
const string rootPath = @"E:/Manga/";
var actual = _defaultParser.Parse(@"E:/Manga/Accel World/cover.png", rootPath);
Assert.Null(actual);
}
[Fact] [Fact]
public void Parse_ParseInfo_Manga() public void Parse_ParseInfo_Manga()
{ {

View File

@ -1,5 +1,5 @@
using API.Entities.Enums; using API.Entities.Enums;
using API.Parser; using API.Services.Tasks.Scanner.Parser;
using Xunit; using Xunit;
namespace API.Tests.Parser; namespace API.Tests.Parser;

View File

@ -7,6 +7,7 @@ using API.Data;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using API.Services; using API.Services;
using AutoMapper; using AutoMapper;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
@ -70,10 +71,10 @@ public class CollectionTagRepositoryTests
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
var lib = new Library()
{ var lib = new LibraryBuilder("Manga")
Name = "Manga", Folders = new List<FolderPath>() {new FolderPath() {Path = "C:/data/"}} .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
}; .Build();
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -118,13 +119,13 @@ public class CollectionTagRepositoryTests
[Fact] [Fact]
public async Task RemoveTagsWithoutSeries_ShouldRemoveTags() public async Task RemoveTagsWithoutSeries_ShouldRemoveTags()
{ {
var library = DbFactory.Library("Test", LibraryType.Manga); var library = new LibraryBuilder("Test", LibraryType.Manga).Build();
var series = DbFactory.Series("Test 1"); var series = new SeriesBuilder("Test 1").Build();
var commonTag = DbFactory.CollectionTag(0, "Tag 1"); var commonTag = new CollectionTagBuilder("Tag 1").Build();
series.Metadata.CollectionTags.Add(commonTag); series.Metadata.CollectionTags.Add(commonTag);
series.Metadata.CollectionTags.Add(DbFactory.CollectionTag(0, "Tag 2")); series.Metadata.CollectionTags.Add(new CollectionTagBuilder("Tag 2").Build());
var series2 = DbFactory.Series("Test 1"); var series2 = new SeriesBuilder("Test 1").Build();
series2.Metadata.CollectionTags.Add(commonTag); series2.Metadata.CollectionTags.Add(commonTag);
library.Series.Add(series); library.Series.Add(series);
library.Series.Add(series2); library.Series.Add(series2);
@ -151,13 +152,13 @@ public class CollectionTagRepositoryTests
[Fact] [Fact]
public async Task RemoveTagsWithoutSeries_ShouldNotRemoveTags() public async Task RemoveTagsWithoutSeries_ShouldNotRemoveTags()
{ {
var library = DbFactory.Library("Test", LibraryType.Manga); var library = new LibraryBuilder("Test", LibraryType.Manga).Build();
var series = DbFactory.Series("Test 1"); var series = new SeriesBuilder("Test 1").Build();
var commonTag = DbFactory.CollectionTag(0, "Tag 1"); var commonTag = new CollectionTagBuilder("Tag 1").Build();
series.Metadata.CollectionTags.Add(commonTag); series.Metadata.CollectionTags.Add(commonTag);
series.Metadata.CollectionTags.Add(DbFactory.CollectionTag(0, "Tag 2")); series.Metadata.CollectionTags.Add(new CollectionTagBuilder("Tag 2").Build());
var series2 = DbFactory.Series("Test 1"); var series2 = new SeriesBuilder("Test 1").Build();
series2.Metadata.CollectionTags.Add(commonTag); series2.Metadata.CollectionTags.Add(commonTag);
library.Series.Add(series); library.Series.Add(series);
library.Series.Add(series2); library.Series.Add(series2);

View File

@ -72,10 +72,9 @@ public class SeriesRepositoryTests
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
var lib = new Library() var lib = new LibraryBuilder("Manga")
{ .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
Name = "Manga", Folders = new List<FolderPath>() {new FolderPath() {Path = "C:/data/"}} .Build();
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -117,23 +116,13 @@ public class SeriesRepositoryTests
private async Task SetupSeriesData() private async Task SetupSeriesData()
{ {
var library = new Library() var library = new LibraryBuilder("GetFullSeriesByAnyName Manga", LibraryType.Manga)
{ .WithFolderPath(new FolderPathBuilder("C:/data/manga/").Build())
Name = "GetFullSeriesByAnyName Manga", .WithSeries(new SeriesBuilder("The Idaten Deities Know Only Peace")
Type = LibraryType.Manga,
Folders = new List<FolderPath>()
{
new FolderPath() {Path = "C:/data/manga/"}
},
Series = new List<Series>()
{
new SeriesBuilder("The Idaten Deities Know Only Peace")
.WithLocalizedName("Heion Sedai no Idaten-tachi") .WithLocalizedName("Heion Sedai no Idaten-tachi")
.WithFormat(MangaFormat.Archive) .WithFormat(MangaFormat.Archive)
.Build() .Build())
} .Build();
};
_unitOfWork.LibraryRepository.Add(library); _unitOfWork.LibraryRepository.Add(library);
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using API.Data; using API.Data;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Helpers.Builders;
using API.Services; using API.Services;
using API.Services.Tasks; using API.Services.Tasks;
using API.SignalR; using API.SignalR;
@ -80,18 +81,9 @@ public class BackupServiceTests
setting.Value = BackupDirectory; setting.Value = BackupDirectory;
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
_context.Library.Add(new LibraryBuilder("Manga")
_context.Library.Add(new Library() .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
{ .Build());
Name = "Manga",
Folders = new List<FolderPath>()
{
new FolderPath()
{
Path = "C:/data/"
}
}
});
return await _context.SaveChangesAsync() > 0; return await _context.SaveChangesAsync() > 0;
} }

View File

@ -87,17 +87,9 @@ public class BookmarkServiceTests
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Manga")
{ .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
Name = "Manga", .Build());
Folders = new List<FolderPath>()
{
new FolderPath()
{
Path = "C:/data/"
}
}
});
return await _context.SaveChangesAsync() > 0; return await _context.SaveChangesAsync() > 0;
} }
@ -140,18 +132,12 @@ public class BookmarkServiceTests
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1") .WithChapter(new ChapterBuilder("1")
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -193,18 +179,13 @@ public class BookmarkServiceTests
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("0") .WithChapter(new ChapterBuilder("0")
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -264,18 +245,13 @@ public class BookmarkServiceTests
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1") .WithChapter(new ChapterBuilder("1")
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -345,18 +321,13 @@ public class BookmarkServiceTests
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1") .WithChapter(new ChapterBuilder("1")
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -403,18 +374,13 @@ public class BookmarkServiceTests
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1") .WithChapter(new ChapterBuilder("1")
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -461,18 +427,13 @@ public class BookmarkServiceTests
await ResetDB(); await ResetDB();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1") .WithChapter(new ChapterBuilder("1")
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);

View File

@ -8,8 +8,9 @@ using API.Data;
using API.Data.Metadata; using API.Data.Metadata;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Parser; using API.Helpers.Builders;
using API.Services; using API.Services;
using API.Services.Tasks.Scanner.Parser;
using API.SignalR; using API.SignalR;
using AutoMapper; using AutoMapper;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
@ -116,17 +117,9 @@ public class CacheServiceTests
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Manga")
{ .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
Name = "Manga", .Build());
Folders = new List<FolderPath>()
{
new FolderPath()
{
Path = "C:/data/"
}
}
});
return await _context.SaveChangesAsync() > 0; return await _context.SaveChangesAsync() > 0;
} }
@ -166,21 +159,11 @@ public class CacheServiceTests
Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds), Substitute.For<IBookmarkService>()); Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds), Substitute.For<IBookmarkService>());
await ResetDB(); await ResetDB();
var s = DbFactory.Series("Test"); var s = new SeriesBuilder("Test").Build();
var v = DbFactory.Volume("1"); var v = new VolumeBuilder("1").Build();
var c = new Chapter() var c = new ChapterBuilder("1")
{ .WithFile(new MangaFileBuilder($"{DataDirectory}Test v1.zip", MangaFormat.Archive).Build())
Number = "1", .Build();
Range = "1",
Files = new List<MangaFile>()
{
new MangaFile()
{
Format = MangaFormat.Archive,
FilePath = $"{DataDirectory}Test v1.zip",
}
}
};
v.Chapters.Add(c); v.Chapters.Add(c);
s.Volumes.Add(v); s.Volumes.Add(v);
s.LibraryId = 1; s.LibraryId = 1;
@ -207,8 +190,8 @@ public class CacheServiceTests
// new ReadingItemService(archiveService, Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds)); // new ReadingItemService(archiveService, Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds));
// //
// await ResetDB(); // await ResetDB();
// var s = DbFactory.Series("Test"); // var s = new SeriesBuilder("Test").Build();
// var v = DbFactory.Volume("1"); // var v = new VolumeBuilder("1").Build();
// var c = new Chapter() // var c = new Chapter()
// { // {
// Number = "1", // Number = "1",
@ -271,22 +254,10 @@ public class CacheServiceTests
new ReadingItemService(Substitute.For<IArchiveService>(), new ReadingItemService(Substitute.For<IArchiveService>(),
Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds), Substitute.For<IBookmarkService>()); Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds), Substitute.For<IBookmarkService>());
var c = new Chapter() var c = new ChapterBuilder("1")
{ .WithFile(new MangaFileBuilder($"{DataDirectory}1.epub", MangaFormat.Epub).Build())
Number = "1", .WithFile(new MangaFileBuilder($"{DataDirectory}2.epub", MangaFormat.Epub).Build())
Range = "1", .Build();
Files = new List<MangaFile>()
{
new MangaFile()
{
FilePath = $"{DataDirectory}1.epub"
},
new MangaFile()
{
FilePath = $"{DataDirectory}2.epub"
}
}
};
cs.GetCachedFile(c); cs.GetCachedFile(c);
Assert.Same($"{DataDirectory}1.epub", cs.GetCachedFile(c)); Assert.Same($"{DataDirectory}1.epub", cs.GetCachedFile(c));
} }
@ -303,13 +274,9 @@ public class CacheServiceTests
filesystem.AddFile($"{DataDirectory}1.zip", new MockFileData("")); filesystem.AddFile($"{DataDirectory}1.zip", new MockFileData(""));
filesystem.AddFile($"{DataDirectory}2.zip", new MockFileData("")); filesystem.AddFile($"{DataDirectory}2.zip", new MockFileData(""));
var c = new Chapter() var c = new ChapterBuilder("1")
{ .WithId(1)
Id = 1, .Build();
Number = "1",
Range = "1",
Files = new List<MangaFile>()
};
var fileIndex = 0; var fileIndex = 0;
foreach (var file in c.Files) foreach (var file in c.Files)
@ -342,28 +309,17 @@ public class CacheServiceTests
filesystem.AddFile($"{DataDirectory}1.zip", new MockFileData("")); filesystem.AddFile($"{DataDirectory}1.zip", new MockFileData(""));
filesystem.AddFile($"{DataDirectory}2.zip", new MockFileData("")); filesystem.AddFile($"{DataDirectory}2.zip", new MockFileData(""));
var c = new Chapter() var c = new ChapterBuilder("1")
{ .WithId(1)
Id = 1, .WithFile(new MangaFileBuilder($"{DataDirectory}1.zip", MangaFormat.Archive)
Number = "1", .WithPages(10)
Range = "1", .WithId(1)
Files = new List<MangaFile>() .Build())
{ .WithFile(new MangaFileBuilder($"{DataDirectory}2.zip", MangaFormat.Archive)
new MangaFile() .WithPages(5)
{ .WithId(2)
Id = 1, .Build())
FilePath = $"{DataDirectory}1.zip", .Build();
Pages = 10
},
new MangaFile()
{
Id = 2,
FilePath = $"{DataDirectory}2.zip",
Pages = 5
}
}
};
var fileIndex = 0; var fileIndex = 0;
foreach (var file in c.Files) foreach (var file in c.Files)
@ -396,22 +352,13 @@ public class CacheServiceTests
filesystem.AddDirectory($"{CacheDirectory}1/"); filesystem.AddDirectory($"{CacheDirectory}1/");
filesystem.AddFile($"{DataDirectory}1.zip", new MockFileData("")); filesystem.AddFile($"{DataDirectory}1.zip", new MockFileData(""));
var c = new Chapter() var c = new ChapterBuilder("1")
{ .WithId(1)
Id = 1, .WithFile(new MangaFileBuilder($"{DataDirectory}1.zip", MangaFormat.Archive)
Number = "1", .WithPages(10)
Range = "1", .WithId(1)
Files = new List<MangaFile>() .Build())
{ .Build();
new MangaFile()
{
Id = 1,
FilePath = $"{DataDirectory}1.zip",
Pages = 10
}
}
};
c.Pages = c.Files.Sum(f => f.Pages); c.Pages = c.Files.Sum(f => f.Pages);
var fileIndex = 0; var fileIndex = 0;
@ -446,28 +393,17 @@ public class CacheServiceTests
filesystem.AddFile($"{DataDirectory}1.zip", new MockFileData("")); filesystem.AddFile($"{DataDirectory}1.zip", new MockFileData(""));
filesystem.AddFile($"{DataDirectory}2.zip", new MockFileData("")); filesystem.AddFile($"{DataDirectory}2.zip", new MockFileData(""));
var c = new Chapter() var c = new ChapterBuilder("1")
{ .WithId(1)
Id = 1, .WithFile(new MangaFileBuilder($"{DataDirectory}1.zip", MangaFormat.Archive)
Number = "1", .WithPages(10)
Range = "1", .WithId(1)
Files = new List<MangaFile>() .Build())
{ .WithFile(new MangaFileBuilder($"{DataDirectory}2.zip", MangaFormat.Archive)
new MangaFile() .WithPages(5)
{ .WithId(2)
Id = 1, .Build())
FilePath = $"{DataDirectory}1.zip", .Build();
Pages = 10
},
new MangaFile()
{
Id = 2,
FilePath = $"{DataDirectory}2.zip",
Pages = 5
}
}
};
var fileIndex = 0; var fileIndex = 0;
foreach (var file in c.Files) foreach (var file in c.Files)

View File

@ -31,17 +31,9 @@ public class CleanupServiceTests : AbstractDbTest
public CleanupServiceTests() : base() public CleanupServiceTests() : base()
{ {
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Manga")
{ .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
Name = "Manga", .Build());
Folders = new List<FolderPath>()
{
new FolderPath()
{
Path = "C:/data/"
}
}
});
} }
#region Setup #region Setup
@ -71,15 +63,15 @@ public class CleanupServiceTests : AbstractDbTest
// Delete all Series to reset state // Delete all Series to reset state
await ResetDb(); await ResetDb();
var s = DbFactory.Series("Test 1"); var s = new SeriesBuilder("Test 1").Build();
s.CoverImage = $"{ImageService.GetSeriesFormat(1)}.jpg"; s.CoverImage = $"{ImageService.GetSeriesFormat(1)}.jpg";
s.LibraryId = 1; s.LibraryId = 1;
_context.Series.Add(s); _context.Series.Add(s);
s = DbFactory.Series("Test 2"); s = new SeriesBuilder("Test 2").Build();
s.CoverImage = $"{ImageService.GetSeriesFormat(3)}.jpg"; s.CoverImage = $"{ImageService.GetSeriesFormat(3)}.jpg";
s.LibraryId = 1; s.LibraryId = 1;
_context.Series.Add(s); _context.Series.Add(s);
s = DbFactory.Series("Test 3"); s = new SeriesBuilder("Test 3").Build();
s.CoverImage = $"{ImageService.GetSeriesFormat(1000)}.jpg"; s.CoverImage = $"{ImageService.GetSeriesFormat(1000)}.jpg";
s.LibraryId = 1; s.LibraryId = 1;
_context.Series.Add(s); _context.Series.Add(s);
@ -105,11 +97,11 @@ public class CleanupServiceTests : AbstractDbTest
await ResetDb(); await ResetDb();
// Add 2 series with cover images // Add 2 series with cover images
var s = DbFactory.Series("Test 1"); var s = new SeriesBuilder("Test 1").Build();
s.CoverImage = $"{ImageService.GetSeriesFormat(1)}.jpg"; s.CoverImage = $"{ImageService.GetSeriesFormat(1)}.jpg";
s.LibraryId = 1; s.LibraryId = 1;
_context.Series.Add(s); _context.Series.Add(s);
s = DbFactory.Series("Test 2"); s = new SeriesBuilder("Test 2").Build();
s.CoverImage = $"{ImageService.GetSeriesFormat(3)}.jpg"; s.CoverImage = $"{ImageService.GetSeriesFormat(3)}.jpg";
s.LibraryId = 1; s.LibraryId = 1;
_context.Series.Add(s); _context.Series.Add(s);
@ -139,33 +131,23 @@ public class CleanupServiceTests : AbstractDbTest
await ResetDb(); await ResetDb();
// Add 2 series with cover images // Add 2 series with cover images
var s = DbFactory.Series("Test 1"); _context.Series.Add(new SeriesBuilder("Test 1")
var v = DbFactory.Volume("1"); .WithVolume(new VolumeBuilder("1")
v.Chapters.Add(new Chapter() .WithChapter(new ChapterBuilder("0").WithCoverImage("v01_c01.jpg").Build())
{ .WithCoverImage("v01_c01.jpg")
Number = "0", .Build())
Range = "0", .WithCoverImage("series_01.jpg")
CoverImage = "v01_c01.jpg" .WithLibraryId(1)
}); .Build());
v.CoverImage = "v01_c01.jpg";
s.Volumes.Add(v);
s.CoverImage = "series_01.jpg";
s.LibraryId = 1;
_context.Series.Add(s);
s = DbFactory.Series("Test 2"); _context.Series.Add(new SeriesBuilder("Test 2")
v = DbFactory.Volume("1"); .WithVolume(new VolumeBuilder("1")
v.Chapters.Add(new Chapter() .WithChapter(new ChapterBuilder("0").WithCoverImage("v01_c03.jpg").Build())
{ .WithCoverImage("v01_c03.jpg")
Number = "0", .Build())
Range = "0", .WithCoverImage("series_03.jpg")
CoverImage = "v01_c03.jpg" .WithLibraryId(1)
}); .Build());
v.CoverImage = "v01_c03jpg";
s.Volumes.Add(v);
s.CoverImage = "series_03.jpg";
s.LibraryId = 1;
_context.Series.Add(s);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -193,29 +175,26 @@ public class CleanupServiceTests : AbstractDbTest
await ResetDb(); await ResetDb();
// Add 2 series with cover images // Add 2 series with cover images
var s = DbFactory.Series("Test 1");
s.Metadata.CollectionTags = new List<CollectionTag>();
s.Metadata.CollectionTags.Add(new CollectionTag()
{
Title = "Something",
NormalizedTitle = "Something".ToNormalized(),
CoverImage = $"{ImageService.GetCollectionTagFormat(1)}.jpg"
});
s.CoverImage = $"{ImageService.GetSeriesFormat(1)}.jpg";
s.LibraryId = 1;
_context.Series.Add(s);
s = DbFactory.Series("Test 2"); _context.Series.Add(new SeriesBuilder("Test 1")
s.Metadata.CollectionTags = new List<CollectionTag>(); .WithMetadata(new SeriesMetadataBuilder()
s.Metadata.CollectionTags.Add(new CollectionTag() .WithCollectionTag(new CollectionTagBuilder("Something")
{ .WithCoverImage($"{ImageService.GetCollectionTagFormat(1)}.jpg")
Title = "Something 2", .Build())
NormalizedTitle = "Something 2".ToNormalized(), .Build())
CoverImage = $"{ImageService.GetCollectionTagFormat(2)}.jpg" .WithCoverImage($"{ImageService.GetSeriesFormat(1)}.jpg")
}); .WithLibraryId(1)
s.CoverImage = $"{ImageService.GetSeriesFormat(3)}.jpg"; .Build());
s.LibraryId = 1;
_context.Series.Add(s); _context.Series.Add(new SeriesBuilder("Test 2")
.WithMetadata(new SeriesMetadataBuilder()
.WithCollectionTag(new CollectionTagBuilder("Something")
.WithCoverImage($"{ImageService.GetCollectionTagFormat(2)}.jpg")
.Build())
.Build())
.WithCoverImage($"{ImageService.GetSeriesFormat(3)}.jpg")
.WithLibraryId(1)
.Build());
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -247,20 +226,14 @@ public class CleanupServiceTests : AbstractDbTest
UserName = "Joe", UserName = "Joe",
ReadingLists = new List<ReadingList>() ReadingLists = new List<ReadingList>()
{ {
new ReadingList() new ReadingListBuilder("Something")
{ .WithRating(AgeRating.Unknown)
Title = "Something", .WithCoverImage($"{ImageService.GetReadingListFormat(1)}.jpg")
NormalizedTitle = "Something".ToNormalized(), .Build(),
CoverImage = $"{ImageService.GetReadingListFormat(1)}.jpg", new ReadingListBuilder("Something 2")
AgeRating = AgeRating.Unknown .WithRating(AgeRating.Unknown)
}, .WithCoverImage($"{ImageService.GetReadingListFormat(2)}.jpg")
new ReadingList() .Build(),
{
Title = "Something 2",
NormalizedTitle = "Something 2".ToNormalized(),
CoverImage = $"{ImageService.GetReadingListFormat(2)}.jpg",
AgeRating = AgeRating.Unknown
}
} }
}); });
@ -415,17 +388,12 @@ public class CleanupServiceTests : AbstractDbTest
.Build(); .Build();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(1) .WithNumber(1)
.WithChapter(c) .WithChapter(c)
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -474,11 +442,7 @@ public class CleanupServiceTests : AbstractDbTest
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadataBuilder().WithCollectionTag(c).Build()) .WithMetadata(new SeriesMetadataBuilder().WithCollectionTag(c).Build())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(s); _context.Series.Add(s);
@ -515,11 +479,7 @@ public class CleanupServiceTests : AbstractDbTest
.WithMetadata(new SeriesMetadataBuilder().WithPublicationStatus(PublicationStatus.Completed).Build()) .WithMetadata(new SeriesMetadataBuilder().WithPublicationStatus(PublicationStatus.Completed).Build())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb").Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(s); _context.Series.Add(s);
var user = new AppUser() var user = new AppUser()

View File

@ -6,6 +6,7 @@ using API.Data.Repositories;
using API.DTOs.CollectionTags; using API.DTOs.CollectionTags;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Helpers.Builders;
using API.Services; using API.Services;
using API.SignalR; using API.SignalR;
using API.Tests.Helpers; using API.Tests.Helpers;
@ -33,19 +34,14 @@ public class CollectionTagServiceTests : AbstractDbTest
private async Task SeedSeries() private async Task SeedSeries()
{ {
if (_context.CollectionTag.Any()) return; if (_context.CollectionTag.Any()) return;
_context.Library.Add(new Library()
{
Name = "Library 2",
Type = LibraryType.Manga,
Series = new List<Series>()
{
EntityFactory.CreateSeries("Series 1"),
EntityFactory.CreateSeries("Series 2"),
}
});
_context.CollectionTag.Add(DbFactory.CollectionTag(0, "Tag 1", string.Empty, false)); _context.Library.Add(new LibraryBuilder("Library 2", LibraryType.Manga)
_context.CollectionTag.Add(DbFactory.CollectionTag(0, "Tag 2", string.Empty, true)); .WithSeries(new SeriesBuilder("Series 1").Build())
.WithSeries(new SeriesBuilder("Series 2").Build())
.Build());
_context.CollectionTag.Add(new CollectionTagBuilder("Tag 1").Build());
_context.CollectionTag.Add(new CollectionTagBuilder("Tag 2").WithIsPromoted(true).Build());
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();
} }
@ -63,8 +59,8 @@ public class CollectionTagServiceTests : AbstractDbTest
public async Task UpdateTag_ShouldUpdateFields() public async Task UpdateTag_ShouldUpdateFields()
{ {
await SeedSeries(); await SeedSeries();
_context.CollectionTag.Add(EntityFactory.CreateCollectionTag(3, "UpdateTag_ShouldUpdateFields",
string.Empty, true)); _context.CollectionTag.Add(new CollectionTagBuilder("UpdateTag_ShouldUpdateFields").WithId(3).WithIsPromoted(true).Build());
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();
await _service.UpdateTag(new CollectionTagDto() await _service.UpdateTag(new CollectionTagDto()

View File

@ -9,7 +9,7 @@ using API.Data.Metadata;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Parser; using API.Helpers.Builders;
using API.Services; using API.Services;
using API.Services.Tasks.Scanner; using API.Services.Tasks.Scanner;
using API.Services.Tasks.Scanner.Parser; using API.Services.Tasks.Scanner.Parser;
@ -118,17 +118,9 @@ public class ParseScannedFilesTests
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Manga")
{ .WithFolderPath(new FolderPathBuilder(DataDirectory).Build())
Name = "Manga", .Build());
Folders = new List<FolderPath>()
{
new FolderPath()
{
Path = DataDirectory
}
}
});
return await _context.SaveChangesAsync() > 0; return await _context.SaveChangesAsync() > 0;
} }

View File

@ -0,0 +1,72 @@
using System.IO;
using API.Data;
using API.Data.Metadata;
using API.Entities;
using API.Entities.Enums;
using API.Helpers;
using API.Helpers.Builders;
using API.Services;
using API.Services.Tasks.Metadata;
using API.Services.Tasks.Scanner;
using API.SignalR;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
namespace API.Tests.Services;
public class ProcessSeriesTests
{
#region UpdateSeriesMetadata
#endregion
#region UpdateVolumes
#endregion
#region UpdateChapters
#endregion
#region AddOrUpdateFileForChapter
#endregion
#region UpdateChapterFromComicInfo
public void UpdateChapterFromComicInfo_()
{
// TODO: Do this
var file = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ScannerService/Library/Manga/Hajime no Ippo/Hajime no Ippo Chapter 1.cbz");
// Chapter and ComicInfo
var chapter = new ChapterBuilder("1")
.WithId(0)
.WithFile(new MangaFileBuilder(file, MangaFormat.Archive).Build())
.Build();
var ps = new ProcessSeries(Substitute.For<IUnitOfWork>(), Substitute.For<ILogger<ProcessSeries>>(),
Substitute.For<IEventHub>(), Substitute.For<IDirectoryService>()
, Substitute.For<ICacheHelper>(), Substitute.For<IReadingItemService>(), Substitute.For<IFileService>(),
Substitute.For<IMetadataService>(),
Substitute.For<IWordCountAnalyzerService>(),
Substitute.For<ICollectionTagService>());
ps.UpdateChapterFromComicInfo(chapter, new ComicInfo()
{
});
}
#endregion
}

View File

@ -81,10 +81,9 @@ public class ReaderServiceTests
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Manga")
{ .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
Name = "Manga", Folders = new List<FolderPath>() {new FolderPath() {Path = "C:/data/"}} .Build());
});
return await _context.SaveChangesAsync() > 0; return await _context.SaveChangesAsync() > 0;
} }
@ -130,7 +129,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("0") .WithChapter(new ChapterBuilder("0")
@ -138,11 +136,8 @@ public class ReaderServiceTests
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -164,7 +159,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("0") .WithChapter(new ChapterBuilder("0")
@ -172,11 +166,7 @@ public class ReaderServiceTests
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -208,7 +198,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("0") .WithChapter(new ChapterBuilder("0")
@ -216,11 +205,7 @@ public class ReaderServiceTests
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -269,7 +254,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("0") .WithChapter(new ChapterBuilder("0")
@ -280,11 +264,7 @@ public class ReaderServiceTests
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -313,7 +293,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("0") .WithChapter(new ChapterBuilder("0")
@ -324,11 +303,7 @@ public class ReaderServiceTests
.Build()) .Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -366,7 +341,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -385,11 +359,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").Build()) .WithChapter(new ChapterBuilder("32").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -441,7 +411,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -460,11 +429,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").Build()) .WithChapter(new ChapterBuilder("32").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -490,7 +455,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -509,11 +473,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").Build()) .WithChapter(new ChapterBuilder("32").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -539,7 +499,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -552,11 +511,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("22").Build()) .WithChapter(new ChapterBuilder("22").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -582,7 +537,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("66").Build()) .WithChapter(new ChapterBuilder("66").Build())
@ -599,11 +553,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("0").Build()) .WithChapter(new ChapterBuilder("0").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -629,7 +579,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -642,11 +591,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -672,18 +617,13 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build()) .WithChapter(new ChapterBuilder("2").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -707,7 +647,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -720,11 +659,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("2").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("2").WithIsSpecial(true).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -749,7 +684,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -762,11 +696,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -793,7 +723,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -801,11 +730,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("A.cbz").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("A.cbz").WithIsSpecial(true).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -831,7 +756,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -843,11 +767,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("0").Build()) .WithChapter(new ChapterBuilder("0").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -872,7 +792,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -884,11 +803,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -919,7 +834,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -938,11 +852,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").Build()) .WithChapter(new ChapterBuilder("32").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -967,7 +877,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -986,11 +895,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").Build()) .WithChapter(new ChapterBuilder("32").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -1012,7 +917,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("40").WithPages(1).Build()) .WithChapter(new ChapterBuilder("40").WithPages(1).Build())
.WithChapter(new ChapterBuilder("50").WithPages(1).Build()) .WithChapter(new ChapterBuilder("50").WithPages(1).Build())
@ -1032,11 +936,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("31").WithPages(1).Build()) .WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -1061,7 +961,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -1077,11 +976,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").WithPages(1).Build()) .WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1106,7 +1001,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -1119,11 +1013,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1149,18 +1039,13 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build()) .WithChapter(new ChapterBuilder("2").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1184,17 +1069,12 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("0").Build()) .WithChapter(new ChapterBuilder("0").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1218,7 +1098,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
@ -1230,11 +1109,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("0").Build()) .WithChapter(new ChapterBuilder("0").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1258,7 +1133,6 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("5").Build()) .WithChapter(new ChapterBuilder("5").Build())
@ -1278,11 +1152,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("4").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("4").WithIsSpecial(true).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1311,18 +1181,13 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build()) .WithChapter(new ChapterBuilder("2").Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1346,24 +1211,18 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build()) .WithChapter(new ChapterBuilder("2").Build())
.Build()) .Build())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("A.cbz").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("A.cbz").WithIsSpecial(true).Build())
.WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build()) .WithChapter(new ChapterBuilder("B.cbz").WithIsSpecial(true).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1390,13 +1249,11 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithNumber(0) .WithNumber(0)
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build()) .WithChapter(new ChapterBuilder("2").Build())
.Build()) .Build())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithNumber(1) .WithNumber(1)
.WithChapter(new ChapterBuilder("21").Build()) .WithChapter(new ChapterBuilder("21").Build())
@ -1404,11 +1261,7 @@ public class ReaderServiceTests
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1436,12 +1289,10 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").Build()) .WithChapter(new ChapterBuilder("95").Build())
.WithChapter(new ChapterBuilder("96").Build()) .WithChapter(new ChapterBuilder("96").Build())
.Build()) .Build())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").Build()) .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build()) .WithChapter(new ChapterBuilder("2").Build())
@ -1456,11 +1307,7 @@ public class ReaderServiceTests
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1485,21 +1332,15 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(3).Build()) .WithChapter(new ChapterBuilder("1").WithPages(3).Build())
.Build()) .Build())
.WithVolume(new VolumeBuilder("2") .WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build()) .Build())
.WithPages(4) .WithPages(4)
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1530,7 +1371,6 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -1545,11 +1385,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").WithPages(1).Build()) .WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1600,7 +1436,6 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
// Loose chapters // Loose chapters
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("45").WithPages(1).Build()) .WithChapter(new ChapterBuilder("45").WithPages(1).Build())
@ -1624,11 +1459,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").WithPages(1).Build()) .WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1673,12 +1504,10 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
.Build()) .Build())
.WithVolume(new VolumeBuilder("2") .WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).Build()) .WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.Build()) .Build())
@ -1687,11 +1516,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("32").WithPages(1).Build()) .WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1740,7 +1565,6 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("230").WithPages(1).Build()) .WithChapter(new ChapterBuilder("230").WithPages(1).Build())
.WithChapter(new ChapterBuilder("231").WithPages(1).Build()) .WithChapter(new ChapterBuilder("231").WithPages(1).Build())
@ -1754,11 +1578,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("21").WithPages(1).Build()) .WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1781,7 +1601,6 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("100").WithPages(1).Build()) .WithChapter(new ChapterBuilder("100").WithPages(1).Build())
.WithChapter(new ChapterBuilder("101").WithPages(1).Build()) .WithChapter(new ChapterBuilder("101").WithPages(1).Build())
@ -1796,11 +1615,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("21").WithPages(1).Build()) .WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1845,7 +1660,6 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -1855,11 +1669,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("21").WithPages(1).Build()) .WithChapter(new ChapterBuilder("21").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1907,7 +1717,7 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -1919,11 +1729,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("22").WithPages(1).Build()) .WithChapter(new ChapterBuilder("22").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -1951,7 +1757,7 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -1959,11 +1765,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("Some Special Title").WithIsSpecial(true).WithPages(1).Build()) .WithChapter(new ChapterBuilder("Some Special Title").WithIsSpecial(true).WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2011,7 +1813,7 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("230").WithPages(1).Build()) .WithChapter(new ChapterBuilder("230").WithPages(1).Build())
//.WithChapter(new ChapterBuilder("231").WithPages(1).Build()) (Added later) //.WithChapter(new ChapterBuilder("231").WithPages(1).Build()) (Added later)
@ -2026,11 +1828,7 @@ public class ReaderServiceTests
//.WithChapter(new ChapterBuilder("14.9").WithPages(1).Build()) (added later) //.WithChapter(new ChapterBuilder("14.9").WithPages(1).Build()) (added later)
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2048,8 +1846,12 @@ public class ReaderServiceTests
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
// Add 2 new unread series to the Series // Add 2 new unread series to the Series
series.Volumes[0].Chapters.Add(EntityFactory.CreateChapter("231", false, new List<MangaFile>(), 1)); series.Volumes[0].Chapters.Add(new ChapterBuilder("231")
series.Volumes[2].Chapters.Add(EntityFactory.CreateChapter("14.9", false, new List<MangaFile>(), 1)); .WithPages(1)
.Build());
series.Volumes[2].Chapters.Add(new ChapterBuilder("14.9")
.WithPages(1)
.Build());
_context.Series.Attach(series); _context.Series.Attach(series);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -2067,7 +1869,7 @@ public class ReaderServiceTests
var volume = new VolumeBuilder("3").WithChapter(new ChapterBuilder("0").WithPages(1).Build()).Build(); var volume = new VolumeBuilder("3").WithChapter(new ChapterBuilder("0").WithPages(1).Build()).Build();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("51").WithPages(1).Build()) .WithChapter(new ChapterBuilder("51").WithPages(1).Build())
.WithChapter(new ChapterBuilder("52").WithPages(1).Build()) .WithChapter(new ChapterBuilder("52").WithPages(1).Build())
@ -2089,11 +1891,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("41").WithPages(1).Build()) .WithChapter(new ChapterBuilder("41").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2130,7 +1928,7 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -2138,11 +1936,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("Some Special Title").WithIsSpecial(true).WithPages(1).Build()) .WithChapter(new ChapterBuilder("Some Special Title").WithIsSpecial(true).WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2171,7 +1965,7 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -2180,11 +1974,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("Some Special Title").WithIsSpecial(true).WithPages(1).Build()) .WithChapter(new ChapterBuilder("Some Special Title").WithIsSpecial(true).WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2214,7 +2004,7 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build()) .Build())
@ -2222,11 +2012,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2252,7 +2038,7 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("45").WithPages(5).Build()) .WithChapter(new ChapterBuilder("45").WithPages(5).Build())
.WithChapter(new ChapterBuilder("46").WithPages(46).Build()) .WithChapter(new ChapterBuilder("46").WithPages(46).Build())
@ -2275,11 +2061,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("14").WithPages(5).Build()) .WithChapter(new ChapterBuilder("14").WithPages(5).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2323,7 +2105,7 @@ public class ReaderServiceTests
await ResetDb(); await ResetDb();
// TODO: Validate this is correct, shouldn't be possible to have 2 Volume 0's in a series // TODO: Validate this is correct, shouldn't be possible to have 2 Volume 0's in a series
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.WithChapter(new ChapterBuilder("1").WithPages(2).Build()) .WithChapter(new ChapterBuilder("1").WithPages(2).Build())
@ -2333,11 +2115,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("1").WithPages(2).Build()) .WithChapter(new ChapterBuilder("1").WithPages(2).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2366,17 +2144,13 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.WithChapter(new ChapterBuilder("1").WithPages(2).Build()) .WithChapter(new ChapterBuilder("1").WithPages(2).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2443,7 +2217,7 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("10").WithPages(1).Build()) .WithChapter(new ChapterBuilder("10").WithPages(1).Build())
.WithChapter(new ChapterBuilder("20").WithPages(1).Build()) .WithChapter(new ChapterBuilder("20").WithPages(1).Build())
@ -2462,11 +2236,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);
@ -2501,7 +2271,6 @@ public class ReaderServiceTests
{ {
await ResetDb(); await ResetDb();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("10").WithPages(1).Build()) .WithChapter(new ChapterBuilder("10").WithPages(1).Build())
.WithChapter(new ChapterBuilder("20").WithPages(1).Build()) .WithChapter(new ChapterBuilder("20").WithPages(1).Build())
@ -2520,11 +2289,7 @@ public class ReaderServiceTests
.WithChapter(new ChapterBuilder("3").WithPages(1).Build()) .WithChapter(new ChapterBuilder("3").WithPages(1).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
_context.Series.Add(series); _context.Series.Add(series);

View File

@ -11,6 +11,7 @@ using API.DTOs.ReadingLists;
using API.DTOs.ReadingLists.CBL; using API.DTOs.ReadingLists.CBL;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions; using API.Extensions;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders; using API.Helpers.Builders;
@ -78,10 +79,10 @@ public class ReadingListServiceTests
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Manga")
{ .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
Name = "Manga", Folders = new List<FolderPath>() {new FolderPath() {Path = "C:/data/"}} .Build());
});
return await _context.SaveChangesAsync() > 0; return await _context.SaveChangesAsync() > 0;
} }
@ -114,20 +115,10 @@ public class ReadingListServiceTests
public async Task AddChaptersToReadingList_ShouldAddFirstItem_AsOrderZero() public async Task AddChaptersToReadingList_ShouldAddFirstItem_AsOrderZero()
{ {
await ResetDb(); await ResetDb();
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUserBuilder("majora2007", "")
{ .WithLibrary(new LibraryBuilder("Test LIb", LibraryType.Book)
UserName = "majora2007", .WithSeries(new SeriesBuilder("Test")
ReadingLists = new List<ReadingList>(), .WithMetadata(new SeriesMetadataBuilder().Build())
Libraries = new List<Library>()
{
new Library()
{
Name = "Test LIb",
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -145,16 +136,16 @@ public class ReadingListServiceTests
) )
.Build() .Build()
}) })
.Build(), .Build())
} .Build()
}, )
} .Build()
}); );
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("test"); var readingList = new ReadingListBuilder("test").Build();
user!.ReadingLists = new List<ReadingList>() user!.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -171,20 +162,9 @@ public class ReadingListServiceTests
public async Task AddChaptersToReadingList_ShouldNewItems_AfterLastOrder() public async Task AddChaptersToReadingList_ShouldNewItems_AfterLastOrder()
{ {
await ResetDb(); await ResetDb();
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUserBuilder("majora2007", "")
{ .WithLibrary(new LibraryBuilder("Test LIb", LibraryType.Book)
UserName = "majora2007", .WithSeries(new SeriesBuilder("Test")
ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>()
{
new Library()
{
Name = "Test LIb",
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -202,16 +182,16 @@ public class ReadingListServiceTests
) )
.Build() .Build()
}) })
.Build())
.Build() .Build()
} )
}, .Build()
} );
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("test"); var readingList = new ReadingListBuilder("test").Build();
user!.ReadingLists = new List<ReadingList>() user!.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -241,14 +221,9 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb", LibraryType.Book)
{ .WithSeries(new SeriesBuilder("Test")
Name = "Test LIb", .WithMetadata(new SeriesMetadataBuilder().Build())
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -266,16 +241,15 @@ public class ReadingListServiceTests
) )
.Build() .Build()
}) })
.Build())
.Build() .Build()
} }
},
}
}); });
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("Test"); var readingList = new ReadingListBuilder("test").Build();
user.ReadingLists = new List<ReadingList>() user.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -307,14 +281,9 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb", LibraryType.Book)
{ .WithSeries(new SeriesBuilder("Test")
Name = "Test LIb", .WithMetadata(new SeriesMetadataBuilder().Build())
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -332,16 +301,15 @@ public class ReadingListServiceTests
) )
.Build() .Build()
}) })
.Build())
.Build() .Build()
} }
},
}
}); });
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("test"); var readingList = new ReadingListBuilder("test").Build();
user!.ReadingLists = new List<ReadingList>() user!.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -392,14 +360,9 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb", LibraryType.Book)
{ .WithSeries(new SeriesBuilder("Test")
Name = "Test LIb", .WithMetadata(new SeriesMetadataBuilder().Build())
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -413,16 +376,15 @@ public class ReadingListServiceTests
) )
.Build() .Build()
}) })
.Build(), .Build())
} .Build()
},
} }
}); });
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("Test"); var readingList = new ReadingListBuilder("test").Build();
user.ReadingLists = new List<ReadingList>() user.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -455,14 +417,9 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb", LibraryType.Book)
{ .WithSeries(new SeriesBuilder("Test")
Name = "Test LIb", .WithMetadata(new SeriesMetadataBuilder().Build())
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -480,16 +437,15 @@ public class ReadingListServiceTests
) )
.Build() .Build()
}) })
.Build())
.Build() .Build()
} }
},
}
}); });
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists | AppUserIncludes.Progress); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists | AppUserIncludes.Progress);
var readingList = DbFactory.ReadingList("Test"); var readingList = new ReadingListBuilder("test").Build();
user.ReadingLists = new List<ReadingList>() user.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -529,14 +485,9 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb", LibraryType.Book)
{ .WithSeries(new SeriesBuilder("Test")
Name = "Test LIb", .WithMetadata(new SeriesMetadataBuilder().Build())
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>()))
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -548,16 +499,15 @@ public class ReadingListServiceTests
) )
.Build() .Build()
}) })
.Build())
.Build() .Build()
} }
},
}
}); });
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("Test"); var readingList = new ReadingListBuilder("test").Build();
user!.ReadingLists = new List<ReadingList>() user!.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -578,7 +528,7 @@ public class ReadingListServiceTests
{ {
await ResetDb(); await ResetDb();
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>())) .WithMetadata(new SeriesMetadataBuilder().Build())
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -597,15 +547,9 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb 2", LibraryType.Book)
{ .WithSeries(s)
Name = "Test LIb", .Build()
Type = LibraryType.Book,
Series = new List<Series>()
{
s
}
},
} }
}); });
@ -614,7 +558,7 @@ public class ReadingListServiceTests
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("Test"); var readingList = new ReadingListBuilder("test").Build();
user.ReadingLists = new List<ReadingList>() user.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -639,7 +583,7 @@ public class ReadingListServiceTests
{ {
await ResetDb(); await ResetDb();
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>())) .WithMetadata(new SeriesMetadataBuilder().Build())
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -658,22 +602,16 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb 2", LibraryType.Book)
{ .WithSeries(s)
Name = "Test LIb", .Build()
Type = LibraryType.Book,
Series = new List<Series>()
{
s
}
},
} }
}); });
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("Test"); var readingList = new ReadingListBuilder("test").Build();
user.ReadingLists = new List<ReadingList>() user.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -697,7 +635,7 @@ public class ReadingListServiceTests
{ {
await ResetDb(); await ResetDb();
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(DbFactory.SeriesMetadata(new List<CollectionTag>())) .WithMetadata(new SeriesMetadataBuilder().Build())
.WithVolumes(new List<Volume>() .WithVolumes(new List<Volume>()
{ {
new VolumeBuilder("0") new VolumeBuilder("0")
@ -718,22 +656,16 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb 2", LibraryType.Book)
{ .WithSeries(s)
Name = "Test LIb", .Build()
Type = LibraryType.Book,
Series = new List<Series>()
{
s
}
},
} }
}); });
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists); var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.ReadingLists);
var readingList = DbFactory.ReadingList("Test"); var readingList = new ReadingListBuilder("test").Build();
user.ReadingLists = new List<ReadingList>() user.ReadingLists = new List<ReadingList>()
{ {
readingList readingList
@ -817,51 +749,27 @@ public class ReadingListServiceTests
private async Task CreateReadingList_SetupBaseData() private async Task CreateReadingList_SetupBaseData()
{ {
var fablesSeries = DbFactory.Series("Fables"); var fablesSeries = new SeriesBuilder("Fables").Build();
fablesSeries.Volumes.Add(new Volume() fablesSeries.Volumes.Add(
{ new VolumeBuilder("1")
Number = 1, .WithNumber(1)
Name = "2002", .WithName("2002")
Chapters = new List<Chapter>() .WithChapter(new ChapterBuilder("1").Build())
{ .Build()
EntityFactory.CreateChapter("1", false), );
}
});
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUserBuilder("majora2007", string.Empty)
{ .WithLibrary(new LibraryBuilder("Test LIb 2", LibraryType.Book)
UserName = "majora2007", .WithSeries(fablesSeries)
ReadingLists = new List<ReadingList>(), .Build())
Libraries = new List<Library>() .Build()
{ );
new Library() _context.AppUser.Add(new AppUserBuilder("admin", string.Empty)
{ .WithLibrary(new LibraryBuilder("Test LIb 2", LibraryType.Book)
Name = "Test Lib", .WithSeries(fablesSeries)
Type = LibraryType.Book, .Build())
Series = new List<Series>() .Build()
{ );
fablesSeries,
},
},
},
});
_context.AppUser.Add(new AppUser()
{
UserName = "admin",
ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>()
{
new Library()
{
Name = "Test Lib 2",
Type = LibraryType.Book,
Series = new List<Series>()
{
fablesSeries,
},
},
}
});
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();
} }
@ -1016,51 +924,33 @@ public class ReadingListServiceTests
var cblReadingList = LoadCblFromPath("Fables.cbl"); var cblReadingList = LoadCblFromPath("Fables.cbl");
// Mock up our series // Mock up our series
var fablesSeries = DbFactory.Series("Fables"); var fablesSeries = new SeriesBuilder("Fables").Build();
var fables2Series = DbFactory.Series("Fables: The Last Castle"); var fables2Series = new SeriesBuilder("Fables: The Last Castle").Build();
fablesSeries.Volumes.Add(new Volume() fablesSeries.Volumes.Add(new VolumeBuilder("1")
{ .WithNumber(1)
Number = 1, .WithName("2002")
Name = "2002", .WithChapter(new ChapterBuilder("1").Build())
Chapters = new List<Chapter>() .WithChapter(new ChapterBuilder("2").Build())
{ .WithChapter(new ChapterBuilder("3").Build())
EntityFactory.CreateChapter("1", false), .Build()
EntityFactory.CreateChapter("2", false), );
EntityFactory.CreateChapter("3", false), fables2Series.Volumes.Add(new VolumeBuilder("1")
.WithNumber(1)
.WithName("2003")
.WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build())
.WithChapter(new ChapterBuilder("3").Build())
.Build()
);
} _context.AppUser.Add(new AppUserBuilder("majora2007", string.Empty).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),
} _context.Library.Add(new LibraryBuilder("Test LIb 2", LibraryType.Book)
}); .WithSeries(fablesSeries)
.WithSeries(fables2Series)
_context.AppUser.Add(new AppUser() .Build()
{ );
UserName = "majora2007",
ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>(),
});
_context.Library.Add(new Library()
{
Name = "Test Lib 2",
Type = LibraryType.Book,
Series = new List<Series>()
{
fablesSeries,
fables2Series,
},
});
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();
@ -1077,33 +967,21 @@ public class ReadingListServiceTests
var cblReadingList = LoadCblFromPath("Fables.cbl"); var cblReadingList = LoadCblFromPath("Fables.cbl");
// Mock up our series // Mock up our series
var fablesSeries = DbFactory.Series("Fablesa"); var fablesSeries = new SeriesBuilder("Fablesa").Build();
var fables2Series = DbFactory.Series("Fablesa: The Last Castle"); var fables2Series = new SeriesBuilder("Fablesa: The Last Castle").Build();
fablesSeries.Volumes.Add(new Volume() fablesSeries.Volumes.Add(new VolumeBuilder("2002")
{ .WithNumber(1)
Number = 1, .WithChapter(new ChapterBuilder("1").Build())
Name = "2002", .WithChapter(new ChapterBuilder("2").Build())
Chapters = new List<Chapter>() .WithChapter(new ChapterBuilder("3").Build())
{ .Build());
EntityFactory.CreateChapter("1", false), fables2Series.Volumes.Add(new VolumeBuilder("2003")
EntityFactory.CreateChapter("2", false), .WithNumber(1)
EntityFactory.CreateChapter("3", false), .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build())
} .WithChapter(new ChapterBuilder("3").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),
}
});
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -1112,16 +990,10 @@ public class ReadingListServiceTests
Libraries = new List<Library>(), Libraries = new List<Library>(),
}); });
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb 2", LibraryType.Book)
{ .WithSeries(fablesSeries)
Name = "Test Lib 2", .WithSeries(fables2Series)
Type = LibraryType.Book, .Build());
Series = new List<Series>()
{
fablesSeries,
fables2Series,
},
});
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();
@ -1153,9 +1025,6 @@ public class ReadingListServiceTests
var cblReadingList = LoadCblFromPath("Fables.cbl"); var cblReadingList = LoadCblFromPath("Fables.cbl");
// Mock up our series // Mock up our series
// var fablesSeries = DbFactory.Series("Fables");
// var fables2Series = DbFactory.Series("Fables: The Last Castle");
var fablesSeries = new SeriesBuilder("Fables") var fablesSeries = new SeriesBuilder("Fables")
.WithVolume(new VolumeBuilder("2002") .WithVolume(new VolumeBuilder("2002")
.WithNumber(1) .WithNumber(1)
@ -1174,49 +1043,16 @@ public class ReadingListServiceTests
.Build()) .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() _context.AppUser.Add(new AppUser()
{ {
UserName = "majora2007", UserName = "majora2007",
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb 2", LibraryType.Book)
{ .WithSeries(fablesSeries)
Name = "Test LIb", .WithSeries(fables2Series)
Type = LibraryType.Book, .Build()
Series = new List<Series>()
{
fablesSeries,
fables2Series
},
},
}, },
}); });
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();
@ -1245,33 +1081,21 @@ public class ReadingListServiceTests
var cblReadingList = LoadCblFromPath("Fables.cbl"); var cblReadingList = LoadCblFromPath("Fables.cbl");
// Mock up our series // Mock up our series
var fablesSeries = DbFactory.Series("Fables"); var fablesSeries = new SeriesBuilder("Fables").Build();
var fables2Series = DbFactory.Series("Fables: The Last Castle"); var fables2Series = new SeriesBuilder("Fables: The Last Castle").Build();
fablesSeries.Volumes.Add(new Volume() fablesSeries.Volumes.Add(new VolumeBuilder("2002")
{ .WithNumber(1)
Number = 1, .WithChapter(new ChapterBuilder("1").Build())
Name = "2002", .WithChapter(new ChapterBuilder("2").Build())
Chapters = new List<Chapter>() .WithChapter(new ChapterBuilder("3").Build())
{ .Build());
EntityFactory.CreateChapter("1", false), fables2Series.Volumes.Add(new VolumeBuilder("2003")
EntityFactory.CreateChapter("2", false), .WithNumber(1)
EntityFactory.CreateChapter("3", false), .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build())
} .WithChapter(new ChapterBuilder("3").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),
}
});
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -1279,27 +1103,15 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb 2", LibraryType.Book)
{ .WithSeries(fablesSeries)
Name = "Test LIb", .Build()
Type = LibraryType.Book,
Series = new List<Series>()
{
fablesSeries,
},
},
}, },
}); });
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb 2", LibraryType.Book)
{ .WithSeries(fables2Series)
Name = "Test Lib 2", .Build());
Type = LibraryType.Book,
Series = new List<Series>()
{
fables2Series,
},
});
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();
@ -1328,33 +1140,21 @@ public class ReadingListServiceTests
var cblReadingList = LoadCblFromPath("Fables.cbl"); var cblReadingList = LoadCblFromPath("Fables.cbl");
// Mock up our series // Mock up our series
var fablesSeries = DbFactory.Series("Fables"); var fablesSeries = new SeriesBuilder("Fables").Build();
var fables2Series = DbFactory.Series("Fables: The Last Castle"); var fables2Series = new SeriesBuilder("Fables: The Last Castle").Build();
fablesSeries.Volumes.Add(new Volume() fablesSeries.Volumes.Add(new VolumeBuilder("2002")
{ .WithNumber(1)
Number = 1, .WithChapter(new ChapterBuilder("1").Build())
Name = "2002", .WithChapter(new ChapterBuilder("2").Build())
Chapters = new List<Chapter>() .WithChapter(new ChapterBuilder("3").Build())
{ .Build());
EntityFactory.CreateChapter("1", false), fables2Series.Volumes.Add(new VolumeBuilder("2003")
EntityFactory.CreateChapter("2", false), .WithNumber(1)
EntityFactory.CreateChapter("3", false), .WithChapter(new ChapterBuilder("1").Build())
.WithChapter(new ChapterBuilder("2").Build())
} .WithChapter(new ChapterBuilder("3").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),
}
});
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -1362,16 +1162,10 @@ public class ReadingListServiceTests
ReadingLists = new List<ReadingList>(), ReadingLists = new List<ReadingList>(),
Libraries = new List<Library>() Libraries = new List<Library>()
{ {
new Library() new LibraryBuilder("Test LIb 2", LibraryType.Book)
{ .WithSeries(fablesSeries)
Name = "Test LIb", .WithSeries(fables2Series)
Type = LibraryType.Book, .Build()
Series = new List<Series>()
{
fablesSeries,
fables2Series
},
},
}, },
}); });

View File

@ -5,9 +5,9 @@ using API.Entities.Enums;
using API.Entities.Metadata; using API.Entities.Metadata;
using API.Extensions; using API.Extensions;
using API.Helpers.Builders; using API.Helpers.Builders;
using API.Parser;
using API.Services.Tasks; using API.Services.Tasks;
using API.Services.Tasks.Scanner; using API.Services.Tasks.Scanner;
using API.Services.Tasks.Scanner.Parser;
using API.Tests.Helpers; using API.Tests.Helpers;
using Xunit; using Xunit;
@ -27,7 +27,7 @@ public class ScannerServiceTests
{ {
new SeriesBuilder("Darker Than Black") new SeriesBuilder("Darker Than Black")
.WithFormat(MangaFormat.Epub) .WithFormat(MangaFormat.Epub)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithName("1") .WithName("1")
.Build()) .Build())
@ -51,7 +51,7 @@ public class ScannerServiceTests
{ {
new SeriesBuilder("Cage of Eden") new SeriesBuilder("Cage of Eden")
.WithFormat(MangaFormat.Archive) .WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithName("1") .WithName("1")
.Build()) .Build())
@ -59,30 +59,11 @@ public class ScannerServiceTests
.Build(), .Build(),
new SeriesBuilder("Darker Than Black") new SeriesBuilder("Darker Than Black")
.WithFormat(MangaFormat.Archive) .WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithName("1") .WithName("1")
.Build()) .Build())
.WithLocalizedName("Darker Than Black") .WithLocalizedName("Darker Than Black")
.Build(), .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)); Assert.Empty(ScannerService.FindSeriesNotOnDisk(existingSeries, infos));

View File

@ -74,21 +74,10 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb")
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("Omake").WithIsSpecial(true).WithTitle("Omake").WithPages(1).Build()) .WithChapter(new ChapterBuilder("Omake").WithIsSpecial(true).WithTitle("Omake").WithPages(1).Build())
.WithChapter(new ChapterBuilder("Something SP02").WithIsSpecial(true).WithTitle("Something").WithPages(1).Build()) .WithChapter(new ChapterBuilder("Something SP02").WithIsSpecial(true).WithTitle("Something").WithPages(1).Build())
@ -102,9 +91,8 @@ public class SeriesServiceTests : AbstractDbTest
.WithChapter(new ChapterBuilder("31").WithPages(1).Build()) .WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build()) .WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -122,21 +110,10 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb")
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Manga,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -150,9 +127,9 @@ public class SeriesServiceTests : AbstractDbTest
.WithChapter(new ChapterBuilder("31").WithPages(1).Build()) .WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).Build()) .WithChapter(new ChapterBuilder("32").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build()
}); );
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -170,21 +147,10 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb")
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Manga,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -196,9 +162,8 @@ public class SeriesServiceTests : AbstractDbTest
.WithVolume(new VolumeBuilder("3") .WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build()) .WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -216,21 +181,9 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb")
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Manga,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build()) .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
@ -242,9 +195,8 @@ public class SeriesServiceTests : AbstractDbTest
.WithVolume(new VolumeBuilder("3") .WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).Build()) .WithChapter(new ChapterBuilder("31").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -265,21 +217,10 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb", LibraryType.Book)
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("2") .WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build()) .Build())
@ -287,9 +228,8 @@ public class SeriesServiceTests : AbstractDbTest
.WithVolume(new VolumeBuilder("3") .WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -306,30 +246,18 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb", LibraryType.Book)
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .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()) .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()) .Build())
.WithVolume(new VolumeBuilder("2") .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()) .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())
.Build(), .Build())
} .Build());
});
@ -353,21 +281,10 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Manga,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("2") .WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build()) .Build())
@ -378,9 +295,8 @@ public class SeriesServiceTests : AbstractDbTest
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("0").WithPages(1).Build()) .WithChapter(new ChapterBuilder("0").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -402,27 +318,15 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Manga,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -451,27 +355,15 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb")
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Manga,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -517,27 +409,15 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb")
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Manga,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -564,27 +444,15 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test LIb", LibraryType.Book)
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test")
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Manga,
Series = new List<Series>()
{
new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("1") .WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build()) .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.Build()) .Build())
.Build(), .Build())
} .Build());
});
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -612,13 +480,8 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{
Name = "Test LIb",
Type = LibraryType.Book,
};
_context.Series.Add(s); _context.Series.Add(s);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -646,13 +509,8 @@ public class SeriesServiceTests : AbstractDbTest
{ {
await ResetDb(); await ResetDb();
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{
Name = "Test LIb",
Type = LibraryType.Book,
};
_context.Series.Add(s); _context.Series.Add(s);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -692,13 +550,9 @@ public class SeriesServiceTests : AbstractDbTest
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build()) .WithMetadata(new SeriesMetadataBuilder().Build())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Genre("Existing Genre"); var g = new GenreBuilder("Existing Genre").Build();
s.Metadata.Genres = new List<Genre>() {g}; s.Metadata.Genres = new List<Genre>() {g};
_context.Series.Add(s); _context.Series.Add(s);
@ -730,13 +584,9 @@ public class SeriesServiceTests : AbstractDbTest
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build()) .WithMetadata(new SeriesMetadataBuilder().Build())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Person("Existing Person", PersonRole.Publisher); var g = new PersonBuilder("Existing Person", PersonRole.Publisher).Build();
_context.Series.Add(s); _context.Series.Add(s);
_context.Person.Add(g); _context.Person.Add(g);
@ -767,14 +617,10 @@ public class SeriesServiceTests : AbstractDbTest
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build()) .WithMetadata(new SeriesMetadataBuilder().Build())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{ var g = new PersonBuilder("Existing Person", PersonRole.Publisher).Build();
Name = "Test LIb", s.Metadata.People = new List<Person>() {new PersonBuilder("Existing Writer", PersonRole.Writer).Build(),
Type = LibraryType.Book, new PersonBuilder("Existing Translator", PersonRole.Translator).Build(), new PersonBuilder("Existing Publisher 2", PersonRole.Publisher).Build()};
};
var g = DbFactory.Person("Existing Person", PersonRole.Publisher);
s.Metadata.People = new List<Person>() {DbFactory.Person("Existing Writer", PersonRole.Writer),
DbFactory.Person("Existing Translator", PersonRole.Translator), DbFactory.Person("Existing Publisher 2", PersonRole.Publisher)};
_context.Series.Add(s); _context.Series.Add(s);
_context.Person.Add(g); _context.Person.Add(g);
@ -807,12 +653,8 @@ public class SeriesServiceTests : AbstractDbTest
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build()) .WithMetadata(new SeriesMetadataBuilder().Build())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{ var g = new PersonBuilder("Existing Person", PersonRole.Publisher).Build();
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Person("Existing Person", PersonRole.Publisher);
_context.Series.Add(s); _context.Series.Add(s);
_context.Person.Add(g); _context.Person.Add(g);
@ -842,12 +684,8 @@ public class SeriesServiceTests : AbstractDbTest
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build()) .WithMetadata(new SeriesMetadataBuilder().Build())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{ var g = new GenreBuilder("Existing Genre").Build();
Name = "Test LIb",
Type = LibraryType.Book,
};
var g = DbFactory.Genre("Existing Genre");
s.Metadata.Genres = new List<Genre>() {g}; s.Metadata.Genres = new List<Genre>() {g};
s.Metadata.GenresLocked = true; s.Metadata.GenresLocked = true;
_context.Series.Add(s); _context.Series.Add(s);
@ -881,11 +719,7 @@ public class SeriesServiceTests : AbstractDbTest
var s = new SeriesBuilder("Test") var s = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadataBuilder().Build()) .WithMetadata(new SeriesMetadataBuilder().Build())
.Build(); .Build();
s.Library = new Library() s.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{
Name = "Test LIb",
Type = LibraryType.Book,
};
_context.Series.Add(s); _context.Series.Add(s);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -913,10 +747,9 @@ public class SeriesServiceTests : AbstractDbTest
private static Series CreateSeriesMock() private static Series CreateSeriesMock()
{ {
var file = EntityFactory.CreateMangaFile("Test.cbz", MangaFormat.Archive, 1); var file = new MangaFileBuilder("Test.cbz", MangaFormat.Archive, 1).Build();
var series = new SeriesBuilder("Test") var series = new SeriesBuilder("Test")
.WithMetadata(new SeriesMetadata())
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("95").WithPages(1).WithFile(file).Build()) .WithChapter(new ChapterBuilder("95").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("96").WithPages(1).WithFile(file).Build()) .WithChapter(new ChapterBuilder("96").WithPages(1).WithFile(file).Build())
@ -937,11 +770,7 @@ public class SeriesServiceTests : AbstractDbTest
.WithChapter(new ChapterBuilder("32").WithPages(1).WithFile(file).Build()) .WithChapter(new ChapterBuilder("32").WithPages(1).WithFile(file).Build())
.Build()) .Build())
.Build(); .Build();
series.Library = new Library() series.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
{
Name = "Test LIb",
Type = LibraryType.Manga,
};
return series; return series;
} }
@ -970,13 +799,13 @@ public class SeriesServiceTests : AbstractDbTest
var series = CreateSeriesMock(); var series = CreateSeriesMock();
var files = new List<MangaFile>() var files = new List<MangaFile>()
{ {
EntityFactory.CreateMangaFile("Test.cbz", MangaFormat.Archive, 1) new MangaFileBuilder("Test.cbz", MangaFormat.Archive, 1).Build()
}; };
series.Volumes[1].Chapters = new List<Chapter>() series.Volumes[1].Chapters = new List<Chapter>()
{ {
EntityFactory.CreateChapter("2", false, files, 1), new ChapterBuilder("2").WithFiles(files).WithPages(1).Build(),
EntityFactory.CreateChapter("1.1", false, files, 1), new ChapterBuilder("1.1").WithFiles(files).WithPages(1).Build(),
EntityFactory.CreateChapter("1.2", false, files, 1), new ChapterBuilder("1.2").WithFiles(files).WithPages(1).Build(),
}; };
var firstChapter = SeriesService.GetFirstChapterForMetadata(series, false); var firstChapter = SeriesService.GetFirstChapterForMetadata(series, false);
@ -1038,9 +867,9 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book, Type = LibraryType.Book,
Series = new List<Series>() Series = new List<Series>()
{ {
DbFactory.Series("Test Series"), new SeriesBuilder("Test Series").Build(),
DbFactory.Series("Test Series Prequels"), new SeriesBuilder("Test Series Prequels").Build(),
DbFactory.Series("Test Series Sequels"), new SeriesBuilder("Test Series Sequels").Build(),
} }
}); });
@ -1080,8 +909,8 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book, Type = LibraryType.Book,
Series = new List<Series>() Series = new List<Series>()
{ {
DbFactory.Series("Series A"), new SeriesBuilder("Series A").Build(),
DbFactory.Series("Series B"), new SeriesBuilder("Series B").Build(),
} }
}); });
@ -1125,8 +954,8 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book, Type = LibraryType.Book,
Series = new List<Series>() Series = new List<Series>()
{ {
DbFactory.Series("Series A"), new SeriesBuilder("Series A").Build(),
DbFactory.Series("Series B"), new SeriesBuilder("Series B").Build(),
} }
}); });
@ -1170,8 +999,8 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book, Type = LibraryType.Book,
Series = new List<Series>() Series = new List<Series>()
{ {
DbFactory.Series("Test Series"), new SeriesBuilder("Test Series").Build(),
DbFactory.Series("Test Series Prequels"), new SeriesBuilder("Test Series Prequels").Build(),
} }
}); });
@ -1215,11 +1044,11 @@ public class SeriesServiceTests : AbstractDbTest
Type = LibraryType.Book, Type = LibraryType.Book,
Series = new List<Series>() Series = new List<Series>()
{ {
DbFactory.Series("Test Series"), new SeriesBuilder("Test Series").Build(),
DbFactory.Series("Test Series Editions"), new SeriesBuilder("Test Series Editions").Build(),
DbFactory.Series("Test Series Prequels"), new SeriesBuilder("Test Series Prequels").Build(),
DbFactory.Series("Test Series Sequels"), new SeriesBuilder("Test Series Sequels").Build(),
DbFactory.Series("Test Series Adaption"), new SeriesBuilder("Test Series Adaption").Build(),
} }
}); });
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -1243,24 +1072,12 @@ public class SeriesServiceTests : AbstractDbTest
public async Task SeriesRelation_ShouldAllowDeleteOnLibrary() public async Task SeriesRelation_ShouldAllowDeleteOnLibrary()
{ {
await ResetDb(); await ResetDb();
var lib = new Library() var lib = new LibraryBuilder("Test LIb")
{ .WithSeries(new SeriesBuilder("Test Series").Build())
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test Series Prequels").Build())
{ .WithSeries(new SeriesBuilder("Test Series Sequels").Build())
new AppUser() .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
{ .Build();
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Book,
Series = new List<Series>()
{
DbFactory.Series("Test Series"),
DbFactory.Series("Test Series Prequels"),
DbFactory.Series("Test Series Sequels"),
}
};
_context.Library.Add(lib); _context.Library.Add(lib);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -1291,51 +1108,28 @@ public class SeriesServiceTests : AbstractDbTest
public async Task SeriesRelation_ShouldAllowDeleteOnLibrary_WhenSeriesCrossLibraries() public async Task SeriesRelation_ShouldAllowDeleteOnLibrary_WhenSeriesCrossLibraries()
{ {
await ResetDb(); await ResetDb();
var lib1 = new Library() var lib1 = new LibraryBuilder("Test LIb")
{ .WithSeries(new SeriesBuilder("Test Series")
AppUsers = new List<AppUser>()
{
new AppUser()
{
UserName = "majora2007"
}
},
Name = "Test LIb",
Type = LibraryType.Book,
Series = new List<Series>()
{
new SeriesBuilder("Test Series")
.WithVolume(new VolumeBuilder("0") .WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithFile(new MangaFile() .WithChapter(new ChapterBuilder("1").WithFile(
{ new MangaFileBuilder($"{DataDirectory}1.zip", MangaFormat.Archive)
Pages = 1, .WithPages(1)
FilePath = "fake file" .Build()
}).Build()) ).Build())
.Build()) .Build())
.Build(), .Build())
new SeriesBuilder("Test Series Prequels").Build(), .WithSeries(new SeriesBuilder("Test Series Prequels").Build())
new SeriesBuilder("Test Series Sequels").Build(), .WithSeries(new SeriesBuilder("Test Series Sequels").Build())
} .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
}; .Build();
_context.Library.Add(lib1); _context.Library.Add(lib1);
var lib2 = new Library()
{ var lib2 = new LibraryBuilder("Test LIb 2", LibraryType.Book)
AppUsers = new List<AppUser>() .WithSeries(new SeriesBuilder("Test Series 2").Build())
{ .WithSeries(new SeriesBuilder("Test Series Prequels 2").Build())
new AppUser() .WithSeries(new SeriesBuilder("Test Series Prequels 2").Build())// TODO: Is this a bug
{ .WithAppUser(new AppUserBuilder("majora2007", string.Empty).Build())
UserName = "majora2007" .Build();
}
},
Name = "Test LIb 2",
Type = LibraryType.Book,
Series = new List<Series>()
{
DbFactory.Series("Test Series 2"),
DbFactory.Series("Test Series Prequels 2"),
DbFactory.Series("Test Series Prequels 2"),
}
};
_context.Library.Add(lib2); _context.Library.Add(lib2);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -1365,7 +1159,81 @@ public class SeriesServiceTests : AbstractDbTest
#region UpdateRelatedList #region UpdateRelatedList
// TODO: Implement UpdateRelatedList
#endregion
#region FormatChapterName
[Theory]
[InlineData(LibraryType.Manga, false, "Chapter")]
[InlineData(LibraryType.Comic, false, "Issue")]
[InlineData(LibraryType.Comic, true, "Issue #")]
[InlineData(LibraryType.Book, false, "Book")]
public void FormatChapterNameTest(LibraryType libraryType, bool withHash, string expected )
{
Assert.Equal(expected, SeriesService.FormatChapterName(libraryType, withHash));
}
#endregion
#region FormatChapterTitle
[Fact]
public void FormatChapterTitle_Manga_NonSpecial()
{
var chapter = new ChapterBuilder("1").WithTitle("Some title").WithIsSpecial(false).Build();
Assert.Equal("Chapter Some title", SeriesService.FormatChapterTitle(chapter, LibraryType.Manga, false));
}
[Fact]
public void FormatChapterTitle_Manga_Special()
{
var chapter = new ChapterBuilder("1").WithTitle("Some title").WithIsSpecial(true).Build();
Assert.Equal("Some title", SeriesService.FormatChapterTitle(chapter, LibraryType.Manga, false));
}
[Fact]
public void FormatChapterTitle_Comic_NonSpecial_WithoutHash()
{
var chapter = new ChapterBuilder("1").WithTitle("Some title").WithIsSpecial(false).Build();
Assert.Equal("Issue Some title", SeriesService.FormatChapterTitle(chapter, LibraryType.Comic, false));
}
[Fact]
public void FormatChapterTitle_Comic_Special_WithoutHash()
{
var chapter = new ChapterBuilder("1").WithTitle("Some title").WithIsSpecial(true).Build();
Assert.Equal("Some title", SeriesService.FormatChapterTitle(chapter, LibraryType.Comic, false));
}
[Fact]
public void FormatChapterTitle_Comic_NonSpecial_WithHash()
{
var chapter = new ChapterBuilder("1").WithTitle("Some title").WithIsSpecial(false).Build();
Assert.Equal("Issue #Some title", SeriesService.FormatChapterTitle(chapter, LibraryType.Comic, true));
}
[Fact]
public void FormatChapterTitle_Comic_Special_WithHash()
{
var chapter = new ChapterBuilder("1").WithTitle("Some title").WithIsSpecial(true).Build();
Assert.Equal("Some title", SeriesService.FormatChapterTitle(chapter, LibraryType.Comic, true));
}
[Fact]
public void FormatChapterTitle_Book_NonSpecial()
{
var chapter = new ChapterBuilder("1").WithTitle("Some title").WithIsSpecial(false).Build();
Assert.Equal("Book Some title", SeriesService.FormatChapterTitle(chapter, LibraryType.Book, false));
}
[Fact]
public void FormatChapterTitle_Book_Special()
{
var chapter = new ChapterBuilder("1").WithTitle("Some title").WithIsSpecial(true).Build();
Assert.Equal("Some title", SeriesService.FormatChapterTitle(chapter, LibraryType.Book, false));
}
#endregion #endregion
} }

View File

@ -81,10 +81,11 @@ public class TachiyomiServiceTests
_context.ServerSetting.Update(setting); _context.ServerSetting.Update(setting);
_context.Library.Add(new Library() _context.Library.Add(
{ new LibraryBuilder("Manga")
Name = "Manga", Folders = new List<FolderPath>() {new FolderPath() {Path = "C:/data/"}} .WithFolderPath(new FolderPathBuilder("C:/data/").Build())
}); .Build()
);
return await _context.SaveChangesAsync() > 0; return await _context.SaveChangesAsync() > 0;
} }
@ -139,12 +140,10 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -186,12 +185,9 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -240,12 +236,9 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -293,12 +286,9 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -341,12 +331,9 @@ public class TachiyomiServiceTests
.WithPages(646) .WithPages(646)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -394,12 +381,9 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Comic,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -452,12 +436,9 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -498,12 +479,9 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -551,12 +529,9 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {
@ -602,12 +577,9 @@ public class TachiyomiServiceTests
.WithPages(7) .WithPages(7)
.Build(); .Build();
var library = new Library() var library = new LibraryBuilder("Test LIb", LibraryType.Manga)
{ .WithSeries(series)
Name = "Test LIb", .Build();
Type = LibraryType.Manga,
Series = new List<Series>() { series }
};
_context.AppUser.Add(new AppUser() _context.AppUser.Add(new AppUser()
{ {

View File

@ -0,0 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<ComicInfo>
<Series>Accel World</Series>
<Number>2</Number>
</ComicInfo>

View File

@ -0,0 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<ComicInfo>
<Series>Hajime no Ippo</Series>
<Number>3</Number>
<AgeRating>M</AgeRating>
</ComicInfo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
This is an example of a layout. All files in here have non-copyrighted data but emulate real series to ensure the Process series Works as expected.

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using API.Services; using API.Services;
using API.Services.Tasks.Metadata; using API.Services.Tasks.Metadata;
using API.SignalR; using API.SignalR;
@ -43,25 +44,26 @@ public class WordCountAnalysisTests : AbstractDbTest
public async Task ReadingTimeShouldBeNonZero() public async Task ReadingTimeShouldBeNonZero()
{ {
await ResetDb(); await ResetDb();
var series = EntityFactory.CreateSeries("Test Series"); var series = new SeriesBuilder("Test Series")
series.Format = MangaFormat.Epub; .WithFormat(MangaFormat.Epub)
var chapter = EntityFactory.CreateChapter("", false, new List<MangaFile>() .Build();
{
EntityFactory.CreateMangaFile(
Path.Join(_testDirectory, "The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub"),
MangaFormat.Epub, 0)
});
_context.Library.Add(new Library() var chapter = new ChapterBuilder("")
{ .WithFile(new MangaFileBuilder(
Name = "Test", Path.Join(_testDirectory,
Type = LibraryType.Book, "The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub"),
Series = new List<Series>() {series} MangaFormat.Epub).Build())
}); .Build();
_context.Library.Add(new LibraryBuilder("Test LIb", LibraryType.Book)
.WithSeries(series)
.Build());
series.Volumes = new List<Volume>() series.Volumes = new List<Volume>()
{ {
EntityFactory.CreateVolume("0", new List<Chapter>() {chapter}) new VolumeBuilder("0")
.WithChapter(chapter)
.Build(),
}; };
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -98,26 +100,23 @@ public class WordCountAnalysisTests : AbstractDbTest
public async Task ReadingTimeShouldIncreaseWhenNewBookAdded() public async Task ReadingTimeShouldIncreaseWhenNewBookAdded()
{ {
await ResetDb(); await ResetDb();
var series = EntityFactory.CreateSeries("Test Series"); var chapter = new ChapterBuilder("")
series.Format = MangaFormat.Epub; .WithFile(new MangaFileBuilder(
var chapter = EntityFactory.CreateChapter("", false, new List<MangaFile>() Path.Join(_testDirectory,
{ "The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub"),
EntityFactory.CreateMangaFile( MangaFormat.Epub).Build())
Path.Join(_testDirectory, "The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub"), .Build();
MangaFormat.Epub, 0) var series = new SeriesBuilder("Test Series")
}); .WithFormat(MangaFormat.Epub)
.WithVolume(new VolumeBuilder("0")
.WithChapter(chapter)
.Build())
.Build();
_context.Library.Add(new Library() _context.Library.Add(new LibraryBuilder("Test", LibraryType.Book)
{ .WithSeries(series)
Name = "Test", .Build());
Type = LibraryType.Book,
Series = new List<Series>() {series}
});
series.Volumes = new List<Volume>()
{
EntityFactory.CreateVolume("0", new List<Chapter>() {chapter})
};
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -125,18 +124,19 @@ public class WordCountAnalysisTests : AbstractDbTest
var cacheService = new CacheHelper(new FileService()); var cacheService = new CacheHelper(new FileService());
var service = new WordCountAnalyzerService(Substitute.For<ILogger<WordCountAnalyzerService>>(), _unitOfWork, var service = new WordCountAnalyzerService(Substitute.For<ILogger<WordCountAnalyzerService>>(), _unitOfWork,
Substitute.For<IEventHub>(), cacheService, _readerService); Substitute.For<IEventHub>(), cacheService, _readerService);
await service.ScanSeries(1, 1); await service.ScanSeries(1, 1);
var chapter2 = EntityFactory.CreateChapter("2", false, new List<MangaFile>() var chapter2 = new ChapterBuilder("2")
{ .WithFile(new MangaFileBuilder(
EntityFactory.CreateMangaFile( Path.Join(_testDirectory,
Path.Join(_testDirectory, "The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub"), "The Golden Harpoon; Or, Lost Among the Floes A Story of the Whaling Grounds.epub"),
MangaFormat.Epub, 0) MangaFormat.Epub).Build())
}); .Build();
series.Volumes.Add(EntityFactory.CreateVolume("1", new List<Chapter>() {chapter2}));
series.Volumes.Add(new VolumeBuilder("1")
.WithChapter(chapter2)
.Build());
series.Volumes.First().Chapters.Add(chapter2); series.Volumes.First().Chapters.Add(chapter2);
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();

View File

@ -13,6 +13,7 @@ using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Errors; using API.Errors;
using API.Extensions; using API.Extensions;
using API.Helpers.Builders;
using API.Middleware.RateLimit; using API.Middleware.RateLimit;
using API.Services; using API.Services;
using API.SignalR; using API.SignalR;
@ -126,16 +127,9 @@ public class AccountController : BaseApiController
return BadRequest(usernameValidation); return BadRequest(usernameValidation);
} }
var user = new AppUser() var user = new AppUserBuilder(registerDto.Username, registerDto.Email,
{ await _unitOfWork.SiteThemeRepository.GetDefaultTheme()).Build();
UserName = registerDto.Username,
Email = registerDto.Email,
UserPreferences = new AppUserPreferences
{
Theme = await _unitOfWork.SiteThemeRepository.GetDefaultTheme()
},
ApiKey = HashUtil.ApiKey()
};
var result = await _userManager.CreateAsync(user, registerDto.Password); var result = await _userManager.CreateAsync(user, registerDto.Password);
if (!result.Succeeded) return BadRequest(result.Errors); if (!result.Succeeded) return BadRequest(result.Errors);
@ -204,6 +198,8 @@ public class AccountController : BaseApiController
// Update LastActive on account // Update LastActive on account
user.UpdateLastActive(); user.UpdateLastActive();
// NOTE: This can likely be removed
user.UserPreferences ??= new AppUserPreferences user.UserPreferences ??= new AppUserPreferences
{ {
Theme = await _unitOfWork.SiteThemeRepository.GetDefaultTheme() Theme = await _unitOfWork.SiteThemeRepository.GetDefaultTheme()
@ -537,7 +533,7 @@ public class AccountController : BaseApiController
} }
// Create a new user // Create a new user
var user = DbFactory.AppUser(dto.Email, dto.Email, await _unitOfWork.SiteThemeRepository.GetDefaultTheme()); var user = new AppUserBuilder(dto.Email, dto.Email, await _unitOfWork.SiteThemeRepository.GetDefaultTheme()).Build();
try try
{ {

View File

@ -34,14 +34,12 @@ public class ReaderController : BaseApiController
private readonly IBookmarkService _bookmarkService; private readonly IBookmarkService _bookmarkService;
private readonly IAccountService _accountService; private readonly IAccountService _accountService;
private readonly IEventHub _eventHub; private readonly IEventHub _eventHub;
private readonly IImageService _imageService;
private readonly IDirectoryService _directoryService;
/// <inheritdoc /> /// <inheritdoc />
public ReaderController(ICacheService cacheService, public ReaderController(ICacheService cacheService,
IUnitOfWork unitOfWork, ILogger<ReaderController> logger, IUnitOfWork unitOfWork, ILogger<ReaderController> logger,
IReaderService readerService, IBookmarkService bookmarkService, IReaderService readerService, IBookmarkService bookmarkService,
IAccountService accountService, IEventHub eventHub, IImageService imageService, IDirectoryService directoryService) IAccountService accountService, IEventHub eventHub)
{ {
_cacheService = cacheService; _cacheService = cacheService;
_unitOfWork = unitOfWork; _unitOfWork = unitOfWork;
@ -50,8 +48,6 @@ public class ReaderController : BaseApiController
_bookmarkService = bookmarkService; _bookmarkService = bookmarkService;
_accountService = accountService; _accountService = accountService;
_eventHub = eventHub; _eventHub = eventHub;
_imageService = imageService;
_directoryService = directoryService;
} }
/// <summary> /// <summary>

View File

@ -229,7 +229,7 @@ public class UploadController : BaseApiController
} }
return _imageService.CreateThumbnailFromBase64(uploadFileDto.Url, return _imageService.CreateThumbnailFromBase64(uploadFileDto.Url,
filename, convertToWebP); ; filename, convertToWebP);
} }
/// <summary> /// <summary>

View File

@ -1,198 +0,0 @@
using System.Collections.Generic;
using System.IO;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Parser;
using API.Services.Tasks;
using Kavita.Common;
namespace API.Data;
/// <summary>
/// Responsible for creating Series, Volume, Chapter, MangaFiles for use in <see cref="ScannerService"/>
/// </summary>
public static class DbFactory
{
public static Library Library(string name, LibraryType type)
{
return new Library()
{
Name = name,
Type = type,
Series = new List<Series>(),
Folders = new List<FolderPath>(),
AppUsers = new List<AppUser>()
};
}
public static Series Series(string name)
{
return new Series
{
Name = name,
OriginalName = name,
LocalizedName = name,
NormalizedName = name.ToNormalized(),
NormalizedLocalizedName = name.ToNormalized(),
SortName = name,
Volumes = new List<Volume>(),
Metadata = SeriesMetadata(new List<CollectionTag>())
};
}
public static Series Series(string name, string localizedName)
{
if (string.IsNullOrEmpty(localizedName))
{
localizedName = name;
}
return new Series
{
Name = name,
OriginalName = name,
LocalizedName = localizedName,
NormalizedName = name.ToNormalized(),
NormalizedLocalizedName = localizedName.ToNormalized(),
SortName = name,
Volumes = new List<Volume>(),
Metadata = SeriesMetadata(new List<CollectionTag>())
};
}
public static Volume Volume(string volumeNumber)
{
return new Volume()
{
Name = volumeNumber,
Number = (int) Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(volumeNumber),
Chapters = new List<Chapter>()
};
}
public static Chapter Chapter(ParserInfo info)
{
var specialTreatment = info.IsSpecialInfo();
var specialTitle = specialTreatment ? info.Filename : info.Chapters;
return new Chapter()
{
Number = specialTreatment ? "0" : Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(info.Chapters) + string.Empty,
Range = specialTreatment ? info.Filename : info.Chapters,
Title = (specialTreatment && info.Format == MangaFormat.Epub)
? info.Title
: specialTitle,
Files = new List<MangaFile>(),
IsSpecial = specialTreatment,
};
}
public static SeriesMetadata SeriesMetadata(ICollection<CollectionTag> collectionTags)
{
return new SeriesMetadata()
{
CollectionTags = collectionTags,
Summary = string.Empty
};
}
public static CollectionTag CollectionTag(int id, string title, string? summary = null, bool promoted = false)
{
title = title.Trim();
return new CollectionTag()
{
Id = id,
NormalizedTitle = title.ToNormalized(),
Title = title,
Summary = summary?.Trim(),
Promoted = promoted,
SeriesMetadatas = new List<SeriesMetadata>()
};
}
public static ReadingList ReadingList(string title, string? summary = null, bool promoted = false, AgeRating rating = AgeRating.Unknown)
{
title = title.Trim();
return new ReadingList()
{
NormalizedTitle = title.ToNormalized(),
Title = title,
Summary = summary?.Trim(),
Promoted = promoted,
Items = new List<ReadingListItem>(),
AgeRating = rating
};
}
public static ReadingListItem ReadingListItem(int index, int seriesId, int volumeId, int chapterId)
{
return new ReadingListItem()
{
Order = index,
ChapterId = chapterId,
SeriesId = seriesId,
VolumeId = volumeId
};
}
public static Genre Genre(string name)
{
return new Genre()
{
Title = name.Trim().SentenceCase(),
NormalizedTitle = name.ToNormalized()
};
}
public static Tag Tag(string name)
{
return new Tag()
{
Title = name.Trim().SentenceCase(),
NormalizedTitle = name.ToNormalized()
};
}
public static Person Person(string name, PersonRole role)
{
return new Person()
{
Name = name.Trim(),
NormalizedName = name.ToNormalized(),
Role = role
};
}
public static MangaFile MangaFile(string filePath, MangaFormat format, int pages)
{
return new MangaFile()
{
FilePath = filePath,
Format = format,
Pages = pages,
LastModified = File.GetLastWriteTime(filePath),
LastModifiedUtc = File.GetLastWriteTimeUtc(filePath),
};
}
public static Device Device(string name)
{
return new Device()
{
Name = name,
};
}
public static AppUser AppUser(string username, string email, SiteTheme defaultTheme)
{
return new AppUser()
{
UserName = username,
Email = email,
ApiKey = HashUtil.ApiKey(),
UserPreferences = new AppUserPreferences
{
Theme = defaultTheme
}
};
}
}

View File

@ -9,6 +9,7 @@ namespace API.Data;
/// v0.7 introduced UTC dates and GMT+1 users would sometimes have dates stored as '0000-12-31 23:00:00'. /// v0.7 introduced UTC dates and GMT+1 users would sometimes have dates stored as '0000-12-31 23:00:00'.
/// This Migration will update those dates. /// This Migration will update those dates.
/// </summary> /// </summary>
// ReSharper disable once InconsistentNaming
public static class MigrateBrokenGMT1Dates public static class MigrateBrokenGMT1Dates
{ {
public static async Task Migrate(IUnitOfWork unitOfWork, DataContext dataContext, ILogger<Program> logger) public static async Task Migrate(IUnitOfWork unitOfWork, DataContext dataContext, ILogger<Program> logger)

View File

@ -2,7 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using API.Entities.Enums; using API.Entities.Enums;
using API.Entities.Interfaces; using API.Entities.Interfaces;
using API.Parser; using API.Services.Tasks.Scanner.Parser;
namespace API.Entities; namespace API.Entities;

View File

@ -2,7 +2,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using API.Entities; using API.Entities;
using API.Helpers; using API.Helpers;
using API.Parser; using API.Services.Tasks.Scanner.Parser;
namespace API.Extensions; namespace API.Extensions;

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using API.Entities; using API.Entities;
using API.Parser; using API.Services.Tasks.Scanner.Parser;
namespace API.Extensions; namespace API.Extensions;

View File

@ -0,0 +1,40 @@
using System.Collections.Generic;
using System.Linq;
using API.Data;
using API.Entities;
using Kavita.Common;
namespace API.Helpers.Builders;
public class AppUserBuilder : IEntityBuilder<AppUser>
{
private readonly AppUser _appUser;
public AppUser Build() => _appUser;
public AppUserBuilder(string username, string email, SiteTheme? theme = null)
{
_appUser = new AppUser()
{
UserName = username,
Email = email,
ApiKey = HashUtil.ApiKey(),
UserPreferences = new AppUserPreferences
{
Theme = theme ?? Seed.DefaultThemes.First()
},
ReadingLists = new List<ReadingList>(),
Bookmarks = new List<AppUserBookmark>(),
Libraries = new List<Library>(),
Ratings = new List<AppUserRating>(),
Progresses = new List<AppUserProgress>(),
Devices = new List<Device>(),
Id = 0
};
}
public AppUserBuilder WithLibrary(Library library)
{
_appUser.Libraries.Add(library);
return this;
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Services.Tasks.Scanner.Parser;
namespace API.Helpers.Builders; namespace API.Helpers.Builders;
@ -16,12 +17,43 @@ public class ChapterBuilder : IEntityBuilder<Chapter>
{ {
Range = string.IsNullOrEmpty(range) ? number : range, Range = string.IsNullOrEmpty(range) ? number : range,
Title = string.IsNullOrEmpty(range) ? number : range, Title = string.IsNullOrEmpty(range) ? number : range,
Number = API.Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(number) + string.Empty, Number = Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(number) + string.Empty,
Files = new List<MangaFile>(), Files = new List<MangaFile>(),
Pages = 1 Pages = 1
}; };
} }
public static ChapterBuilder FromParserInfo(ParserInfo info)
{
var specialTreatment = info.IsSpecialInfo();
var specialTitle = specialTreatment ? info.Filename : info.Chapters;
var builder = new ChapterBuilder(Services.Tasks.Scanner.Parser.Parser.DefaultChapter);
return builder.WithNumber(specialTreatment ? Services.Tasks.Scanner.Parser.Parser.DefaultChapter : Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(info.Chapters) + string.Empty)
.WithRange(specialTreatment ? info.Filename : info.Chapters)
.WithTitle((specialTreatment && info.Format == MangaFormat.Epub)
? info.Title
: specialTitle)
.WithIsSpecial(specialTreatment);
}
public ChapterBuilder WithId(int id)
{
_chapter.Id = Math.Max(id, 0);
return this;
}
private ChapterBuilder WithNumber(string number)
{
_chapter.Number = number;
return this;
}
private ChapterBuilder WithRange(string range)
{
_chapter.Range = range;
return this;
}
public ChapterBuilder WithReleaseDate(DateTime time) public ChapterBuilder WithReleaseDate(DateTime time)
{ {
_chapter.ReleaseDate = time; _chapter.ReleaseDate = time;
@ -61,4 +93,24 @@ public class ChapterBuilder : IEntityBuilder<Chapter>
_chapter.Files.Add(file); _chapter.Files.Add(file);
return this; return this;
} }
public ChapterBuilder WithFiles(IList<MangaFile> files)
{
_chapter.Files = files ?? new List<MangaFile>();
return this;
}
public ChapterBuilder WithLastModified(DateTime lastModified)
{
_chapter.LastModified = lastModified;
_chapter.LastModifiedUtc = lastModified.ToUniversalTime();
return this;
}
public ChapterBuilder WithCreated(DateTime created)
{
_chapter.Created = created;
_chapter.CreatedUtc = created.ToUniversalTime();
return this;
}
} }

View File

@ -0,0 +1,57 @@
using System.Collections.Generic;
using API.Entities;
using API.Entities.Metadata;
using API.Extensions;
namespace API.Helpers.Builders;
public class CollectionTagBuilder : IEntityBuilder<CollectionTag>
{
private readonly CollectionTag _collectionTag;
public CollectionTag Build() => _collectionTag;
public CollectionTagBuilder(string title, bool promoted = false)
{
title = title.Trim();
_collectionTag = new CollectionTag()
{
Id = 0,
NormalizedTitle = title.ToNormalized(),
Title = title,
Promoted = promoted,
Summary = string.Empty,
SeriesMetadatas = new List<SeriesMetadata>()
};
}
public CollectionTagBuilder WithId(int id)
{
_collectionTag.Id = id;
return this;
}
public CollectionTagBuilder WithSummary(string summary)
{
_collectionTag.Summary = summary;
return this;
}
public CollectionTagBuilder WithIsPromoted(bool promoted)
{
_collectionTag.Promoted = promoted;
return this;
}
public CollectionTagBuilder WithSeriesMetadata(SeriesMetadata seriesMetadata)
{
_collectionTag.SeriesMetadatas ??= new List<SeriesMetadata>();
_collectionTag.SeriesMetadatas.Add(seriesMetadata);
return this;
}
public CollectionTagBuilder WithCoverImage(string cover)
{
_collectionTag.CoverImage = cover;
return this;
}
}

View File

@ -0,0 +1,30 @@
using API.Entities;
using API.Entities.Enums.Device;
namespace API.Helpers.Builders;
public class DeviceBuilder : IEntityBuilder<Device>
{
private readonly Device _device;
public Device Build() => _device;
public DeviceBuilder(string name)
{
_device = new Device()
{
Name = name,
Platform = DevicePlatform.Custom
};
}
public DeviceBuilder WithPlatform(DevicePlatform platform)
{
_device.Platform = platform;
return this;
}
public DeviceBuilder WithEmail(string email)
{
_device.EmailAddress = email;
return this;
}
}

View File

@ -0,0 +1,19 @@
using System.IO;
using API.Entities;
namespace API.Helpers.Builders;
public class FolderPathBuilder : IEntityBuilder<FolderPath>
{
private readonly FolderPath _folderPath;
public FolderPath Build() => _folderPath;
public FolderPathBuilder(string directory)
{
_folderPath = new FolderPath()
{
Path = directory,
Id = 0
};
}
}

View File

@ -0,0 +1,30 @@
using System.Collections.Generic;
using API.Entities;
using API.Entities.Metadata;
using API.Extensions;
namespace API.Helpers.Builders;
public class GenreBuilder : IEntityBuilder<Genre>
{
private readonly Genre _genre;
public Genre Build() => _genre;
public GenreBuilder(string name)
{
_genre = new Genre()
{
Title = name.Trim().SentenceCase(),
NormalizedTitle = name.ToNormalized(),
Chapters = new List<Chapter>(),
SeriesMetadatas = new List<SeriesMetadata>()
};
}
public GenreBuilder WithSeriesMetadata(SeriesMetadata seriesMetadata)
{
_genre.SeriesMetadatas ??= new List<SeriesMetadata>();
_genre.SeriesMetadatas.Add(seriesMetadata);
return this;
}
}

View File

@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Linq;
using API.Entities;
using API.Entities.Enums;
using SQLitePCL;
namespace API.Helpers.Builders;
public class LibraryBuilder : IEntityBuilder<Library>
{
private readonly Library _library;
public Library Build() => _library;
public LibraryBuilder(string name, LibraryType type = LibraryType.Manga)
{
_library = new Library()
{
Name = name,
Type = type,
Series = new List<Series>(),
Folders = new List<FolderPath>(),
AppUsers = new List<AppUser>()
};
}
public LibraryBuilder WithFolderPath(FolderPath folderPath)
{
_library.Folders ??= new List<FolderPath>();
if (_library.Folders.All(f => f != folderPath)) _library.Folders.Add(folderPath);
return this;
}
public LibraryBuilder WithSeries(Series series)
{
_library.Series ??= new List<Series>();
_library.Series.Add(series);
return this;
}
public LibraryBuilder WithAppUser(AppUser appUser)
{
_library.AppUsers ??= new List<AppUser>();
_library.AppUsers.Add(appUser);
return this;
}
}

View File

@ -0,0 +1,61 @@
using System;
using System.IO;
using API.Entities;
using API.Entities.Enums;
namespace API.Helpers.Builders;
public class MangaFileBuilder : IEntityBuilder<MangaFile>
{
private readonly MangaFile _mangaFile;
public MangaFile Build() => _mangaFile;
public MangaFileBuilder(string filePath, MangaFormat format, int pages = 0)
{
_mangaFile = new MangaFile()
{
FilePath = filePath,
Format = format,
Pages = pages,
LastModified = File.GetLastWriteTime(filePath),
LastModifiedUtc = File.GetLastWriteTimeUtc(filePath),
};
}
public MangaFileBuilder WithFormat(MangaFormat format)
{
_mangaFile.Format = format;
return this;
}
public MangaFileBuilder WithPages(int pages)
{
_mangaFile.Pages = Math.Max(pages, 0);
return this;
}
public MangaFileBuilder WithExtension(string extension)
{
_mangaFile.Extension = extension.ToLowerInvariant();
return this;
}
public MangaFileBuilder WithBytes(long bytes)
{
_mangaFile.Bytes = Math.Max(0, bytes);
return this;
}
public MangaFileBuilder WithLastModified(DateTime dateTime)
{
_mangaFile.LastModified = dateTime;
_mangaFile.LastModifiedUtc = dateTime.ToUniversalTime();
return this;
}
public MangaFileBuilder WithId(int id)
{
_mangaFile.Id = Math.Max(id, 0);
return this;
}
}

View File

@ -23,6 +23,17 @@ public class PersonBuilder : IEntityBuilder<Person>
}; };
} }
/// <summary>
/// Only call for Unit Tests
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public PersonBuilder WithId(int id)
{
_person.Id = id;
return this;
}
public PersonBuilder WithSeriesMetadata(SeriesMetadata metadata) public PersonBuilder WithSeriesMetadata(SeriesMetadata metadata)
{ {
_person.SeriesMetadatas ??= new List<SeriesMetadata>(); _person.SeriesMetadatas ??= new List<SeriesMetadata>();

View File

@ -0,0 +1,57 @@
using System.Collections.Generic;
using API.Entities;
using API.Entities.Enums;
using API.Extensions;
namespace API.Helpers.Builders;
public class ReadingListBuilder : IEntityBuilder<ReadingList>
{
private readonly ReadingList _readingList;
public ReadingList Build() => _readingList;
public ReadingListBuilder(string title)
{
title = title.Trim();
_readingList = new ReadingList()
{
Title = title,
NormalizedTitle = title.ToNormalized(),
Summary = string.Empty,
Promoted = false,
Items = new List<ReadingListItem>(),
AgeRating = AgeRating.Unknown
};
}
public ReadingListBuilder WithSummary(string summary)
{
_readingList.Summary = summary ?? string.Empty;
return this;
}
public ReadingListBuilder WithItem(ReadingListItem item)
{
_readingList.Items ??= new List<ReadingListItem>();
_readingList.Items.Add(item);
return this;
}
public ReadingListBuilder WithRating(AgeRating rating)
{
_readingList.AgeRating = rating;
return this;
}
public ReadingListBuilder WithPromoted(bool promoted)
{
_readingList.Promoted = promoted;
return this;
}
public ReadingListBuilder WithCoverImage(string coverImage)
{
_readingList.CoverImage = coverImage;
return this;
}
}

View File

@ -0,0 +1,21 @@
using API.Entities;
namespace API.Helpers.Builders;
public class ReadingListItemBuilder : IEntityBuilder<ReadingListItem>
{
private readonly ReadingListItem _item;
public ReadingListItem Build() => _item;
public ReadingListItemBuilder(int index, int seriesId, int volumeId, int chapterId)
{
_item = new ReadingListItem()
{
Order = index,
ChapterId = chapterId,
SeriesId = seriesId,
VolumeId = volumeId
};
}
}

View File

@ -26,13 +26,22 @@ public class SeriesBuilder : IEntityBuilder<Series>
SortName = name, SortName = name,
NormalizedName = name.ToNormalized(), NormalizedName = name.ToNormalized(),
NormalizedLocalizedName = name.ToNormalized(), NormalizedLocalizedName = name.ToNormalized(),
Metadata = new SeriesMetadata(), Metadata = new SeriesMetadataBuilder().Build(),
Volumes = new List<Volume>() Volumes = new List<Volume>()
}; };
} }
/// <summary>
/// Sets the localized name. If null or empty, defaults back to the
/// </summary>
/// <param name="localizedName"></param>
/// <returns></returns>
public SeriesBuilder WithLocalizedName(string localizedName) public SeriesBuilder WithLocalizedName(string localizedName)
{ {
if (string.IsNullOrEmpty(localizedName))
{
localizedName = _series.Name;
}
_series.LocalizedName = localizedName; _series.LocalizedName = localizedName;
_series.NormalizedLocalizedName = localizedName.ToNormalized(); _series.NormalizedLocalizedName = localizedName.ToNormalized();
return this; return this;
@ -68,4 +77,16 @@ public class SeriesBuilder : IEntityBuilder<Series>
_series.Pages = pages; _series.Pages = pages;
return this; return this;
} }
public SeriesBuilder WithCoverImage(string cover)
{
_series.CoverImage = cover;
return this;
}
public SeriesBuilder WithLibraryId(int id)
{
_series.LibraryId = id;
return this;
}
} }

View File

@ -23,14 +23,26 @@ public class SeriesMetadataBuilder : IEntityBuilder<SeriesMetadata>
public SeriesMetadataBuilder WithCollectionTag(CollectionTag tag) public SeriesMetadataBuilder WithCollectionTag(CollectionTag tag)
{ {
_seriesMetadata.CollectionTags ??= new List<API.Entities.CollectionTag>(); _seriesMetadata.CollectionTags ??= new List<CollectionTag>();
_seriesMetadata.CollectionTags.Add(tag); _seriesMetadata.CollectionTags.Add(tag);
return this; return this;
} }
public SeriesMetadataBuilder WithCollectionTags(IList<CollectionTag> tags)
{
if (tags == null) return this;
_seriesMetadata.CollectionTags ??= new List<CollectionTag>();
_seriesMetadata.CollectionTags = tags;
return this;
}
public SeriesMetadataBuilder WithPublicationStatus(PublicationStatus status) public SeriesMetadataBuilder WithPublicationStatus(PublicationStatus status)
{ {
_seriesMetadata.PublicationStatus = status; _seriesMetadata.PublicationStatus = status;
return this; return this;
} }
public SeriesMetadataBuilder WithAgeRating(AgeRating rating)
{
_seriesMetadata.AgeRating = rating;
return this;
}
} }

View File

@ -0,0 +1,30 @@
using System.Collections.Generic;
using API.Entities;
using API.Entities.Metadata;
using API.Extensions;
namespace API.Helpers.Builders;
public class TagBuilder : IEntityBuilder<Tag>
{
private readonly Tag _tag;
public Tag Build() => _tag;
public TagBuilder(string name)
{
_tag = new Tag()
{
Title = name.Trim().SentenceCase(),
NormalizedTitle = name.ToNormalized(),
Chapters = new List<Chapter>(),
SeriesMetadatas = new List<SeriesMetadata>()
};
}
public TagBuilder WithSeriesMetadata(SeriesMetadata seriesMetadata)
{
_tag.SeriesMetadatas ??= new List<SeriesMetadata>();
_tag.SeriesMetadatas.Add(seriesMetadata);
return this;
}
}

View File

@ -12,7 +12,12 @@ public class VolumeBuilder : IEntityBuilder<Volume>
public VolumeBuilder(string volumeNumber) public VolumeBuilder(string volumeNumber)
{ {
_volume = DbFactory.Volume(volumeNumber); _volume = new Volume()
{
Name = volumeNumber,
Number = (int) Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(volumeNumber),
Chapters = new List<Chapter>()
};
} }
public VolumeBuilder WithName(string name) public VolumeBuilder WithName(string name)
@ -40,4 +45,16 @@ public class VolumeBuilder : IEntityBuilder<Volume>
_volume.Pages = _volume.Chapters.Sum(c => c.Pages); _volume.Pages = _volume.Chapters.Sum(c => c.Pages);
return this; return this;
} }
public VolumeBuilder WithSeriesId(int seriesId)
{
_volume.SeriesId = seriesId;
return this;
}
public VolumeBuilder WithCoverImage(string cover)
{
_volume.CoverImage = cover;
return this;
}
} }

View File

@ -5,6 +5,7 @@ using API.Data;
using API.DTOs.Metadata; using API.DTOs.Metadata;
using API.Entities; using API.Entities;
using API.Extensions; using API.Extensions;
using API.Helpers.Builders;
namespace API.Helpers; namespace API.Helpers;
@ -26,7 +27,7 @@ public static class GenreHelper
var genre = allGenres.FirstOrDefault(p => p.NormalizedTitle != null && p.NormalizedTitle.Equals(normalizedName)); var genre = allGenres.FirstOrDefault(p => p.NormalizedTitle != null && p.NormalizedTitle.Equals(normalizedName));
if (genre == null) if (genre == null)
{ {
genre = DbFactory.Genre(name); genre = new GenreBuilder(name).Build();
allGenres.Add(genre); allGenres.Add(genre);
} }
@ -99,7 +100,7 @@ public static class GenreHelper
else else
{ {
// Add new tag // Add new tag
handleAdd(DbFactory.Genre(tagTitle)); handleAdd(new GenreBuilder(tagTitle).Build());
isModified = true; isModified = true;
} }
} }

View File

@ -2,8 +2,8 @@
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Parser;
using API.Services.Tasks.Scanner; using API.Services.Tasks.Scanner;
using API.Services.Tasks.Scanner.Parser;
namespace API.Helpers; namespace API.Helpers;

View File

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using API.Data;
using API.DTOs; using API.DTOs;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
@ -25,6 +23,7 @@ public static class PersonHelper
/// <param name="action"></param> /// <param name="action"></param>
public static void UpdatePeople(ICollection<Person> allPeople, IEnumerable<string> names, PersonRole role, Action<Person> action) public static void UpdatePeople(ICollection<Person> allPeople, IEnumerable<string> names, PersonRole role, Action<Person> action)
{ {
// TODO: Validate if we need this, not used
var allPeopleTypeRole = allPeople.Where(p => p.Role == role).ToList(); var allPeopleTypeRole = allPeople.Where(p => p.Role == role).ToList();
foreach (var name in names) foreach (var name in names)
@ -34,7 +33,7 @@ public static class PersonHelper
p.NormalizedName != null && p.NormalizedName.Equals(normalizedName)); p.NormalizedName != null && p.NormalizedName.Equals(normalizedName));
if (person == null) if (person == null)
{ {
person = DbFactory.Person(name, role); person = new PersonBuilder(name, role).Build();
allPeople.Add(person); allPeople.Add(person);
} }
@ -102,7 +101,7 @@ public static class PersonHelper
public static void AddPersonIfNotExists(ICollection<Person> metadataPeople, Person person) public static void AddPersonIfNotExists(ICollection<Person> metadataPeople, Person person)
{ {
if (string.IsNullOrEmpty(person.Name)) return; if (string.IsNullOrEmpty(person.Name)) return;
var existingPerson = metadataPeople.SingleOrDefault(p => var existingPerson = metadataPeople.FirstOrDefault(p =>
p.NormalizedName == person.Name.ToNormalized() && p.Role == person.Role); p.NormalizedName == person.Name.ToNormalized() && p.Role == person.Role);
if (existingPerson == null) if (existingPerson == null)
{ {
@ -110,21 +109,16 @@ public static class PersonHelper
} }
} }
/// <summary>
/// Adds the person to the list if it's not already in there
/// </summary>
/// <param name="metadataPeople"></param>
/// <param name="person"></param>
public static void AddPersonIfNotExists(BlockingCollection<Person> metadataPeople, Person person)
{
var existingPerson = metadataPeople.SingleOrDefault(p =>
p.NormalizedName == person.Name?.ToNormalized() && p.Role == person.Role);
if (existingPerson == null)
{
metadataPeople.Add(person);
}
}
/// <summary>
/// For a given role and people dtos, update a series
/// </summary>
/// <param name="role"></param>
/// <param name="tags"></param>
/// <param name="series"></param>
/// <param name="allTags"></param>
/// <param name="handleAdd">This will call with an existing or new tag, but the method does not update the series Metadata</param>
/// <param name="onModified"></param>
public static void UpdatePeopleList(PersonRole role, ICollection<PersonDto>? tags, Series series, IReadOnlyCollection<Person> allTags, public static void UpdatePeopleList(PersonRole role, ICollection<PersonDto>? tags, Series series, IReadOnlyCollection<Person> allTags,
Action<Person> handleAdd, Action onModified) Action<Person> handleAdd, Action onModified)
{ {

View File

@ -6,6 +6,7 @@ using API.Data;
using API.DTOs.Metadata; using API.DTOs.Metadata;
using API.Entities; using API.Entities;
using API.Extensions; using API.Extensions;
using API.Helpers.Builders;
namespace API.Helpers; namespace API.Helpers;
@ -31,7 +32,7 @@ public static class TagHelper
if (genre == null) if (genre == null)
{ {
added = true; added = true;
genre = DbFactory.Tag(name); genre = new TagBuilder(name).Build();
allTags.Add(genre); allTags.Add(genre);
} }
@ -129,7 +130,7 @@ public static class TagHelper
else else
{ {
// Add new tag // Add new tag
handleAdd(DbFactory.Tag(tagTitle)); handleAdd(new TagBuilder(tagTitle).Build());
isModified = true; isModified = true;
} }
} }

View File

@ -11,7 +11,7 @@ using API.Data.Metadata;
using API.DTOs.Reader; using API.DTOs.Reader;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Parser; using API.Services.Tasks.Scanner.Parser;
using Docnet.Core; using Docnet.Core;
using Docnet.Core.Converters; using Docnet.Core.Converters;
using Docnet.Core.Models; using Docnet.Core.Models;

View File

@ -7,6 +7,7 @@ using API.Data.Repositories;
using API.DTOs.CollectionTags; using API.DTOs.CollectionTags;
using API.Entities; using API.Entities;
using API.Entities.Metadata; using API.Entities.Metadata;
using API.Helpers.Builders;
using API.SignalR; using API.SignalR;
using Kavita.Common; using Kavita.Common;
@ -163,7 +164,7 @@ public class CollectionTagService : ICollectionTagService
/// <returns></returns> /// <returns></returns>
public CollectionTag CreateTag(string title) public CollectionTag CreateTag(string title)
{ {
var tag = DbFactory.CollectionTag(0, title, string.Empty, false); var tag = new CollectionTagBuilder(title).Build();
_unitOfWork.CollectionTagRepository.Add(tag); _unitOfWork.CollectionTagRepository.Add(tag);
return tag; return tag;
} }

View File

@ -8,6 +8,7 @@ using API.DTOs.Email;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Entities.Enums.Device; using API.Entities.Enums.Device;
using API.Helpers.Builders;
using Kavita.Common; using Kavita.Common;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -42,9 +43,10 @@ public class DeviceService : IDeviceService
var existingDevice = userWithDevices.Devices.SingleOrDefault(d => d.Name!.Equals(dto.Name)); var existingDevice = userWithDevices.Devices.SingleOrDefault(d => d.Name!.Equals(dto.Name));
if (existingDevice != null) throw new KavitaException("A device with this name already exists"); if (existingDevice != null) throw new KavitaException("A device with this name already exists");
existingDevice = DbFactory.Device(dto.Name); existingDevice = new DeviceBuilder(dto.Name)
existingDevice.Platform = dto.Platform; .WithPlatform(dto.Platform)
existingDevice.EmailAddress = dto.EmailAddress; .WithEmail(dto.EmailAddress)
.Build();
userWithDevices.Devices.Add(existingDevice); userWithDevices.Devices.Add(existingDevice);

View File

@ -1,7 +1,6 @@
using System; using System;
using API.Data.Metadata; using API.Data.Metadata;
using API.Entities.Enums; using API.Entities.Enums;
using API.Parser;
using API.Services.Tasks.Scanner.Parser; using API.Services.Tasks.Scanner.Parser;
namespace API.Services; namespace API.Services;

View File

@ -12,6 +12,7 @@ using API.DTOs.ReadingLists.CBL;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using API.SignalR; using API.SignalR;
using Kavita.Common; using Kavita.Common;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -118,7 +119,7 @@ public class ReadingListService : IReadingListService
throw new KavitaException("A list of this name already exists"); throw new KavitaException("A list of this name already exists");
} }
var readingList = DbFactory.ReadingList(title, string.Empty, false); var readingList = new ReadingListBuilder(title).Build();
userWithReadingList.ReadingLists.Add(readingList); userWithReadingList.ReadingLists.Add(readingList);
if (!_unitOfWork.HasChanges()) throw new KavitaException("There was a problem creating list"); if (!_unitOfWork.HasChanges()) throw new KavitaException("There was a problem creating list");
@ -410,7 +411,7 @@ public class ReadingListService : IReadingListService
var index = readingList.Items.Count == 0 ? 0 : lastOrder + 1; var index = readingList.Items.Count == 0 ? 0 : lastOrder + 1;
foreach (var chapter in chaptersForSeries.Where(chapter => !existingChapterExists.Contains(chapter.Id))) foreach (var chapter in chaptersForSeries.Where(chapter => !existingChapterExists.Contains(chapter.Id)))
{ {
readingList.Items.Add(DbFactory.ReadingListItem(index, seriesId, chapter.VolumeId, chapter.Id)); readingList.Items.Add(new ReadingListItemBuilder(index, seriesId, chapter.VolumeId, chapter.Id).Build());
index += 1; index += 1;
} }
@ -509,7 +510,7 @@ public class ReadingListService : IReadingListService
var allReadingLists = (user.ReadingLists).ToDictionary(s => s.NormalizedTitle); var allReadingLists = (user.ReadingLists).ToDictionary(s => s.NormalizedTitle);
if (!allReadingLists.TryGetValue(readingListNameNormalized, out var readingList)) if (!allReadingLists.TryGetValue(readingListNameNormalized, out var readingList))
{ {
readingList = DbFactory.ReadingList(cblReading.Name, cblReading.Summary, false); readingList = new ReadingListBuilder(cblReading.Name).WithSummary(cblReading.Summary).Build();
user.ReadingLists.Add(readingList); user.ReadingLists.Add(readingList);
} }
else else
@ -645,8 +646,8 @@ public class ReadingListService : IReadingListService
item.SeriesId == seriesId && item.ChapterId == chapterId); item.SeriesId == seriesId && item.ChapterId == chapterId);
if (readingListItem != null) return; if (readingListItem != null) return;
readingListItem = DbFactory.ReadingListItem(readingList.Items.Count, seriesId, readingListItem = new ReadingListItemBuilder(readingList.Items.Count, seriesId,
volumeId, chapterId); volumeId, chapterId).Build();
readingList.Items.Add(readingListItem); readingList.Items.Add(readingListItem);
} }

View File

@ -13,6 +13,7 @@ using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Entities.Metadata; using API.Entities.Metadata;
using API.Helpers; using API.Helpers;
using API.Helpers.Builders;
using API.SignalR; using API.SignalR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -69,8 +70,14 @@ public class SeriesService : ISeriesService
var allPeople = (await _unitOfWork.PersonRepository.GetAllPeople()).ToList(); var allPeople = (await _unitOfWork.PersonRepository.GetAllPeople()).ToList();
var allTags = (await _unitOfWork.TagRepository.GetAllTagsAsync()).ToList(); var allTags = (await _unitOfWork.TagRepository.GetAllTagsAsync()).ToList();
series.Metadata ??= DbFactory.SeriesMetadata((updateSeriesMetadataDto.CollectionTags ?? new List<CollectionTagDto>()) series.Metadata ??= new SeriesMetadataBuilder()
.Select(dto => DbFactory.CollectionTag(dto.Id, dto.Title, dto.Summary, dto.Promoted)).ToList()); .WithCollectionTags(updateSeriesMetadataDto.CollectionTags.Select(dto =>
new CollectionTagBuilder(dto.Title)
.WithId(dto.Id)
.WithSummary(dto.Summary)
.WithIsPromoted(dto.Promoted)
.Build()).ToList())
.Build();
if (series.Metadata.AgeRating != updateSeriesMetadataDto.SeriesMetadata.AgeRating) if (series.Metadata.AgeRating != updateSeriesMetadataDto.SeriesMetadata.AgeRating)
{ {
@ -244,7 +251,11 @@ public class SeriesService : ISeriesService
else else
{ {
// Add new tag // Add new tag
handleAdd(DbFactory.CollectionTag(tag.Id, tag.Title, tag.Summary, tag.Promoted)); handleAdd(new CollectionTagBuilder(tag.Title)
.WithId(tag.Id)
.WithSummary(tag.Summary)
.WithIsPromoted(tag.Promoted)
.Build());
} }
} }
} }

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Parser; using API.Services.Tasks.Scanner.Parser;
using API.SignalR; using API.SignalR;
using Kavita.Common.Helpers; using Kavita.Common.Helpers;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@ -1,7 +1,6 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using API.Entities.Enums; using API.Entities.Enums;
using API.Parser;
namespace API.Services.Tasks.Scanner.Parser; namespace API.Services.Tasks.Scanner.Parser;
@ -34,8 +33,9 @@ public class DefaultParser : IDefaultParser
public ParserInfo? Parse(string filePath, string rootPath, LibraryType type = LibraryType.Manga) public ParserInfo? Parse(string filePath, string rootPath, LibraryType type = LibraryType.Manga)
{ {
var fileName = _directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath); var fileName = _directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath);
// TODO: Potential Bug: This will return null, but on Image libraries, if all images, we would want to include this. // TODO: Potential Bug: This will return null, but on Image libraries, if all images, we would want to include this. (we can probably remove this and have users use kavitaignore)
if (Parser.IsCoverImage(_directoryService.FileSystem.Path.GetFileName(filePath))) return null; if (Parser.IsCoverImage(_directoryService.FileSystem.Path.GetFileName(filePath))) return null;
ParserInfo ret; ParserInfo ret;
if (Parser.IsEpub(filePath)) if (Parser.IsEpub(filePath))

View File

@ -1,8 +1,7 @@
using API.Data.Metadata; using API.Data.Metadata;
using API.Entities.Enums; using API.Entities.Enums;
using API.Services.Tasks.Scanner.Parser;
namespace API.Parser; namespace API.Services.Tasks.Scanner.Parser;
/// <summary> /// <summary>
/// This represents all parsed information from a single file /// This represents all parsed information from a single file

View File

@ -11,8 +11,9 @@ using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Helpers; using API.Helpers;
using API.Parser; using API.Helpers.Builders;
using API.Services.Tasks.Metadata; using API.Services.Tasks.Metadata;
using API.Services.Tasks.Scanner.Parser;
using API.SignalR; using API.SignalR;
using Hangfire; using Hangfire;
using Kavita.Common; using Kavita.Common;
@ -29,6 +30,13 @@ public interface IProcessSeries
Task Prime(); Task Prime();
Task ProcessSeriesAsync(IList<ParserInfo> parsedInfos, Library library, bool forceUpdate = false); Task ProcessSeriesAsync(IList<ParserInfo> parsedInfos, Library library, bool forceUpdate = false);
void EnqueuePostSeriesProcessTasks(int libraryId, int seriesId, bool forceUpdate = false); void EnqueuePostSeriesProcessTasks(int libraryId, int seriesId, bool forceUpdate = false);
// These exists only for Unit testing
void UpdateSeriesMetadata(Series series, Library library);
void UpdateVolumes(Series series, IList<ParserInfo> parsedInfos, bool forceUpdate = false);
void UpdateChapters(Series series, Volume volume, IList<ParserInfo> parsedInfos, bool forceUpdate = false);
void AddOrUpdateFileForChapter(Chapter chapter, ParserInfo info, bool forceUpdate = false);
void UpdateChapterFromComicInfo(Chapter chapter, ComicInfo? info);
} }
/// <summary> /// <summary>
@ -51,9 +59,9 @@ public class ProcessSeries : IProcessSeries
private IList<Person> _people; private IList<Person> _people;
private Dictionary<string, Tag> _tags; private Dictionary<string, Tag> _tags;
private Dictionary<string, CollectionTag> _collectionTags; private Dictionary<string, CollectionTag> _collectionTags;
private readonly object _peopleLock; private readonly object _peopleLock = new object();
private readonly object _genreLock; private readonly object _genreLock = new object();
private readonly object _tagLock; private readonly object _tagLock = new object();
public ProcessSeries(IUnitOfWork unitOfWork, ILogger<ProcessSeries> logger, IEventHub eventHub, public ProcessSeries(IUnitOfWork unitOfWork, ILogger<ProcessSeries> logger, IEventHub eventHub,
IDirectoryService directoryService, ICacheHelper cacheHelper, IReadingItemService readingItemService, IDirectoryService directoryService, ICacheHelper cacheHelper, IReadingItemService readingItemService,
@ -71,6 +79,7 @@ public class ProcessSeries : IProcessSeries
_wordCountAnalyzerService = wordCountAnalyzerService; _wordCountAnalyzerService = wordCountAnalyzerService;
_collectionTagService = collectionTagService; _collectionTagService = collectionTagService;
_genres = new Dictionary<string, Genre>(); _genres = new Dictionary<string, Genre>();
_people = new List<Person>(); _people = new List<Person>();
_tags = new Dictionary<string, Tag>(); _tags = new Dictionary<string, Tag>();
@ -122,7 +131,9 @@ public class ProcessSeries : IProcessSeries
if (series == null) if (series == null)
{ {
seriesAdded = true; seriesAdded = true;
series = DbFactory.Series(firstInfo.Series, firstInfo.LocalizedSeries); series = new SeriesBuilder(firstInfo.Series)
.WithLocalizedName(firstInfo.LocalizedSeries)
.Build();
_unitOfWork.SeriesRepository.Add(series); _unitOfWork.SeriesRepository.Add(series);
} }
@ -217,7 +228,7 @@ public class ProcessSeries : IProcessSeries
//if (!library.ManageReadingLists) return; //if (!library.ManageReadingLists) return;
_logger.LogInformation("Generating Reading Lists for {SeriesName}", series.Name); _logger.LogInformation("Generating Reading Lists for {SeriesName}", series.Name);
series.Metadata ??= DbFactory.SeriesMetadata(new List<CollectionTag>()); series.Metadata ??= new SeriesMetadataBuilder().Build();
foreach (var chapter in series.Volumes.SelectMany(v => v.Chapters)) foreach (var chapter in series.Volumes.SelectMany(v => v.Chapters))
{ {
if (!string.IsNullOrEmpty(chapter.StoryArc)) if (!string.IsNullOrEmpty(chapter.StoryArc))
@ -261,9 +272,9 @@ public class ProcessSeries : IProcessSeries
BackgroundJob.Enqueue(() => _wordCountAnalyzerService.ScanSeries(libraryId, seriesId, forceUpdate)); BackgroundJob.Enqueue(() => _wordCountAnalyzerService.ScanSeries(libraryId, seriesId, forceUpdate));
} }
private void UpdateSeriesMetadata(Series series, Library library) public void UpdateSeriesMetadata(Series series, Library library)
{ {
series.Metadata ??= DbFactory.SeriesMetadata(new List<CollectionTag>()); series.Metadata ??= new SeriesMetadataBuilder().Build();
var isBook = library.Type == LibraryType.Book; var isBook = library.Type == LibraryType.Book;
var firstChapter = SeriesService.GetFirstChapterForMetadata(series, isBook); var firstChapter = SeriesService.GetFirstChapterForMetadata(series, isBook);
@ -333,7 +344,19 @@ public class ProcessSeries : IProcessSeries
} }
} }
lock (_genreLock)
{
var genres = chapters.SelectMany(c => c.Genres).ToList();
GenreHelper.KeepOnlySameGenreBetweenLists(series.Metadata.Genres.ToList(), genres, genre =>
{
if (series.Metadata.GenresLocked) return; // NOTE: Doesn't it make sense to do the locked skip outside this loop?
series.Metadata.Genres.Remove(genre);
});
}
// Handle People // Handle People
lock (_peopleLock)
{
foreach (var chapter in chapters) foreach (var chapter in chapters)
{ {
if (!series.Metadata.WriterLocked) if (!series.Metadata.WriterLocked)
@ -432,14 +455,6 @@ public class ProcessSeries : IProcessSeries
} }
} }
} }
var genres = chapters.SelectMany(c => c.Genres).ToList();
GenreHelper.KeepOnlySameGenreBetweenLists(series.Metadata.Genres.ToList(), genres, genre =>
{
if (series.Metadata.GenresLocked) return; // NOTE: Doesn't it make sense to do the locked skip outside this loop?
series.Metadata.Genres.Remove(genre);
});
// NOTE: The issue here is that people is just from chapter, but series metadata might already have some people on it // NOTE: The issue here is that people is just from chapter, but series metadata might already have some people on it
// I might be able to filter out people that are in locked fields? // I might be able to filter out people that are in locked fields?
var people = chapters.SelectMany(c => c.People).ToList(); var people = chapters.SelectMany(c => c.People).ToList();
@ -484,8 +499,9 @@ public class ProcessSeries : IProcessSeries
} }
}); });
} }
}
private void UpdateVolumes(Series series, IList<ParserInfo> parsedInfos, bool forceUpdate = false) public void UpdateVolumes(Series series, IList<ParserInfo> parsedInfos, bool forceUpdate = false)
{ {
var startingVolumeCount = series.Volumes.Count; var startingVolumeCount = series.Volumes.Count;
// Add new volumes and update chapters per volume // Add new volumes and update chapters per volume
@ -493,7 +509,7 @@ public class ProcessSeries : IProcessSeries
_logger.LogDebug("[ScannerService] Updating {DistinctVolumes} volumes on {SeriesName}", distinctVolumes.Count, series.Name); _logger.LogDebug("[ScannerService] Updating {DistinctVolumes} volumes on {SeriesName}", distinctVolumes.Count, series.Name);
foreach (var volumeNumber in distinctVolumes) foreach (var volumeNumber in distinctVolumes)
{ {
_logger.LogDebug("[ScannerService] Looking up volume for {VolumeNumber}", volumeNumber); _logger.LogTrace("[ScannerService] Looking up volume for {VolumeNumber}", volumeNumber);
Volume? volume; Volume? volume;
try try
{ {
@ -511,8 +527,9 @@ public class ProcessSeries : IProcessSeries
} }
if (volume == null) if (volume == null)
{ {
volume = DbFactory.Volume(volumeNumber); volume = new VolumeBuilder(volumeNumber)
volume.SeriesId = series.Id; .WithSeriesId(series.Id)
.Build();
series.Volumes.Add(volume); series.Volumes.Add(volume);
} }
@ -568,7 +585,7 @@ public class ProcessSeries : IProcessSeries
series.Name, startingVolumeCount, series.Volumes.Count); series.Name, startingVolumeCount, series.Volumes.Count);
} }
private void UpdateChapters(Series series, Volume volume, IList<ParserInfo> parsedInfos, bool forceUpdate = false) public void UpdateChapters(Series series, Volume volume, IList<ParserInfo> parsedInfos, bool forceUpdate = false)
{ {
// Add new chapters // Add new chapters
foreach (var info in parsedInfos) foreach (var info in parsedInfos)
@ -590,7 +607,7 @@ public class ProcessSeries : IProcessSeries
{ {
_logger.LogDebug( _logger.LogDebug(
"[ScannerService] Adding new chapter, {Series} - Vol {Volume} Ch {Chapter}", info.Series, info.Volumes, info.Chapters); "[ScannerService] Adding new chapter, {Series} - Vol {Volume} Ch {Chapter}", info.Series, info.Volumes, info.Chapters);
chapter = DbFactory.Chapter(info); chapter = ChapterBuilder.FromParserInfo(info).Build();
volume.Chapters.Add(chapter); volume.Chapters.Add(chapter);
series.UpdateLastChapterAdded(); series.UpdateLastChapterAdded();
} }
@ -628,7 +645,7 @@ public class ProcessSeries : IProcessSeries
} }
} }
private void AddOrUpdateFileForChapter(Chapter chapter, ParserInfo info, bool forceUpdate = false) public void AddOrUpdateFileForChapter(Chapter chapter, ParserInfo info, bool forceUpdate = false)
{ {
chapter.Files ??= new List<MangaFile>(); chapter.Files ??= new List<MangaFile>();
var existingFile = chapter.Files.SingleOrDefault(f => f.FilePath == info.FullFilePath); var existingFile = chapter.Files.SingleOrDefault(f => f.FilePath == info.FullFilePath);
@ -644,15 +661,16 @@ public class ProcessSeries : IProcessSeries
} }
else else
{ {
var file = DbFactory.MangaFile(info.FullFilePath, info.Format, _readingItemService.GetNumberOfPages(info.FullFilePath, info.Format));
if (file == null) return; var file = new MangaFileBuilder(info.FullFilePath, info.Format, _readingItemService.GetNumberOfPages(info.FullFilePath, info.Format))
file.Extension = fileInfo.Extension.ToLowerInvariant(); .WithExtension(fileInfo.Extension)
file.Bytes = fileInfo.Length; .WithBytes(fileInfo.Length)
.Build();
chapter.Files.Add(file); chapter.Files.Add(file);
} }
} }
private void UpdateChapterFromComicInfo(Chapter chapter, ComicInfo? info) public void UpdateChapterFromComicInfo(Chapter chapter, ComicInfo? info)
{ {
var firstFile = chapter.Files.MinBy(x => x.Chapter); var firstFile = chapter.Files.MinBy(x => x.Chapter);
if (firstFile == null || if (firstFile == null ||
@ -665,7 +683,7 @@ public class ProcessSeries : IProcessSeries
} }
if (comicInfo == null) return; if (comicInfo == null) return;
_logger.LogDebug("[ScannerService] Read ComicInfo for {File}", firstFile.FilePath); _logger.LogTrace("[ScannerService] Read ComicInfo for {File}", firstFile.FilePath);
chapter.AgeRating = ComicInfo.ConvertAgeRatingToEnum(comicInfo.AgeRating); chapter.AgeRating = ComicInfo.ConvertAgeRatingToEnum(comicInfo.AgeRating);
@ -749,70 +767,59 @@ public class ProcessSeries : IProcessSeries
var people = GetTagValues(comicInfo.Colorist); var people = GetTagValues(comicInfo.Colorist);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Colorist); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Colorist);
UpdatePeople(people, PersonRole.Colorist, UpdatePeople(people, PersonRole.Colorist, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.Characters); people = GetTagValues(comicInfo.Characters);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Character); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Character);
UpdatePeople(people, PersonRole.Character, UpdatePeople(people, PersonRole.Character, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.Translator); people = GetTagValues(comicInfo.Translator);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Translator); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Translator);
UpdatePeople(people, PersonRole.Translator, UpdatePeople(people, PersonRole.Translator, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.Writer); people = GetTagValues(comicInfo.Writer);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Writer); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Writer);
UpdatePeople(people, PersonRole.Writer, UpdatePeople(people, PersonRole.Writer, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.Editor); people = GetTagValues(comicInfo.Editor);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Editor); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Editor);
UpdatePeople(people, PersonRole.Editor, UpdatePeople(people, PersonRole.Editor, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.Inker); people = GetTagValues(comicInfo.Inker);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Inker); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Inker);
UpdatePeople(people, PersonRole.Inker, UpdatePeople(people, PersonRole.Inker, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.Letterer); people = GetTagValues(comicInfo.Letterer);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Letterer); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Letterer);
UpdatePeople(people, PersonRole.Letterer, UpdatePeople(people, PersonRole.Letterer, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.Penciller); people = GetTagValues(comicInfo.Penciller);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Penciller); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Penciller);
UpdatePeople(people, PersonRole.Penciller, UpdatePeople(people, PersonRole.Penciller, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.CoverArtist); people = GetTagValues(comicInfo.CoverArtist);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.CoverArtist); PersonHelper.RemovePeople(chapter.People, people, PersonRole.CoverArtist);
UpdatePeople(people, PersonRole.CoverArtist, UpdatePeople(people, PersonRole.CoverArtist, AddPerson);
AddPerson);
people = GetTagValues(comicInfo.Publisher); people = GetTagValues(comicInfo.Publisher);
PersonHelper.RemovePeople(chapter.People, people, PersonRole.Publisher); PersonHelper.RemovePeople(chapter.People, people, PersonRole.Publisher);
UpdatePeople(people, PersonRole.Publisher, UpdatePeople(people, PersonRole.Publisher, AddPerson);
AddPerson);
var genres = GetTagValues(comicInfo.Genre); var genres = GetTagValues(comicInfo.Genre);
GenreHelper.KeepOnlySameGenreBetweenLists(chapter.Genres, GenreHelper.KeepOnlySameGenreBetweenLists(chapter.Genres,
genres.Select(DbFactory.Genre).ToList()); genres.Select(g => new GenreBuilder(g).Build()).ToList());
UpdateGenre(genres, AddGenre); UpdateGenre(genres, AddGenre);
var tags = GetTagValues(comicInfo.Tags); var tags = GetTagValues(comicInfo.Tags);
TagHelper.KeepOnlySameTagBetweenLists(chapter.Tags, tags.Select(DbFactory.Tag).ToList()); TagHelper.KeepOnlySameTagBetweenLists(chapter.Tags, tags.Select(t => new TagBuilder(t).Build()).ToList());
UpdateTag(tags, AddTag); UpdateTag(tags, AddTag);
} }
private static IList<string> GetTagValues(string comicInfoTagSeparatedByComma) private static IList<string> GetTagValues(string comicInfoTagSeparatedByComma)
{ {
// TODO: Move this to an extension and test it
if (!string.IsNullOrEmpty(comicInfoTagSeparatedByComma)) if (!string.IsNullOrEmpty(comicInfoTagSeparatedByComma))
{ {
return comicInfoTagSeparatedByComma.Split(",").Select(s => s.Trim()).DistinctBy(Parser.Parser.Normalize).ToList(); return comicInfoTagSeparatedByComma.Split(",").Select(s => s.Trim()).DistinctBy(Parser.Parser.Normalize).ToList();
@ -830,6 +837,8 @@ public class ProcessSeries : IProcessSeries
/// <param name="role"></param> /// <param name="role"></param>
/// <param name="action"></param> /// <param name="action"></param>
private void UpdatePeople(IEnumerable<string> names, PersonRole role, Action<Person> action) private void UpdatePeople(IEnumerable<string> names, PersonRole role, Action<Person> action)
{
lock (_peopleLock)
{ {
var allPeopleTypeRole = _people.Where(p => p.Role == role).ToList(); var allPeopleTypeRole = _people.Where(p => p.Role == role).ToList();
@ -840,16 +849,14 @@ public class ProcessSeries : IProcessSeries
p.NormalizedName != null && p.NormalizedName.Equals(normalizedName)); p.NormalizedName != null && p.NormalizedName.Equals(normalizedName));
if (person == null) if (person == null)
{ {
person = DbFactory.Person(name, role); person = new PersonBuilder(name, role).Build();
lock (_peopleLock)
{
_people.Add(person); _people.Add(person);
} }
}
action(person); action(person);
} }
} }
}
/// <summary> /// <summary>
/// ///
@ -867,7 +874,7 @@ public class ProcessSeries : IProcessSeries
var newTag = genre == null; var newTag = genre == null;
if (newTag) if (newTag)
{ {
genre = DbFactory.Genre(name); genre = new GenreBuilder(name).Build();
lock (_genreLock) lock (_genreLock)
{ {
_genres.Add(normalizedName, genre); _genres.Add(normalizedName, genre);
@ -896,7 +903,7 @@ public class ProcessSeries : IProcessSeries
var added = tag == null; var added = tag == null;
if (tag == null) if (tag == null)
{ {
tag = DbFactory.Tag(name); tag = new TagBuilder(name).Build();
lock (_tagLock) lock (_tagLock)
{ {
_tags.Add(normalizedName, tag); _tags.Add(normalizedName, tag);

View File

@ -11,9 +11,9 @@ using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Helpers; using API.Helpers;
using API.Parser;
using API.Services.Tasks.Metadata; using API.Services.Tasks.Metadata;
using API.Services.Tasks.Scanner; using API.Services.Tasks.Scanner;
using API.Services.Tasks.Scanner.Parser;
using API.SignalR; using API.SignalR;
using Hangfire; using Hangfire;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@ -28,6 +28,7 @@ public class TokenService : ITokenService
{ {
private readonly UserManager<AppUser> _userManager; private readonly UserManager<AppUser> _userManager;
private readonly SymmetricSecurityKey _key; private readonly SymmetricSecurityKey _key;
private const string RefreshTokenName = "RefreshToken";
public TokenService(IConfiguration config, UserManager<AppUser> userManager) public TokenService(IConfiguration config, UserManager<AppUser> userManager)
{ {
@ -65,22 +66,24 @@ public class TokenService : ITokenService
public async Task<string> CreateRefreshToken(AppUser user) public async Task<string> CreateRefreshToken(AppUser user)
{ {
await _userManager.RemoveAuthenticationTokenAsync(user, TokenOptions.DefaultProvider, "RefreshToken"); await _userManager.RemoveAuthenticationTokenAsync(user, TokenOptions.DefaultProvider, RefreshTokenName);
var refreshToken = await _userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, "RefreshToken"); var refreshToken = await _userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, RefreshTokenName);
await _userManager.SetAuthenticationTokenAsync(user, TokenOptions.DefaultProvider, "RefreshToken", refreshToken); await _userManager.SetAuthenticationTokenAsync(user, TokenOptions.DefaultProvider, RefreshTokenName, refreshToken);
return refreshToken; return refreshToken;
} }
public async Task<TokenRequestDto?> ValidateRefreshToken(TokenRequestDto request) public async Task<TokenRequestDto?> ValidateRefreshToken(TokenRequestDto request)
{
try
{ {
var tokenHandler = new JwtSecurityTokenHandler(); var tokenHandler = new JwtSecurityTokenHandler();
var tokenContent = tokenHandler.ReadJwtToken(request.Token); var tokenContent = tokenHandler.ReadJwtToken(request.Token);
var username = tokenContent.Claims.FirstOrDefault(q => q.Type == JwtRegisteredClaimNames.NameId)?.Value; var username = tokenContent.Claims.FirstOrDefault(q => q.Type == JwtRegisteredClaimNames.NameId)?.Value;
if (string.IsNullOrEmpty(username)) return null; if (string.IsNullOrEmpty(username)) return null;
var user = await _userManager.FindByNameAsync(username); var user = await _userManager.FindByIdAsync(username);
if (user == null) return null; // This forces a logout if (user == null) return null; // This forces a logout
await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, "RefreshToken", request.RefreshToken); var validated = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, RefreshTokenName, request.RefreshToken);
if (!validated) return null;
await _userManager.UpdateSecurityStampAsync(user); await _userManager.UpdateSecurityStampAsync(user);
return new TokenRequestDto() return new TokenRequestDto()
@ -88,5 +91,15 @@ public class TokenService : ITokenService
Token = await CreateToken(user), Token = await CreateToken(user),
RefreshToken = await CreateRefreshToken(user) RefreshToken = await CreateRefreshToken(user)
}; };
} catch (SecurityTokenExpiredException)
{
// Handle expired token
return null;
}
catch (Exception)
{
// Handle other exceptions
return null;
}
} }
} }

View File

@ -185,13 +185,6 @@ public class Startup
{ {
options.AddPolicy("Authentication", httpContext => options.AddPolicy("Authentication", httpContext =>
new AuthenticationRateLimiterPolicy().GetPartition(httpContext)); new AuthenticationRateLimiterPolicy().GetPartition(httpContext));
// RateLimitPartition.GetFixedWindowLimiter(httpContext.Connection.RemoteIpAddress?.ToString(),
// partition => new FixedWindowRateLimiterOptions
// {
// AutoReplenishment = true,
// PermitLimit = 1,
// Window = TimeSpan.FromMinutes(1),
// }));
}); });
services.AddHangfire(configuration => configuration services.AddHangfire(configuration => configuration

View File

@ -285,9 +285,9 @@ export class AccountService implements OnDestroy {
} }
const jwtToken = JSON.parse(atob(this.currentUser.token.split('.')[1])); const jwtToken = JSON.parse(atob(this.currentUser.token.split('.')[1]));
// set a timeout to refresh the token a minute before it expires // set a timeout to refresh the token 10 mins before it expires
const expires = new Date(jwtToken.exp * 1000); const expires = new Date(jwtToken.exp * 1000);
const timeout = expires.getTime() - Date.now() - (60 * 1000); const timeout = expires.getTime() - Date.now() - (60 * 10000);
this.refreshTokenTimeout = setTimeout(() => this.refreshToken().subscribe(() => {}), timeout); this.refreshTokenTimeout = setTimeout(() => this.refreshToken().subscribe(() => {}), timeout);
} }

View File

@ -23,7 +23,7 @@
<div class="col-md-6 col-sm-12"> <div class="col-md-6 col-sm-12">
<div class="mb-3" style="width:100%"> <div class="mb-3" style="width:100%">
<label for="email" class="form-label">Email</label> <label for="email" class="form-label">Email</label>
<input class="form-control" type="email" id="email" formControlName="email"> <input class="form-control" inputmode="email" type="email" id="email" formControlName="email">
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="userForm.dirty || userForm.touched" [class.is-invalid]="userForm.get('email')?.invalid && userForm.get('email')?.touched"> <div id="inviteForm-validations" class="invalid-feedback" *ngIf="userForm.dirty || userForm.touched" [class.is-invalid]="userForm.get('email')?.invalid && userForm.get('email')?.touched">
<div *ngIf="userForm.get('email')?.errors?.required"> <div *ngIf="userForm.get('email')?.errors?.required">
This field is required This field is required

View File

@ -13,7 +13,7 @@
<div class="row g-0"> <div class="row g-0">
<div class="mb-3" style="width:100%"> <div class="mb-3" style="width:100%">
<label for="email" class="form-label">Email</label> <label for="email" class="form-label">Email</label>
<input class="form-control" type="email" id="email" formControlName="email" required [class.is-invalid]="inviteForm.get('email')?.invalid && inviteForm.get('email')?.touched"> <input class="form-control" type="email" inputmode="email" id="email" formControlName="email" required [class.is-invalid]="inviteForm.get('email')?.invalid && inviteForm.get('email')?.touched">
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="inviteForm.dirty || inviteForm.touched"> <div id="inviteForm-validations" class="invalid-feedback" *ngIf="inviteForm.dirty || inviteForm.touched">
<div *ngIf="email?.errors?.required"> <div *ngIf="email?.errors?.required">
This field is required This field is required

View File

@ -13,7 +13,7 @@
<ng-template #emailServiceTooltip>Use fully qualified URL of the email service. Do not include ending slash.</ng-template> <ng-template #emailServiceTooltip>Use fully qualified URL of the email service. Do not include ending slash.</ng-template>
<span class="visually-hidden" id="settings-emailservice-help"><ng-container [ngTemplateOutlet]="emailServiceTooltip"></ng-container></span> <span class="visually-hidden" id="settings-emailservice-help"><ng-container [ngTemplateOutlet]="emailServiceTooltip"></ng-container></span>
<div class="input-group"> <div class="input-group">
<input id="settings-emailservice" aria-describedby="settings-emailservice-help" class="form-control" formControlName="emailServiceUrl" type="text" aria-describedby="change-bookmarks-dir"> <input id="settings-emailservice" aria-describedby="settings-emailservice-help" class="form-control" formControlName="emailServiceUrl" type="url" autocapitalize="off" inputmode="url" aria-describedby="change-bookmarks-dir">
<button class="btn btn-outline-secondary" (click)="resetEmailServiceUrl()"> <button class="btn btn-outline-secondary" (click)="resetEmailServiceUrl()">
Reset Reset
</button> </button>

View File

@ -35,8 +35,8 @@
<div class="mb-3"> <div class="mb-3">
<label for="settings-baseurl" class="form-label">Base Url</label>&nbsp;<i class="fa fa-info-circle" placement="right" [ngbTooltip]="baseUrlTooltip" role="button" tabindex="0"></i> <label for="settings-baseurl" class="form-label">Base Url</label>&nbsp;<i class="fa fa-info-circle" placement="right" [ngbTooltip]="baseUrlTooltip" role="button" tabindex="0"></i>
<ng-template #baseUrlTooltip>Use this if you want to host Kavita on a base url ie) yourdomain.com/kavita</ng-template> <ng-template #baseUrlTooltip>Use this if you want to host Kavita on a base url ie) yourdomain.com/kavita. Not supported on Docker using non-root user.</ng-template>
<span class="visually-hidden" id="settings-cachedir-help">Use this if you want to host Kavita on a base url ie) yourdomain.com/kavita</span> <span class="visually-hidden" id="settings-cachedir-help">Use this if you want to host Kavita on a base url ie) yourdomain.com/kavita. Not supported on Docker using non-root user.</span>
<input id="settings-baseurl" aria-describedby="settings-baseurl-help" class="form-control" formControlName="baseUrl" type="text" <input id="settings-baseurl" aria-describedby="settings-baseurl-help" class="form-control" formControlName="baseUrl" type="text"
[class.is-invalid]="settingsForm.get('baseUrl')?.invalid && settingsForm.get('baseUrl')?.touched"> [class.is-invalid]="settingsForm.get('baseUrl')?.invalid && settingsForm.get('baseUrl')?.touched">
<div id="baseurl-validations" class="invalid-feedback" *ngIf="settingsForm.dirty || settingsForm.touched"> <div id="baseurl-validations" class="invalid-feedback" *ngIf="settingsForm.dirty || settingsForm.touched">
@ -77,7 +77,7 @@
<ng-template #backupTasksTooltip>The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template> <ng-template #backupTasksTooltip>The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template>
<span class="visually-hidden" id="backup-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span> <span class="visually-hidden" id="backup-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
<input id="backup-tasks" aria-describedby="backup-tasks-help" class="form-control" formControlName="totalBackups" <input id="backup-tasks" aria-describedby="backup-tasks-help" class="form-control" formControlName="totalBackups"
type="number" step="1" min="1" max="30" onkeypress="return event.charCode >= 48 && event.charCode <= 57" type="number" inputmode="numeric" step="1" min="1" max="30" onkeypress="return event.charCode >= 48 && event.charCode <= 57"
[class.is-invalid]="settingsForm.get('totalBackups')?.invalid && settingsForm.get('totalBackups')?.touched"> [class.is-invalid]="settingsForm.get('totalBackups')?.invalid && settingsForm.get('totalBackups')?.touched">
<ng-container *ngIf="settingsForm.get('totalBackups')?.errors as errors"> <ng-container *ngIf="settingsForm.get('totalBackups')?.errors as errors">
<p class="invalid-feedback" *ngIf="errors.min"> <p class="invalid-feedback" *ngIf="errors.min">
@ -97,7 +97,7 @@
<ng-template #logTasksTooltip>The number of logs to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template> <ng-template #logTasksTooltip>The number of logs to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template>
<span class="visually-hidden" id="log-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span> <span class="visually-hidden" id="log-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
<input id="log-tasks" aria-describedby="log-tasks-help" class="form-control" formControlName="totalLogs" <input id="log-tasks" aria-describedby="log-tasks-help" class="form-control" formControlName="totalLogs"
type="number" step="1" min="1" max="30" onkeypress="return event.charCode >= 48 && event.charCode <= 57" type="number" inputmode="numeric" step="1" min="1" max="30" onkeypress="return event.charCode >= 48 && event.charCode <= 57"
[class.is-invalid]="settingsForm.get('totalLogs')?.invalid && settingsForm.get('totalLogs')?.touched"> [class.is-invalid]="settingsForm.get('totalLogs')?.invalid && settingsForm.get('totalLogs')?.touched">
<ng-container *ngIf="settingsForm.get('totalLogs')?.errors as errors"> <ng-container *ngIf="settingsForm.get('totalLogs')?.errors as errors">
<p class="invalid-feedback" *ngIf="errors.min"> <p class="invalid-feedback" *ngIf="errors.min">

View File

@ -88,7 +88,7 @@
<label for="release-year" class="form-label">Release Year</label> <label for="release-year" class="form-label">Release Year</label>
<div class="input-group {{metadata.releaseYearLocked ? 'lock-active' : ''}}"> <div class="input-group {{metadata.releaseYearLocked ? 'lock-active' : ''}}">
<ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'releaseYearLocked' }"></ng-container> <ng-container [ngTemplateOutlet]="lock" [ngTemplateOutletContext]="{ item: metadata, field: 'releaseYearLocked' }"></ng-container>
<input type="number" class="form-control" id="release-year" formControlName="releaseYear" maxlength="4" minlength="4" [class.is-invalid]="editSeriesForm.get('releaseYear')?.invalid && editSeriesForm.get('releaseYear')?.touched"> <input type="number" inputmode="numeric" class="form-control" id="release-year" formControlName="releaseYear" maxlength="4" minlength="4" [class.is-invalid]="editSeriesForm.get('releaseYear')?.invalid && editSeriesForm.get('releaseYear')?.touched">
<ng-container *ngIf="editSeriesForm.get('releaseYear')?.errors as errors"> <ng-container *ngIf="editSeriesForm.get('releaseYear')?.errors as errors">
<p class="invalid-feedback" *ngIf="errors.pattern"> <p class="invalid-feedback" *ngIf="errors.pattern">
This must be a valid year greater than 1000 and 4 characters long This must be a valid year greater than 1000 and 4 characters long

View File

@ -92,7 +92,7 @@
<ng-template #progressEvent> <ng-template #progressEvent>
<li class="list-group-item dark-menu-item"> <li class="list-group-item dark-menu-item">
<div class="h6 mb-1">{{message.title}}</div> <div class="h6 mb-1">{{message.title}}</div>
<div class="accent-text mb-1" *ngIf="message.subTitle !== ''">{{message.subTitle}}</div> <div class="accent-text mb-1" *ngIf="message.subTitle !== ''" [title]="message.subTitle">{{message.subTitle}}</div>
<div class="progress-container row g-0 align-items-center"> <div class="progress-container row g-0 align-items-center">
<div class="col-2">{{prettyPrintProgress(message.body.progress) + '%'}}</div> <div class="col-2">{{prettyPrintProgress(message.body.progress) + '%'}}</div>
<div class="col-10 progress" style="height: 5px;"> <div class="col-10 progress" style="height: 5px;">
@ -122,7 +122,7 @@
<ng-container *ngFor="let download of activeDownloads"> <ng-container *ngFor="let download of activeDownloads">
<li class="list-group-item dark-menu-item"> <li class="list-group-item dark-menu-item">
<div class="h6 mb-1">Downloading {{download.entityType | sentenceCase}}</div> <div class="h6 mb-1">Downloading {{download.entityType | sentenceCase}}</div>
<div class="accent-text mb-1" *ngIf="download.subTitle !== ''">{{download.subTitle}}</div> <div class="accent-text mb-1" *ngIf="download.subTitle !== ''" [title]="download.subTitle">{{download.subTitle}}</div>
<div class="progress-container row g-0 align-items-center"> <div class="progress-container row g-0 align-items-center">
<div class="col-2">{{download.progress}}%</div> <div class="col-2">{{download.progress}}%</div>
<div class="col-10 progress" style="height: 5px;"> <div class="col-10 progress" style="height: 5px;">

View File

@ -1,7 +1,7 @@
<form [formGroup]="typeaheadForm" class="grouped-typeahead"> <form [formGroup]="typeaheadForm" class="grouped-typeahead">
<div class="typeahead-input" [ngClass]="{'focused': hasFocus}" (click)="onInputFocus($event)"> <div class="typeahead-input" [ngClass]="{'focused': hasFocus}" (click)="onInputFocus($event)">
<div class="search"> <div class="search">
<input #input [id]="id" type="text" autocomplete="off" formControlName="typeahead" [placeholder]="placeholder" <input #input [id]="id" type="text" inputmode="search" autocomplete="off" formControlName="typeahead" [placeholder]="placeholder"
aria-haspopup="listbox" aria-owns="dropdown" aria-expanded="hasFocus && (grouppedData.persons.length || grouppedData.collections.length || grouppedData.series.length || grouppedData.persons.length || grouppedData.tags.length || grouppedData.genres.length)" aria-haspopup="listbox" aria-owns="dropdown" aria-expanded="hasFocus && (grouppedData.persons.length || grouppedData.collections.length || grouppedData.series.length || grouppedData.persons.length || grouppedData.tags.length || grouppedData.genres.length)"
aria-autocomplete="list" (focusout)="close($event)" (focus)="open($event)" role="search" aria-autocomplete="list" (focusout)="close($event)" (focus)="open($event)" role="search"
> >

View File

@ -8,7 +8,7 @@
<div class="me-3 align-middle"> <div class="me-3 align-middle">
<div style="padding-top: 40px"> <div style="padding-top: 40px">
<label for="reorder-{{i}}" class="form-label visually-hidden">Reorder</label> <label for="reorder-{{i}}" class="form-label visually-hidden">Reorder</label>
<input *ngIf="accessibilityMode" id="reorder-{{i}}" class="form-control" type="number" min="0" [max]="items.length - 1" [value]="i" style="width: 60px" <input *ngIf="accessibilityMode" id="reorder-{{i}}" class="form-control" type="number" inputmode="numeric" min="0" [max]="items.length - 1" [value]="i" style="width: 60px"
(focusout)="updateIndex(i, item)" (keydown.enter)="updateIndex(i, item)" aria-describedby="instructions"> (focusout)="updateIndex(i, item)" (keydown.enter)="updateIndex(i, item)" aria-describedby="instructions">
</div> </div>
</div> </div>
@ -31,7 +31,7 @@
<div class="me-3 align-middle"> <div class="me-3 align-middle">
<div class="align-middle" style="padding-top: 40px" *ngIf="accessibilityMode"> <div class="align-middle" style="padding-top: 40px" *ngIf="accessibilityMode">
<label for="reorder-{{i}}" class="form-label visually-hidden">Reorder</label> <label for="reorder-{{i}}" class="form-label visually-hidden">Reorder</label>
<input id="reorder-{{i}}" class="form-control" type="number" min="0" [max]="items.length - 1" [value]="i" style="width: 60px" <input id="reorder-{{i}}" class="form-control" type="number" inputmode="numeric" min="0" [max]="items.length - 1" [value]="i" style="width: 60px"
(focusout)="updateIndex(i, item)" (keydown.enter)="updateIndex(i, item)" aria-describedby="instructions"> (focusout)="updateIndex(i, item)" (keydown.enter)="updateIndex(i, item)" aria-describedby="instructions">
</div> </div>
<i *ngIf="!accessibilityMode" class="fa fa-grip-vertical drag-handle" aria-hidden="true" cdkDragHandle></i> <i *ngIf="!accessibilityMode" class="fa fa-grip-vertical drag-handle" aria-hidden="true" cdkDragHandle></i>

View File

@ -43,7 +43,7 @@
<div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('startingMonth') as formControl" style="width: 90%"> <div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('startingMonth') as formControl" style="width: 90%">
<label for="start-month" class="form-label">Month</label> <label for="start-month" class="form-label">Month</label>
<input id="start-month" class="form-control" formControlName="startingMonth" <input id="start-month" class="form-control" formControlName="startingMonth"
type="number" [class.is-invalid]="formControl?.invalid && formControl?.touched" type="number" inputmode="numeric" [class.is-invalid]="formControl?.invalid && formControl?.touched"
aria-describedby="starting-year-header"> aria-describedby="starting-year-header">
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched"> <div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched">
<div *ngIf="formControl.errors?.min || formControl.errors?.max"> <div *ngIf="formControl.errors?.min || formControl.errors?.max">
@ -53,7 +53,7 @@
</div> </div>
<div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('startingYear') as formControl" style="width: 90%"> <div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('startingYear') as formControl" style="width: 90%">
<label for="start-year" class="form-label">Year</label> <label for="start-year" class="form-label">Year</label>
<input id="start-year" class="form-control" formControlName="startingYear" type="number" <input id="start-year" class="form-control" formControlName="startingYear" type="number" inputmode="numeric"
[class.is-invalid]="formControl.invalid && formControl.touched" [class.is-invalid]="formControl.invalid && formControl.touched"
aria-describedby="starting-year-header"> aria-describedby="starting-year-header">
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched"> <div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched">
@ -68,7 +68,7 @@
<h6 id="ending-year-heading">Ending</h6> <h6 id="ending-year-heading">Ending</h6>
<div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('endingMonth') as formControl" style="width: 90%"> <div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('endingMonth') as formControl" style="width: 90%">
<label for="library-name" class="form-label">Month</label> <label for="library-name" class="form-label">Month</label>
<input id="library-name" class="form-control" formControlName="endingMonth" type="number" <input id="library-name" class="form-control" formControlName="endingMonth" type="number" inputmode="numeric"
[class.is-invalid]="formControl?.invalid && formControl?.touched" [class.is-invalid]="formControl?.invalid && formControl?.touched"
aria-describedby="ending-year-header"> aria-describedby="ending-year-header">
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched"> <div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched">
@ -79,7 +79,7 @@
</div> </div>
<div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('endingYear') as formControl" style="width: 90%"> <div class="col-md-6 col-sm-12" *ngIf="reviewGroup.get('endingYear') as formControl" style="width: 90%">
<label for="library-name" class="form-label">Year</label> <label for="library-name" class="form-label">Year</label>
<input id="library-name" class="form-control" formControlName="endingYear" type="number" <input id="library-name" class="form-control" formControlName="endingYear" type="number" inputmode="numeric"
[class.is-invalid]="formControl?.invalid && formControl?.touched" [class.is-invalid]="formControl?.invalid && formControl?.touched"
aria-describedby="ending-year-header"> aria-describedby="ending-year-header">
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched"> <div id="inviteForm-validations" class="invalid-feedback" *ngIf="reviewGroup.dirty || reviewGroup.touched">

View File

@ -23,7 +23,7 @@
<div class="mb-3" style="width:100%"> <div class="mb-3" style="width:100%">
<label for="email" class="form-label">Email</label> <label for="email" class="form-label">Email</label>
<input class="form-control" type="email" id="email" formControlName="email" required readonly <input class="form-control" type="email" inputmode="email" id="email" formControlName="email" required readonly
[class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched"> [class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched">
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched"> <div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
<div *ngIf="registerForm.get('email')?.errors?.required"> <div *ngIf="registerForm.get('email')?.errors?.required">

View File

@ -20,7 +20,7 @@
<span class="visually-hidden" id="email-help"> <span class="visually-hidden" id="email-help">
<ng-container [ngTemplateOutlet]="emailTooltip"></ng-container> <ng-container [ngTemplateOutlet]="emailTooltip"></ng-container>
</span> </span>
<input class="form-control" type="email" id="email" formControlName="email" required aria-describedby="email-help" <input class="form-control" type="email" inputmode="email" id="email" formControlName="email" required aria-describedby="email-help"
[class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched"> [class.is-invalid]="registerForm.get('email')?.invalid && registerForm.get('email')?.touched">
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched"> <div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
<div *ngIf="registerForm.get('email')?.errors?.required"> <div *ngIf="registerForm.get('email')?.errors?.required">

Some files were not shown because too many files have changed in this diff Show More