Added abstraction layeer IHtmlLoader. Finished reorganizing test project folder structure.
This commit is contained in:
@@ -13,16 +13,17 @@
|
||||
<None Remove="Sources\MangaDex\Api\Manga-Chapter-Response.json" />
|
||||
<None Remove="Sources\MangaDex\Api\Manga-Cover-Art-Response.json" />
|
||||
<None Remove="Sources\MangaDex\Api\Manga-Search-Response-2.json" />
|
||||
<None Remove="Sources\NatoManga\Api\Manga-Chapter-Response.html" />
|
||||
<None Remove="WebCrawlers\Samples\MangaNato - Please Go Home, Akutsu-San!.htm" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="WebCrawlers\NatoManga\SampleMangaPage.html">
|
||||
<EmbeddedResource Include="Sources\NatoManga\Metadata\Manga-Response.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="WebCrawlers\Samples\MangaNato - Please Go Home, Akutsu-San!.htm">
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Sources\MangaNato\Metadata\Manga-Response.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -30,6 +31,7 @@
|
||||
<EmbeddedResource Include="Sources\MangaDex\Api\Manga-Cover-Art-Response.json" />
|
||||
<EmbeddedResource Include="Sources\MangaDex\Api\Manga-Search-Response-2.json" />
|
||||
<EmbeddedResource Include="Sources\MangaDex\Api\Manga-Search-Response.json" />
|
||||
<EmbeddedResource Include="Sources\NatoManga\Metadata\Manga-Chapter-Response.html" />
|
||||
<EmbeddedResource Include="Sources\NatoManga\Api\Manga-Search-Response.json" />
|
||||
<EmbeddedResource Include="Sources\MangaDex\Api\Manga-Feed-Response.json" />
|
||||
<EmbeddedResource Include="Sources\MangaDex\Api\Manga-Response.json" />
|
||||
@@ -59,4 +61,9 @@
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="WebCrawlers\NatoManga\" />
|
||||
<Folder Include="WebCrawlers\Samples\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -17,12 +17,16 @@ public class MangaPipelineTests(TestDbContextFactory factory) : IClassFixture<Te
|
||||
|
||||
var sourceManga = new SourceManga
|
||||
{
|
||||
Title = "Fullmetal Alchemist",
|
||||
Title = new()
|
||||
{
|
||||
Name = "Fullmetal Alchemist",
|
||||
Language = Language.English
|
||||
},
|
||||
AlternateTitles =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Title = "Hagane no Renkinjutsushi",
|
||||
Name = "Hagane no Renkinjutsushi",
|
||||
Language = Language.Romaji
|
||||
}
|
||||
],
|
||||
@@ -49,7 +53,10 @@ public class MangaPipelineTests(TestDbContextFactory factory) : IClassFixture<Te
|
||||
await pipeline.RunAsync(request);
|
||||
|
||||
context.Mangas.ShouldHaveSingleItem();
|
||||
context.MangaTitles.ShouldHaveSingleItem();
|
||||
context.MangaTitles.Count().ShouldBe(2);
|
||||
context.MangaTitles.Where(mt => mt.IsPrimary).ShouldHaveSingleItem();
|
||||
context.MangaTitles.Where(mt => mt.IsPrimary).First().Name.ShouldBe("Fullmetal Alchemist");
|
||||
context.MangaTitles.Where(mt => mt.IsPrimary).First().Language.ShouldBe(Language.English);
|
||||
context.Genres.Count().ShouldBe(2);
|
||||
context.MangaChapters.ShouldHaveSingleItem();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using MangaReader.Core.HttpService;
|
||||
using MangaReader.Core.Http;
|
||||
using MangaReader.Core.Sources.MangaDex.Api;
|
||||
using MangaReader.Tests.Utilities;
|
||||
using NSubstitute;
|
||||
|
||||
@@ -229,23 +229,23 @@ public class MangaDexMetadataTests
|
||||
SourceManga? sourceManga = await metadataProvider.GetMangaAsync("https://mangadex.org/title/ee96e2b7-9af2-4864-9656-649f4d3b6fec/gals-can-t-be-kind-to-otaku", CancellationToken.None);
|
||||
|
||||
sourceManga.ShouldNotBeNull();
|
||||
sourceManga.Title.ShouldBe("Gals Can’t Be Kind to Otaku!?");
|
||||
sourceManga.Title.Name.ShouldBe("Gals Can’t Be Kind to Otaku!?");
|
||||
|
||||
sourceManga.AlternateTitles.Count.ShouldBe(5);
|
||||
|
||||
sourceManga.AlternateTitles[0].Title.ShouldBe("オタクに優しいギャルはいない!?");
|
||||
sourceManga.AlternateTitles[0].Name.ShouldBe("オタクに優しいギャルはいない!?");
|
||||
sourceManga.AlternateTitles[0].Language.ShouldBe(Language.Japanese);
|
||||
|
||||
sourceManga.AlternateTitles[1].Title.ShouldBe("Otaku ni Yasashii Gal wa Inai!?");
|
||||
sourceManga.AlternateTitles[1].Name.ShouldBe("Otaku ni Yasashii Gal wa Inai!?");
|
||||
sourceManga.AlternateTitles[1].Language.ShouldBe(Language.Romaji);
|
||||
|
||||
sourceManga.AlternateTitles[2].Title.ShouldBe("Otaku ni Yasashii Gyaru ha Inai!?");
|
||||
sourceManga.AlternateTitles[2].Name.ShouldBe("Otaku ni Yasashii Gyaru ha Inai!?");
|
||||
sourceManga.AlternateTitles[2].Language.ShouldBe(Language.Romaji);
|
||||
|
||||
sourceManga.AlternateTitles[3].Title.ShouldBe("Gal Can't Be Kind to Otaku!?");
|
||||
sourceManga.AlternateTitles[3].Name.ShouldBe("Gal Can't Be Kind to Otaku!?");
|
||||
sourceManga.AlternateTitles[3].Language.ShouldBe(Language.English);
|
||||
|
||||
sourceManga.AlternateTitles[4].Title.ShouldBe("Gals Can't Be Kind To A Geek!?");
|
||||
sourceManga.AlternateTitles[4].Name.ShouldBe("Gals Can't Be Kind To A Geek!?");
|
||||
sourceManga.AlternateTitles[4].Language.ShouldBe(Language.English);
|
||||
|
||||
sourceManga.Genres.Count.ShouldBe(5);
|
||||
|
||||
@@ -1,47 +1,35 @@
|
||||
using HtmlAgilityPack;
|
||||
using MangaReader.Core.Http;
|
||||
using MangaReader.Core.Metadata;
|
||||
using MangaReader.Core.Sources.MangaNato.Metadata;
|
||||
using MangaReader.Tests.Utilities;
|
||||
using NSubstitute;
|
||||
using Shouldly;
|
||||
using System.Data;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace MangaReader.Tests.WebCrawlers;
|
||||
namespace MangaReader.Tests.Sources.MangaNato.Metadata;
|
||||
|
||||
public class UnitTest1
|
||||
public class MangaNatoMetadataTests
|
||||
{
|
||||
class TestMangaNatoWebCrawler : MangaNatoWebCrawler
|
||||
{
|
||||
protected override Task<HtmlDocument> GetHtmlDocumentAsync(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
HtmlWeb web = new()
|
||||
{
|
||||
UsingCacheIfExists = false
|
||||
};
|
||||
|
||||
return Task.FromResult(web.Load(url));
|
||||
}
|
||||
}
|
||||
|
||||
private readonly string samplesPath;
|
||||
private readonly string mangaNatoSampleFilePath;
|
||||
|
||||
public UnitTest1()
|
||||
{
|
||||
samplesPath = Path.Combine(AppContext.BaseDirectory, "WebCrawlers", "Samples");
|
||||
mangaNatoSampleFilePath = Path.Combine(samplesPath, "MangaNato - Please Go Home, Akutsu-San!.htm");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_Manga()
|
||||
{
|
||||
var webCrawler = new TestMangaNatoWebCrawler();
|
||||
var manga = await webCrawler.GetMangaAsync(mangaNatoSampleFilePath, CancellationToken.None);
|
||||
string mangaHtml = await ReadJsonResourceAsync("Manga-Response.html");
|
||||
|
||||
IHttpService httpService = Substitute.For<IHttpService>();
|
||||
|
||||
httpService.GetStringAsync(Arg.Any<string>(), CancellationToken.None)
|
||||
.Returns(Task.FromResult(mangaHtml));
|
||||
|
||||
HtmlLoader htmlLoader = new(httpService);
|
||||
|
||||
MangaNatoWebCrawler webCrawler = new(htmlLoader);
|
||||
SourceManga? manga = await webCrawler.GetMangaAsync("/test-url", CancellationToken.None);
|
||||
|
||||
manga.ShouldNotBeNull();
|
||||
|
||||
manga.Title.ShouldBe("Please Go Home, Akutsu-San!");
|
||||
manga.Title.Name.ShouldBe("Please Go Home, Akutsu-San!");
|
||||
|
||||
manga.AlternateTitles.Select(x => x.Title).ShouldBe([
|
||||
manga.AlternateTitles.Select(x => x.Name).ShouldBe([
|
||||
"Kaette kudasai! Akutsu-san",
|
||||
"Yankee Musume",
|
||||
"ヤンキー娘",
|
||||
@@ -62,8 +50,8 @@ public class UnitTest1
|
||||
manga.Votes.ShouldBe(15979);
|
||||
|
||||
//manga.Description.ShouldStartWith("Ooyama-kun normally doesn’t get involved with Akutsu-san, a delinquent girl in his class");
|
||||
manga.Description.ShouldStartWith("Ooyama-kun normally doesn’t get involved with Akutsu-san, a delinquent girl in his class");
|
||||
manga.Description.ShouldEndWith("Artist's Pixiv: https://www.pixiv.net/member.php?id=133935");
|
||||
manga.Description?.Name.ShouldStartWith("Ooyama-kun normally doesn’t get involved with Akutsu-san, a delinquent girl in his class");
|
||||
manga.Description?.Name.ShouldEndWith("Artist's Pixiv: https://www.pixiv.net/member.php?id=133935");
|
||||
|
||||
manga.Chapters.Count.ShouldBe(236);
|
||||
|
||||
@@ -79,4 +67,9 @@ public class UnitTest1
|
||||
manga.Chapters[235].Views.ShouldBe(232_200);
|
||||
manga.Chapters[235].UploadDate.ShouldBe(new DateTime(2021, 8, 24, 1, 8, 0));
|
||||
}
|
||||
|
||||
private static async Task<string> ReadJsonResourceAsync(string resourceName)
|
||||
{
|
||||
return await ResourceHelper.ReadJsonResourceAsync($"MangaReader.Tests.Sources.MangaNato.Metadata.{resourceName}");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using MangaReader.Core.HttpService;
|
||||
using MangaReader.Core.Http;
|
||||
using MangaReader.Core.Sources.NatoManga.Api;
|
||||
using MangaReader.Tests.Utilities;
|
||||
using NSubstitute;
|
||||
@@ -34,6 +34,9 @@ public class NatoMangaClientTests
|
||||
httpService.GetStringAsync(Arg.Any<string>(), CancellationToken.None)
|
||||
.Returns(Task.FromResult(searchResultJson));
|
||||
|
||||
httpService.GetStringAsync(Arg.Any<string>(), Arg.Any<IDictionary<string,string>>(), CancellationToken.None)
|
||||
.Returns(Task.FromResult(searchResultJson));
|
||||
|
||||
NatoMangaClient natoMangaClient = new(httpService);
|
||||
NatoMangaSearchResult[] searchResults = await natoMangaClient.SearchAsync("Gal Can't Be Kind", CancellationToken.None);
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,35 +1,32 @@
|
||||
using HtmlAgilityPack;
|
||||
using MangaReader.Core.Http;
|
||||
using MangaReader.Core.Metadata;
|
||||
using MangaReader.Core.Sources.NatoManga.Metadata;
|
||||
using MangaReader.Tests.Utilities;
|
||||
using NSubstitute;
|
||||
using Shouldly;
|
||||
|
||||
namespace MangaReader.Tests.WebCrawlers.NatoManga;
|
||||
namespace MangaReader.Tests.Sources.NatoManga.Metadata;
|
||||
|
||||
public class NatoMangaWebCrawlerTests
|
||||
{
|
||||
class TestNatoMangaWebCrawler : NatoMangaWebCrawler
|
||||
{
|
||||
protected override Task<HtmlDocument> GetHtmlDocumentAsync(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
HtmlWeb web = new()
|
||||
{
|
||||
UsingCacheIfExists = false
|
||||
};
|
||||
|
||||
return Task.FromResult(web.Load(url));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_Manga()
|
||||
{
|
||||
string sampleFilePath = Path.Combine(AppContext.BaseDirectory, "WebCrawlers", "NatoManga", "SampleMangaPage.html");
|
||||
string mangaHtml = await ReadJsonResourceAsync("Manga-Response.html");
|
||||
|
||||
var webCrawler = new TestNatoMangaWebCrawler();
|
||||
var manga = await webCrawler.GetMangaAsync(sampleFilePath, CancellationToken.None);
|
||||
IHttpService httpService = Substitute.For<IHttpService>();
|
||||
|
||||
httpService.GetStringAsync(Arg.Any<string>(), CancellationToken.None)
|
||||
.Returns(Task.FromResult(mangaHtml));
|
||||
|
||||
HtmlLoader htmlLoader = new(httpService);
|
||||
|
||||
NatoMangaWebCrawler webCrawler = new(htmlLoader);
|
||||
SourceManga? manga = await webCrawler.GetMangaAsync("/test-url", CancellationToken.None);
|
||||
|
||||
manga.ShouldNotBeNull();
|
||||
|
||||
manga.Title.ShouldBe("Gal Can’t Be Kind to Otaku!?");
|
||||
manga.Title.Name.ShouldBe("Gal Can’t Be Kind to Otaku!?");
|
||||
|
||||
//manga.AlternateTitles.ShouldBe([
|
||||
// "Kaette kudasai! Akutsu-san",
|
||||
@@ -63,4 +60,9 @@ public class NatoMangaWebCrawlerTests
|
||||
//manga.Chapters[235].Views.ShouldBe(232_200);
|
||||
//manga.Chapters[235].UploadDate.ShouldBe(new DateTime(2021, 8, 24, 1, 8, 0));
|
||||
}
|
||||
|
||||
private static async Task<string> ReadJsonResourceAsync(string resourceName)
|
||||
{
|
||||
return await ResourceHelper.ReadJsonResourceAsync($"MangaReader.Tests.Sources.NatoManga.Metadata.{resourceName}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user