mirror of
https://github.com/Ikatono/ComiServ.git
synced 2025-10-28 20:45:35 -05:00
Compare commits
6 Commits
7479dbf8f8
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41c92196b6 | ||
|
|
06fc8260d5 | ||
|
|
a69cd6a33c | ||
|
|
fd92d38cdd | ||
|
|
296190b79c | ||
|
|
0082a6f219 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
|
*.sln
|
||||||
|
|
||||||
#SQLite files
|
#SQLite files
|
||||||
*.db
|
*.db
|
||||||
|
|||||||
@@ -313,6 +313,8 @@ public class ComicController(ComicsContext context, ILogger<ComicController> log
|
|||||||
var comic = await _context.Comics.SingleOrDefaultAsync(c => c.Handle == handle);
|
var comic = await _context.Comics.SingleOrDefaultAsync(c => c.Handle == handle);
|
||||||
if (comic is null)
|
if (comic is null)
|
||||||
return NotFound(RequestError.ComicNotFound);
|
return NotFound(RequestError.ComicNotFound);
|
||||||
|
//can't mock this easily, move to a service?
|
||||||
|
//maybe IComicAnalyzer should be used even just to read a file
|
||||||
var data = await System.IO.File.ReadAllBytesAsync(Path.Join(_config.LibraryRoot, comic.Filepath));
|
var data = await System.IO.File.ReadAllBytesAsync(Path.Join(_config.LibraryRoot, comic.Filepath));
|
||||||
return File(data, "application/octet-stream", new FileInfo(comic.Filepath).Name);
|
return File(data, "application/octet-stream", new FileInfo(comic.Filepath).Name);
|
||||||
}
|
}
|
||||||
@@ -469,8 +471,8 @@ public class ComicController(ComicsContext context, ILogger<ComicController> log
|
|||||||
public async Task<IActionResult> GetLibraryStats()
|
public async Task<IActionResult> GetLibraryStats()
|
||||||
{
|
{
|
||||||
return Ok(new LibraryResponse(
|
return Ok(new LibraryResponse(
|
||||||
await _context.Comics.CountAsync(),
|
ComicCount: await _context.Comics.CountAsync(),
|
||||||
await _context.Comics.Select(c => c.FileXxhash64).Distinct().CountAsync()
|
UniqueFiles: await _context.Comics.Select(c => c.FileXxhash64).Distinct().CountAsync()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
41
ComiServ/Properties/launchSettings.json
Normal file
41
ComiServ/Properties/launchSettings.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:32904",
|
||||||
|
"sslPort": 44308
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:5265",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "https://localhost:7020;http://localhost:5265",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
ComiServ/package-lock.json
generated
Normal file
44
ComiServ/package-lock.json
generated
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "ComiServ",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "^18.3.4",
|
||||||
|
"@types/react-dom": "^18.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/prop-types": {
|
||||||
|
"version": "15.7.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
|
||||||
|
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/react": {
|
||||||
|
"version": "18.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz",
|
||||||
|
"integrity": "sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/prop-types": "*",
|
||||||
|
"csstype": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/react-dom": {
|
||||||
|
"version": "18.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz",
|
||||||
|
"integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/csstype": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
ComiServ/package.json
Normal file
6
ComiServ/package.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "^18.3.4",
|
||||||
|
"@types/react-dom": "^18.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
28
ComiServUnitTest/ComiServUnitTest.csproj
Normal file
28
ComiServUnitTest/ComiServUnitTest.csproj
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
|
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
||||||
|
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ComiServ\ComiServ.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
96
ComiServUnitTest/ContollerTests/ComicControllerTests.cs
Normal file
96
ComiServUnitTest/ContollerTests/ComicControllerTests.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ComiServ;
|
||||||
|
using ComiServ.Entities;
|
||||||
|
using ComiServ.Services;
|
||||||
|
using ComiServ.Controllers;
|
||||||
|
using Microsoft.CodeAnalysis.Elfie.Diagnostics;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using ComiServUnitTest.Mocks;
|
||||||
|
using ComiServ.Background;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace ComiServUnitTest.ContollerTests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class ComicControllerTests
|
||||||
|
{
|
||||||
|
private ILoggerFactory? _factory;
|
||||||
|
public ILoggerFactory factory
|
||||||
|
{ get
|
||||||
|
{
|
||||||
|
_factory = _factory ?? LoggerFactory.Create(builder => builder.AddConsole());
|
||||||
|
return _factory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task TestGetPage()
|
||||||
|
{
|
||||||
|
const int PAGE_NUMBER = 7;
|
||||||
|
const string PAGE_FILEPATH = "Page File.jpg";
|
||||||
|
const string PAGE_MIME = "image/jpeg";
|
||||||
|
var context = DatabaseHelper.CreateDatabase();
|
||||||
|
Comic comic = new()
|
||||||
|
{
|
||||||
|
Title = "Test Comic",
|
||||||
|
Filepath = Path.Join("test", "filepath"),
|
||||||
|
Handle = string.Join("", Enumerable.Repeat("A", ComicsContext.HANDLE_LENGTH)),
|
||||||
|
Description = ""
|
||||||
|
};
|
||||||
|
context.Comics.Add(comic);
|
||||||
|
User user = new()
|
||||||
|
{
|
||||||
|
Username = "user",
|
||||||
|
UserTypeId = UserTypeEnum.User,
|
||||||
|
Salt = User.MakeSalt(),
|
||||||
|
HashedPassword = User.Hash([], []),
|
||||||
|
};
|
||||||
|
context.Users.Add(user);
|
||||||
|
context.SaveChanges();
|
||||||
|
Configuration config = new()
|
||||||
|
{
|
||||||
|
AutoScanPeriodHours = 24,
|
||||||
|
DatabaseFile = "",
|
||||||
|
LibraryRoot = "root",
|
||||||
|
};
|
||||||
|
ComicPage comicPage = new(PAGE_FILEPATH, PAGE_MIME, [1, 2, 3, 4, 5]);
|
||||||
|
MockComicAnalyzer analyzer = new();
|
||||||
|
analyzer.ComicPages.Add((Path.Join(config.LibraryRoot, comic.Filepath), PAGE_NUMBER), comicPage);
|
||||||
|
//returned from all MockPictureConverter functions
|
||||||
|
byte[] mockPictureData = [5, 4, 3, 2, 1];
|
||||||
|
MockPictureConverter converter = new MockPictureConverter(mockPictureData);
|
||||||
|
AuthenticationService auth = new();
|
||||||
|
auth.Authenticate(user);
|
||||||
|
var controller = new ComicController(
|
||||||
|
context,
|
||||||
|
factory.CreateLogger<ComicController>(),
|
||||||
|
new MockConfig(config),
|
||||||
|
analyzer,
|
||||||
|
converter,
|
||||||
|
auth
|
||||||
|
);
|
||||||
|
//get actual page
|
||||||
|
var result = await controller.GetComicPage(comic.Handle, PAGE_NUMBER, null, null, null);
|
||||||
|
Assert.IsInstanceOfType<FileContentResult>(result);
|
||||||
|
var contents = ((FileContentResult)result).FileContents;
|
||||||
|
Assert.IsTrue(comicPage.Data.SequenceEqual(contents));
|
||||||
|
//invalid handle (too short)
|
||||||
|
var result2 = await controller.GetComicPage(comic.Handle.Substring(comic.Handle.Length-1),
|
||||||
|
PAGE_NUMBER, null, null, null);
|
||||||
|
Assert.IsInstanceOfType<BadRequestObjectResult>(result2);
|
||||||
|
//valid handle but doesn't exist
|
||||||
|
var result3 = await controller.GetComicPage(string.Join("", Enumerable.Repeat("B", ComicsContext.HANDLE_LENGTH)),
|
||||||
|
PAGE_NUMBER, null, null, null);
|
||||||
|
Assert.IsInstanceOfType<NotFoundObjectResult>(result3);
|
||||||
|
//valid handle and convert
|
||||||
|
var result4 = await controller.GetComicPage(comic.Handle, PAGE_NUMBER, 500, 500, PictureFormats.Webp);
|
||||||
|
Assert.AreEqual(1, converter.ResizeIfBiggerCount);
|
||||||
|
Assert.IsInstanceOfType<FileContentResult>(result4);
|
||||||
|
Assert.IsTrue(mockPictureData.SequenceEqual(((FileContentResult)result4).FileContents));
|
||||||
|
}
|
||||||
|
}
|
||||||
25
ComiServUnitTest/DatabaseHelper.cs
Normal file
25
ComiServUnitTest/DatabaseHelper.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using ComiServ;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ComiServUnitTest;
|
||||||
|
|
||||||
|
internal static class DatabaseHelper
|
||||||
|
{
|
||||||
|
public static ComicsContext CreateDatabase()
|
||||||
|
{
|
||||||
|
var connection = new SqliteConnection("Filename=:memory:");
|
||||||
|
connection.Open();
|
||||||
|
var contextOptions = new DbContextOptionsBuilder<ComicsContext>()
|
||||||
|
.UseSqlite(connection)
|
||||||
|
.Options;
|
||||||
|
var context = new ComicsContext(contextOptions);
|
||||||
|
context.Database.EnsureCreated();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
87
ComiServUnitTest/EntityTests/PaginatedTests.cs
Normal file
87
ComiServUnitTest/EntityTests/PaginatedTests.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
using ComiServ.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
||||||
|
using System.CodeDom;
|
||||||
|
using System.Security.Policy;
|
||||||
|
|
||||||
|
namespace ComiServUnitTest.EntityTests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class PaginatedTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void PageUnderUnderflow()
|
||||||
|
{
|
||||||
|
const int pageNum = 1;
|
||||||
|
const int pageSize = 20;
|
||||||
|
const int dataSize = 30;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var page = new Paginated<int>(pageSize, pageNum, data);
|
||||||
|
Assert.IsTrue(page.Last);
|
||||||
|
Assert.AreEqual(pageSize, page.Max);
|
||||||
|
Assert.AreEqual(pageNum, page.Page);
|
||||||
|
Assert.AreEqual(10, page.Count);
|
||||||
|
Assert.AreEqual(page.Items.Count, page.Count);
|
||||||
|
Assert.AreEqual(20, page.Items.First());
|
||||||
|
Assert.AreEqual(data.Last(), page.Items.Last());
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void PageOverflow()
|
||||||
|
{
|
||||||
|
const int pageNum = 2;
|
||||||
|
const int pageSize = 30;
|
||||||
|
const int dataSize = 150;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var page = new Paginated<int>(pageSize, pageNum, data);
|
||||||
|
Assert.IsFalse(page.Last);
|
||||||
|
Assert.AreEqual(pageSize, page.Max);
|
||||||
|
Assert.AreEqual(pageNum, page.Page);
|
||||||
|
Assert.AreEqual(pageSize, page.Count);
|
||||||
|
Assert.AreEqual(page.Items.Count, page.Count);
|
||||||
|
Assert.AreEqual(pageSize * pageNum, page.Items.First());
|
||||||
|
Assert.AreEqual(pageSize * (pageNum + 1) - 1, page.Items.Last());
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void PageExact()
|
||||||
|
{
|
||||||
|
const int pageNum = 1;
|
||||||
|
const int pageSize = 30;
|
||||||
|
const int dataSize = 60;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var page = new Paginated<int>(pageSize, pageNum, data);
|
||||||
|
Assert.IsTrue(page.Last);
|
||||||
|
Assert.AreEqual(pageSize, page.Max);
|
||||||
|
Assert.AreEqual(pageNum, page.Page);
|
||||||
|
Assert.AreEqual(pageSize, page.Count);
|
||||||
|
Assert.AreEqual(page.Items.Count, page.Count);
|
||||||
|
Assert.AreEqual(pageSize * pageNum, page.Items.First());
|
||||||
|
Assert.AreEqual(data.Last(), page.Items.Last());
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void PageEmpty()
|
||||||
|
{
|
||||||
|
const int pageNum = 0;
|
||||||
|
const int pageSize = 10;
|
||||||
|
const int dataSize = 0;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var page = new Paginated<int>(pageSize, pageNum, data);
|
||||||
|
Assert.IsTrue(page.Last);
|
||||||
|
Assert.AreEqual(pageSize, page.Max);
|
||||||
|
Assert.AreEqual(pageNum, page.Page);
|
||||||
|
Assert.AreEqual(page.Items.Count, page.Count);
|
||||||
|
Assert.IsFalse(page.Items.Any());
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void PageDoesntExist()
|
||||||
|
{
|
||||||
|
const int pageNum = 5;
|
||||||
|
const int pageSize = 20;
|
||||||
|
const int dataSize = 50;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var page = new Paginated<int>(pageSize, pageNum, data);
|
||||||
|
Assert.IsTrue(page.Last);
|
||||||
|
Assert.AreEqual(pageSize, page.Max);
|
||||||
|
Assert.AreEqual(pageNum, page.Page);
|
||||||
|
Assert.AreEqual(page.Items.Count, page.Count);
|
||||||
|
Assert.IsFalse(page.Items.Any());
|
||||||
|
}
|
||||||
|
}
|
||||||
67
ComiServUnitTest/EntityTests/TruncatedTests.cs
Normal file
67
ComiServUnitTest/EntityTests/TruncatedTests.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ComiServ.Models;
|
||||||
|
|
||||||
|
namespace ComiServUnitTest.EntityTests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class TruncatedTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void TruncationUnderflow()
|
||||||
|
{
|
||||||
|
const int truncMax = 20;
|
||||||
|
const int dataSize = 10;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var trunc = new Truncated<int>(truncMax, data);
|
||||||
|
Assert.IsTrue(trunc.Complete);
|
||||||
|
Assert.AreEqual(truncMax, trunc.Max);
|
||||||
|
Assert.AreEqual(dataSize, trunc.Count);
|
||||||
|
Assert.AreEqual(trunc.Items.Count, trunc.Count);
|
||||||
|
Assert.AreEqual(data.First(), trunc.Items.First());
|
||||||
|
Assert.AreEqual(data.Last(), trunc.Items.Last());
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void TruncationOverflow()
|
||||||
|
{
|
||||||
|
const int truncMax = 20;
|
||||||
|
const int dataSize = 30;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var trunc = new Truncated<int>(truncMax, data);
|
||||||
|
Assert.IsFalse(trunc.Complete);
|
||||||
|
Assert.AreEqual(truncMax, trunc.Max);
|
||||||
|
Assert.AreEqual(truncMax, trunc.Count);
|
||||||
|
Assert.AreEqual(trunc.Items.Count, trunc.Count);
|
||||||
|
Assert.AreEqual(data.First(), trunc.Items.First());
|
||||||
|
Assert.AreEqual(truncMax - 1, trunc.Items.Last());
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void TruncationExact()
|
||||||
|
{
|
||||||
|
const int truncMax = 5;
|
||||||
|
const int dataSize = 5;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var trunc = new Truncated<int>(truncMax, data);
|
||||||
|
Assert.IsTrue(trunc.Complete);
|
||||||
|
Assert.AreEqual(truncMax, trunc.Max);
|
||||||
|
Assert.AreEqual(truncMax, trunc.Count);
|
||||||
|
Assert.AreEqual(trunc.Items.Count, trunc.Count);
|
||||||
|
Assert.AreEqual(data.First(), trunc.Items.First());
|
||||||
|
Assert.AreEqual(data.Last(), trunc.Items.Last());
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void TruncationEmpty()
|
||||||
|
{
|
||||||
|
const int truncMax = 5;
|
||||||
|
const int dataSize = 0;
|
||||||
|
var data = Enumerable.Range(0, dataSize).ToArray();
|
||||||
|
var trunc = new Truncated<int>(truncMax, data);
|
||||||
|
Assert.IsTrue(trunc.Complete);
|
||||||
|
Assert.AreEqual(truncMax, trunc.Max);
|
||||||
|
Assert.AreEqual(0, trunc.Count);
|
||||||
|
Assert.AreEqual(trunc.Items.Count, trunc.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
75
ComiServUnitTest/Mocks/MockComicAnalyzer.cs
Normal file
75
ComiServUnitTest/Mocks/MockComicAnalyzer.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using ComiServ.Background;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ComiServUnitTest.Mocks
|
||||||
|
{
|
||||||
|
internal class MockComicAnalyzer : IComicAnalyzer
|
||||||
|
{
|
||||||
|
//preseed these
|
||||||
|
public readonly Dictionary<string, ComicAnalysis> AnalysisResults = [];
|
||||||
|
public readonly HashSet<string> ComicsThatExist = [];
|
||||||
|
public readonly Dictionary<(string, int), ComicPage> ComicPages = [];
|
||||||
|
|
||||||
|
//check these afterwards
|
||||||
|
public readonly List<string> Analyzed = [];
|
||||||
|
public readonly List<string> CheckedForExistance = [];
|
||||||
|
public readonly List<string> Deleted = [];
|
||||||
|
public readonly List<(string, int)> RetreivedPages = [];
|
||||||
|
public MockComicAnalyzer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
Analyzed.Clear();
|
||||||
|
CheckedForExistance.Clear();
|
||||||
|
Deleted.Clear();
|
||||||
|
RetreivedPages.Clear();
|
||||||
|
}
|
||||||
|
public ComicAnalysis? AnalyzeComic(string filename)
|
||||||
|
{
|
||||||
|
Analyzed.Add(filename);
|
||||||
|
if (AnalysisResults.TryGetValue(filename, out var analysis))
|
||||||
|
return analysis;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
public async Task<ComicAnalysis?> AnalyzeComicAsync(string filename)
|
||||||
|
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
{
|
||||||
|
return AnalyzeComic(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ComicFileExists(string filename)
|
||||||
|
{
|
||||||
|
CheckedForExistance.Add(filename);
|
||||||
|
return ComicsThatExist.Contains(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteComicFile(string filename)
|
||||||
|
{
|
||||||
|
Deleted.Add(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComicPage? GetComicPage(string filepath, int page)
|
||||||
|
{
|
||||||
|
var key = (filepath, page);
|
||||||
|
RetreivedPages.Add(key);
|
||||||
|
if (ComicPages.TryGetValue(key, out var comicPage))
|
||||||
|
return comicPage;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
public async Task<ComicPage?> GetComicPageAsync(string filepath, int page)
|
||||||
|
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
{
|
||||||
|
return GetComicPage(filepath, page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
ComiServUnitTest/Mocks/MockConfig.cs
Normal file
20
ComiServUnitTest/Mocks/MockConfig.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using ComiServ.Services;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ComiServUnitTest.Mocks;
|
||||||
|
|
||||||
|
internal class MockConfig : IConfigService
|
||||||
|
{
|
||||||
|
private readonly Configuration _Config;
|
||||||
|
public Configuration Config => _Config.Copy();
|
||||||
|
public MockConfig(Configuration config)
|
||||||
|
{
|
||||||
|
_Config = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
ComiServUnitTest/Mocks/MockPictureConverter.cs
Normal file
46
ComiServUnitTest/Mocks/MockPictureConverter.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using ComiServ.Background;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ComiServUnitTest.Mocks
|
||||||
|
{
|
||||||
|
internal class MockPictureConverter : IPictureConverter
|
||||||
|
{
|
||||||
|
public int MakeThumbnailCount = 0;
|
||||||
|
public int ResizeCount = 0;
|
||||||
|
public int ResizeIfBiggerCount = 0;
|
||||||
|
private byte[] StreamObject { get; }
|
||||||
|
public MockPictureConverter(byte[] streamObject)
|
||||||
|
{
|
||||||
|
StreamObject = streamObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
public async Task<Stream> MakeThumbnail(Stream image)
|
||||||
|
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
{
|
||||||
|
MakeThumbnailCount++;
|
||||||
|
return new MemoryStream(StreamObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
public async Task<Stream> Resize(Stream image, Size newSize, PictureFormats? newFormat = null)
|
||||||
|
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
{
|
||||||
|
ResizeCount++;
|
||||||
|
return new MemoryStream(StreamObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
public async Task<Stream> ResizeIfBigger(Stream image, Size maxSize, PictureFormats? newFormat = null)
|
||||||
|
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
{
|
||||||
|
ResizeIfBiggerCount++;
|
||||||
|
return new MemoryStream(StreamObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
ComiServUnitTest/ServiceTests/AuthenticationServiceTests.cs
Normal file
38
ComiServUnitTest/ServiceTests/AuthenticationServiceTests.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ComiServ.Entities;
|
||||||
|
using ComiServ.Services;
|
||||||
|
|
||||||
|
namespace ComiServUnitTest.ServiceTests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class AuthenticationServiceTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void FailAuth()
|
||||||
|
{
|
||||||
|
IAuthenticationService auth = new AuthenticationService();
|
||||||
|
Assert.IsFalse(auth.Tested);
|
||||||
|
auth.FailAuth();
|
||||||
|
Assert.IsTrue(auth.Tested);
|
||||||
|
Assert.IsNull(auth.User);
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void AuthenticateUser()
|
||||||
|
{
|
||||||
|
IAuthenticationService auth = new AuthenticationService();
|
||||||
|
User user = new()
|
||||||
|
{
|
||||||
|
Username = "NewUser",
|
||||||
|
UserTypeId = UserTypeEnum.User,
|
||||||
|
};
|
||||||
|
Assert.IsFalse(auth.Tested);
|
||||||
|
auth.Authenticate(user);
|
||||||
|
Assert.IsTrue(auth.Tested);
|
||||||
|
Assert.IsNotNull(auth.User);
|
||||||
|
Assert.AreSame(user, auth.User);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user