Added MangaDex cover art logic. Added "Search Manga" test for MangaDex client.

This commit is contained in:
2025-05-28 08:52:40 -04:00
parent 4e5be6c910
commit 1348684144
8 changed files with 362 additions and 5 deletions

View File

@@ -0,0 +1,216 @@
{
"result": "ok",
"response": "collection",
"data": [
{
"id": "0045f243-5625-4f0f-9066-a6c3a95d84d3",
"type": "cover_art",
"attributes": {
"description": "",
"volume": "1",
"fileName": "2569ffd8-4ba1-4030-8d08-b7a21333a7a6.jpg",
"locale": "ja",
"createdAt": "2024-06-18T14:42:11+00:00",
"updatedAt": "2024-06-18T14:42:11+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "f73d34f6-f678-4f8b-9dff-5c759d5fc767",
"type": "user"
}
]
},
{
"id": "a81ad8d3-ba2c-4003-9126-fbd9d28e3732",
"type": "cover_art",
"attributes": {
"description": "",
"volume": "2",
"fileName": "d2314e9b-4287-4e65-8045-b713d97c0b28.jpg",
"locale": "ja",
"createdAt": "2024-06-18T14:42:15+00:00",
"updatedAt": "2024-06-18T14:42:15+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "f73d34f6-f678-4f8b-9dff-5c759d5fc767",
"type": "user"
}
]
},
{
"id": "0ca43181-8ae1-4e5f-934f-4ea407e05913",
"type": "cover_art",
"attributes": {
"description": "",
"volume": "3",
"fileName": "ed4715de-fc1b-4f50-9e12-9d2ba99e044f.jpg",
"locale": "ja",
"createdAt": "2024-06-18T14:42:15+00:00",
"updatedAt": "2024-06-18T14:42:15+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "f73d34f6-f678-4f8b-9dff-5c759d5fc767",
"type": "user"
}
]
},
{
"id": "1dce1a43-86fb-4db6-86ca-fbc4b6c5cfab",
"type": "cover_art",
"attributes": {
"description": "",
"volume": "4",
"fileName": "b4c335cc-0e4d-4407-86ff-61e41f817e83.jpg",
"locale": "ja",
"createdAt": "2024-06-18T14:42:14+00:00",
"updatedAt": "2024-06-18T14:42:14+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "f73d34f6-f678-4f8b-9dff-5c759d5fc767",
"type": "user"
}
]
},
{
"id": "c8151575-1aac-4464-a99f-6cafa1f962c5",
"type": "cover_art",
"attributes": {
"description": "",
"volume": "5",
"fileName": "66323609-ba33-4ade-8c64-3b08c346e6da.jpg",
"locale": "ja",
"createdAt": "2024-06-18T14:42:11+00:00",
"updatedAt": "2024-06-18T14:42:11+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "f73d34f6-f678-4f8b-9dff-5c759d5fc767",
"type": "user"
}
]
},
{
"id": "dbac6a58-4d97-4ec9-85e3-fb4a4d904590",
"type": "cover_art",
"attributes": {
"description": "",
"volume": "6",
"fileName": "fc9d5eb5-3179-4543-ae6b-88d3231fca5b.jpg",
"locale": "ja",
"createdAt": "2024-06-18T14:42:15+00:00",
"updatedAt": "2024-06-18T14:42:15+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "f73d34f6-f678-4f8b-9dff-5c759d5fc767",
"type": "user"
}
]
},
{
"id": "d7158641-029d-4763-b621-fbdaa83ed3c4",
"type": "cover_art",
"attributes": {
"description": "",
"volume": "7",
"fileName": "61f990f0-103a-4967-ac64-01dc9938cb5c.jpg",
"locale": "ja",
"createdAt": "2024-06-18T14:42:12+00:00",
"updatedAt": "2024-06-18T14:42:12+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "f73d34f6-f678-4f8b-9dff-5c759d5fc767",
"type": "user"
}
]
},
{
"id": "9cbbbcfc-e82d-4c83-9d82-de692f52faf1",
"type": "cover_art",
"attributes": {
"description": "",
"volume": "8",
"fileName": "4b87e456-0243-4dfe-abda-d0f41c91141a.jpg",
"locale": "ja",
"createdAt": "2024-10-16T10:40:16+00:00",
"updatedAt": "2024-10-16T10:40:16+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "f73d34f6-f678-4f8b-9dff-5c759d5fc767",
"type": "user"
}
]
},
{
"id": "a06943fd-6309-49a8-a66a-8df0f6dc41eb",
"type": "cover_art",
"attributes": {
"description": "Volume 9 Cover from BookLive",
"volume": "9",
"fileName": "6b3073de-bb65-4723-8113-6068bf8c6eb4.jpg",
"locale": "ja",
"createdAt": "2025-02-20T11:59:45+00:00",
"updatedAt": "2025-02-20T11:59:45+00:00",
"version": 1
},
"relationships": [
{
"id": "ee96e2b7-9af2-4864-9656-649f4d3b6fec",
"type": "manga"
},
{
"id": "27bde0e8-71b0-4bf2-8e25-2902a7b2dd4b",
"type": "user"
}
]
}
],
"limit": 100,
"offset": 0,
"total": 9
}

View File

@@ -22,6 +22,52 @@ public class MangaDexClientTests
MangaDexResponse? mangaDexResponse = await mangaDexClient.SearchMangaByTitleAsync("Some random text", CancellationToken.None);
// Testing here
mangaDexResponse.ShouldNotBeNull();
mangaDexResponse.Response.ShouldBe("collection");
mangaDexResponse.ShouldBeOfType<MangaDexCollectionResponse>();
MangaDexCollectionResponse mangaDexCollectionResponse = (mangaDexResponse as MangaDexCollectionResponse)!;
mangaDexCollectionResponse.Data.Count.ShouldBe(3);
mangaDexCollectionResponse.Data[0].ShouldBeOfType<MangaEntity>();
MangaEntity mangaEntity = (mangaDexCollectionResponse.Data[0] as MangaEntity)!;
mangaEntity.Attributes.ShouldNotBeNull();
mangaEntity.Attributes.Title.ShouldContainKey("en");
mangaEntity.Attributes.Title["en"].ShouldBe("Gals Cant Be Kind to Otaku!?");
mangaEntity.Attributes.Description.ShouldContainKey("en");
mangaEntity.Attributes.Description["en"].ShouldBe("Takuya Seo is an otaku who likes \"anime for girls\" and can't say he likes it out loud. One day, he hooks up with two gals from his class, Amane and Ijichi, but it seems that Amane is also an otaku...");
mangaEntity.Attributes.Tags.Count.ShouldBe(5);
mangaEntity.Attributes.Tags[0].Attributes.ShouldNotBeNull();
mangaEntity.Attributes.Tags[0].Attributes!.Name.ShouldContainKey("en");
mangaEntity.Attributes.Tags[0].Attributes!.Name["en"].ShouldBe("Romance");
mangaEntity.Attributes.Tags[1].Attributes.ShouldNotBeNull();
mangaEntity.Attributes.Tags[1].Attributes!.Name.ShouldContainKey("en");
mangaEntity.Attributes.Tags[1].Attributes!.Name["en"].ShouldBe("Comedy");
mangaEntity.Attributes.Tags[2].Attributes.ShouldNotBeNull();
mangaEntity.Attributes.Tags[2].Attributes!.Name.ShouldContainKey("en");
mangaEntity.Attributes.Tags[2].Attributes!.Name["en"].ShouldBe("School Life");
mangaEntity.Attributes.Tags[3].Attributes.ShouldNotBeNull();
mangaEntity.Attributes.Tags[3].Attributes!.Name.ShouldContainKey("en");
mangaEntity.Attributes.Tags[3].Attributes!.Name["en"].ShouldBe("Slice of Life");
mangaEntity.Attributes.Tags[4].Attributes.ShouldNotBeNull();
mangaEntity.Attributes.Tags[4].Attributes!.Name.ShouldContainKey("en");
mangaEntity.Attributes.Tags[4].Attributes!.Name["en"].ShouldBe("Gyaru");
mangaEntity.Relationships.Count.ShouldBe(4);
mangaEntity.Relationships[2].ShouldBeOfType<CoverArtEntity>();
CoverArtEntity coverArtEntity = (mangaEntity.Relationships[2] as CoverArtEntity)!;
coverArtEntity.Attributes.ShouldNotBeNull();
coverArtEntity.Attributes.FileName.ShouldBe("6b3073de-bb65-4723-8113-6068bf8c6eb4.jpg");
}
[Fact]
@@ -154,6 +200,35 @@ public class MangaDexClientTests
mangaDexChapterResponse.Chapter.DataSaver[12].ShouldBe("13-b886b4ed986a473478e3db7bb18fe2faea567a1ad5e520408967410dcf8838d1.jpg");
}
[Fact]
public async Task Get_Cover_Art()
{
string searchResultJson = await ReadJsonResourceAsync("Manga-Cover-Art-Response.json");
IHttpService httpService = Substitute.For<IHttpService>();
httpService.GetStringAsync(Arg.Any<string>(), CancellationToken.None)
.Returns(Task.FromResult(searchResultJson));
MangaDexClient mangaDexClient = new(httpService);
MangaDexResponse? mangaDexResponse = await mangaDexClient.GetCoverArtAsync(Guid.NewGuid(), CancellationToken.None);
mangaDexResponse.ShouldNotBeNull();
mangaDexResponse.Response.ShouldBe("collection");
mangaDexResponse.ShouldBeOfType<MangaDexCollectionResponse>();
MangaDexCollectionResponse mangaDexEntityResponse = (mangaDexResponse as MangaDexCollectionResponse)!;
List<CoverArtEntity> coverArtEntities = [.. mangaDexEntityResponse.Data.Where(entity => entity is CoverArtEntity).Cast<CoverArtEntity>()];
coverArtEntities.Count.ShouldBe(9);
coverArtEntities[0].Attributes.ShouldNotBeNull();
coverArtEntities[0].Attributes!.FileName.ShouldBe("2569ffd8-4ba1-4030-8d08-b7a21333a7a6.jpg");
coverArtEntities[8].Attributes.ShouldNotBeNull();
coverArtEntities[8].Attributes!.FileName.ShouldBe("6b3073de-bb65-4723-8113-6068bf8c6eb4.jpg");
}
private static async Task<string> ReadJsonResourceAsync(string resourceName)
{
return await ResourceHelper.ReadJsonResourceAsync($"MangaReader.Tests.Sources.MangaDex.Api.{resourceName}");

View File

@@ -11,7 +11,7 @@ public class MangaDexMetadataTests
[Fact]
public async Task Get_Manga()
{
MangaDexEntityResponse entityResponse = new()
MangaDexEntityResponse mangaEntityResponse = new()
{
Result = "ok",
Response = "entity",
@@ -141,7 +141,7 @@ public class MangaDexMetadataTests
}
};
MangaDexCollectionResponse collectionResponse = new()
MangaDexCollectionResponse feedCollectionResponse = new()
{
Result = "ok",
Response = "collection",
@@ -186,13 +186,43 @@ public class MangaDexMetadataTests
]
};
MangaDexCollectionResponse coverArtCollectionResponse = new()
{
Result = "ok",
Response = "collection",
Data =
[
new CoverArtEntity()
{
Id = new Guid("0045f243-5625-4f0f-9066-a6c3a95d84d3"),
Type = "cover_art",
Attributes = new()
{
FileName = "2569ffd8-4ba1-4030-8d08-b7a21333a7a6.jpg"
}
},
new CoverArtEntity()
{
Id = new Guid("a81ad8d3-ba2c-4003-9126-fbd9d28e3732"),
Type = "cover_art",
Attributes = new()
{
FileName = "d2314e9b-4287-4e65-8045-b713d97c0b28.jpg"
}
}
]
};
IMangaDexClient mangaDexClient = Substitute.For<IMangaDexClient>();
mangaDexClient.GetMangaAsync(Arg.Any<Guid>(), CancellationToken.None)
.Returns(entityResponse);
.Returns(mangaEntityResponse);
mangaDexClient.GetFeedAsync(Arg.Any<Guid>(), CancellationToken.None)
.Returns(collectionResponse);
.Returns(feedCollectionResponse);
mangaDexClient.GetCoverArtAsync(Arg.Any<Guid>(), CancellationToken.None)
.Returns(coverArtCollectionResponse);
MangaDexMetadataProvider metadataProvider = new(mangaDexClient);
SourceManga? sourceManga = await metadataProvider.GetMangaAsync("https://mangadex.org/title/ee96e2b7-9af2-4864-9656-649f4d3b6fec/gals-can-t-be-kind-to-otaku", CancellationToken.None);
@@ -248,5 +278,9 @@ public class MangaDexMetadataTests
sourceManga.Chapters[2].Number.ShouldBe(8.1f);
sourceManga.Chapters[2].Title.ShouldBe("Otaku & Gyaru & Protegee");
sourceManga.Chapters[2].Url.ShouldBe("https://mangadex.org/chapter/b5206e9b-6e3e-4ef0-aa62-381fd0ff75a5");
sourceManga.CoverArt.Length.ShouldBe(2);
sourceManga.CoverArt[0].ShouldBe("https://mangadex.org/covers/ee96e2b7-9af2-4864-9656-649f4d3b6fec/2569ffd8-4ba1-4030-8d08-b7a21333a7a6.jpg");
sourceManga.CoverArt[1].ShouldBe("https://mangadex.org/covers/ee96e2b7-9af2-4864-9656-649f4d3b6fec/d2314e9b-4287-4e65-8045-b713d97c0b28.jpg");
}
}