mirror of
https://github.com/sebastiandine/Card-Collection-Manager-3.git
synced 2026-08-28 17:01:02 +00:00
d3b4762b76
* several functions. fixes #1 and #2 * multi selection functionality
270 lines
9.6 KiB
C++
270 lines
9.6 KiB
C++
#include "ccm/games/yugiohbandai/YuGiOhBandaiCardPreviewSource.hpp"
|
|
|
|
#include <doctest/doctest.h>
|
|
|
|
#include <string>
|
|
|
|
using namespace ccm;
|
|
|
|
namespace {
|
|
|
|
class FixedHttpClient final : public IHttpClient {
|
|
public:
|
|
std::string body;
|
|
std::string lastUrl;
|
|
bool fail{false};
|
|
|
|
Result<std::string> get(std::string_view url) override {
|
|
lastUrl = std::string(url);
|
|
if (fail) return Result<std::string>::err("http fail");
|
|
return Result<std::string>::ok(body);
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
TEST_SUITE("YuGiOhBandaiCardPreviewSource helpers") {
|
|
TEST_CASE("preferredPageTitle picks Bandai / English / Sealdass") {
|
|
CHECK(YuGiOhBandaiCardPreviewSource::preferredPageTitle("Dark Magician", "ban1", "14") ==
|
|
"Dark Magician (Bandai)");
|
|
CHECK(YuGiOhBandaiCardPreviewSource::preferredPageTitle("Blue-Eyes White Dragon", "ban3",
|
|
"118") ==
|
|
"Blue-Eyes White Dragon (English Bandai)");
|
|
CHECK(YuGiOhBandaiCardPreviewSource::preferredPageTitle("Dark Magician", "bansealdass",
|
|
"2") ==
|
|
"Dark Magician (Bandai Sealdass)");
|
|
}
|
|
|
|
TEST_CASE("buildPageImagesUrl encodes spaces as underscores then percent") {
|
|
const auto url =
|
|
YuGiOhBandaiCardPreviewSource::buildPageImagesUrl("Dark Magician (Bandai)");
|
|
CHECK(url.find("titles=Dark_Magician_%28Bandai%29") != std::string::npos);
|
|
}
|
|
|
|
TEST_CASE("buildAskByNameUrl includes English name constraint") {
|
|
const auto url = YuGiOhBandaiCardPreviewSource::buildAskByNameUrl("Dark Magician");
|
|
CHECK(url.find("action=ask") != std::string::npos);
|
|
CHECK(url.find("query=") != std::string::npos);
|
|
}
|
|
|
|
TEST_CASE("parsePageImagesResponse returns original source") {
|
|
const std::string body = R"JSON({
|
|
"query": {
|
|
"pages": {
|
|
"1": {
|
|
"title": "Dark Magician (Bandai)",
|
|
"original": {"source": "https://ms.yugipedia.com/d/d0/DarkMagician.png"}
|
|
}
|
|
}
|
|
}
|
|
})JSON";
|
|
auto out = YuGiOhBandaiCardPreviewSource::parsePageImagesResponse(body);
|
|
REQUIRE(out);
|
|
CHECK(out.value() == "https://ms.yugipedia.com/d/d0/DarkMagician.png");
|
|
}
|
|
|
|
TEST_CASE("parsePageImagesResponse missing page is NotFound") {
|
|
const std::string body = R"JSON({
|
|
"query": { "pages": { "-1": { "missing": true, "title": "Nope" } } }
|
|
})JSON";
|
|
auto out = YuGiOhBandaiCardPreviewSource::parsePageImagesResponse(body);
|
|
REQUIRE_FALSE(out);
|
|
CHECK(out.error().kind == PreviewLookupError::Kind::NotFound);
|
|
}
|
|
|
|
TEST_CASE("parseAskResponse fills setNo rarity name and setId") {
|
|
const std::string body = R"JSON({
|
|
"query": {
|
|
"results": {
|
|
"Dark Magician (Bandai)": {
|
|
"printouts": {
|
|
"English name": ["Dark Magician"],
|
|
"Bandai number": [14],
|
|
"Rarity": [{"fulltext": "Rare"}]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})JSON";
|
|
auto out = YuGiOhBandaiCardPreviewSource::parseAskResponse(body, "ban1");
|
|
REQUIRE(out);
|
|
REQUIRE(out.value().size() == 1);
|
|
CHECK(out.value()[0].name == "Dark Magician");
|
|
CHECK(out.value()[0].setNo == "14");
|
|
CHECK(out.value()[0].rarity == "Rare");
|
|
CHECK(out.value()[0].setId == "ban1");
|
|
CHECK(out.value()[0].language == "Japanese");
|
|
}
|
|
|
|
TEST_CASE("parseAskResponse prefers Bandai over Sealdass when set is ban1") {
|
|
const std::string body = R"JSON({
|
|
"query": {
|
|
"results": {
|
|
"Dark Magician (Bandai Sealdass)": {
|
|
"printouts": {
|
|
"English name": ["Dark Magician"],
|
|
"Bandai number": [2],
|
|
"Rarity": [{"fulltext": "Common"}]
|
|
}
|
|
},
|
|
"Dark Magician (Bandai)": {
|
|
"printouts": {
|
|
"English name": ["Dark Magician"],
|
|
"Bandai number": [14],
|
|
"Rarity": [{"fulltext": "Rare"}]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})JSON";
|
|
auto out = YuGiOhBandaiCardPreviewSource::parseAskResponse(body, "ban1");
|
|
REQUIRE(out);
|
|
REQUIRE(out.value().size() == 2);
|
|
CHECK(out.value()[0].setNo == "14");
|
|
CHECK(out.value()[0].setId == "ban1");
|
|
}
|
|
|
|
TEST_CASE("parseAskResponse drops results whose Bandai number does not match") {
|
|
const std::string body = R"JSON({
|
|
"query": {
|
|
"results": {
|
|
"Card Eleven (Bandai)": {
|
|
"printouts": {
|
|
"English name": ["Card Eleven"],
|
|
"Bandai number": [11],
|
|
"Rarity": [{"fulltext": "Common"}]
|
|
}
|
|
},
|
|
"Card One (Bandai)": {
|
|
"printouts": {
|
|
"English name": ["Card One"],
|
|
"Bandai number": [1],
|
|
"Rarity": [{"fulltext": "Common"}]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})JSON";
|
|
auto out = YuGiOhBandaiCardPreviewSource::parseAskResponse(body, "ban1", "1");
|
|
REQUIRE(out);
|
|
REQUIRE(out.value().size() == 1);
|
|
CHECK(out.value()[0].name == "Card One");
|
|
CHECK(out.value()[0].setNo == "1");
|
|
}
|
|
|
|
TEST_CASE("fetchImageUrl uses pageimages URL") {
|
|
FixedHttpClient http;
|
|
http.body = R"JSON({
|
|
"query": {
|
|
"pages": {
|
|
"1": {
|
|
"title": "Dark Magician (Bandai)",
|
|
"original": {"source": "https://ms.yugipedia.com/x.png"}
|
|
}
|
|
}
|
|
}
|
|
})JSON";
|
|
YuGiOhBandaiCardPreviewSource src(http);
|
|
auto out = src.fetchImageUrl("Dark Magician", "ban1", "14");
|
|
REQUIRE(out);
|
|
CHECK(out.value() == "https://ms.yugipedia.com/x.png");
|
|
CHECK(http.lastUrl.find("pageimages") != std::string::npos);
|
|
}
|
|
|
|
TEST_CASE("detectFirstPrint uses ask response") {
|
|
FixedHttpClient http;
|
|
http.body = R"JSON({
|
|
"query": {
|
|
"results": {
|
|
"Dark Magician (Bandai)": {
|
|
"printouts": {
|
|
"English name": ["Dark Magician"],
|
|
"Bandai number": [14],
|
|
"Rarity": [{"fulltext": "Rare"}]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})JSON";
|
|
YuGiOhBandaiCardPreviewSource src(http);
|
|
auto out = src.detectFirstPrint("Dark Magician", "ban1");
|
|
REQUIRE(out);
|
|
CHECK(out.value().setNo == "14");
|
|
CHECK(out.value().rarity == "Rare");
|
|
CHECK(out.value().setId == "ban1");
|
|
}
|
|
|
|
TEST_CASE("detectBySetNo uses ask-by-number URL") {
|
|
FixedHttpClient http;
|
|
http.body = R"JSON({
|
|
"query": {
|
|
"results": {
|
|
"Dark Magician (Bandai)": {
|
|
"printouts": {
|
|
"English name": ["Dark Magician"],
|
|
"Bandai number": [14],
|
|
"Rarity": [{"fulltext": "Rare"}]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})JSON";
|
|
YuGiOhBandaiCardPreviewSource src(http);
|
|
auto out = src.detectBySetNo("ban1", "014");
|
|
REQUIRE(out);
|
|
CHECK(out.value().name == "Dark Magician");
|
|
CHECK(http.lastUrl.find("action=ask") != std::string::npos);
|
|
}
|
|
|
|
TEST_CASE("detectBySetNo resolves promo TA2 from gallery parse") {
|
|
FixedHttpClient http;
|
|
http.body = R"JSON({
|
|
"parse": {
|
|
"wikitext": "WickedChain-BAN1-JP-SR.png | [[TA1]] ([[SR]]) {{Gallery card names|Wicked Chain|ja}}\nBlueEyesWhiteDragons3BodyConnection-BAN1-JP-SR.png | [[TA2]] ([[SR]])<br />{{Gallery card names|Blue-Eyes White Dragon's 3-Body Connection|ja}}\n"
|
|
}
|
|
})JSON";
|
|
YuGiOhBandaiCardPreviewSource src(http);
|
|
auto out = src.detectBySetNo("banpromo-ta", "ta2");
|
|
REQUIRE(out);
|
|
CHECK(out.value().name == "Blue-Eyes White Dragon's 3-Body Connection");
|
|
CHECK(out.value().setNo == "TA2");
|
|
CHECK(out.value().setId == "banpromo-ta");
|
|
CHECK(out.value().rarity == "Super Rare");
|
|
CHECK(http.lastUrl.find("action=parse") != std::string::npos);
|
|
CHECK(http.lastUrl.find("Promotional") != std::string::npos);
|
|
}
|
|
|
|
TEST_CASE("detectBySetNo filters out prints from other sets") {
|
|
FixedHttpClient http;
|
|
http.body = R"JSON({
|
|
"query": {
|
|
"results": {
|
|
"Dark Magician (Bandai)": {
|
|
"printouts": {
|
|
"English name": ["Dark Magician"],
|
|
"Bandai number": [14],
|
|
"Rarity": [{"fulltext": "Rare"}]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})JSON";
|
|
YuGiOhBandaiCardPreviewSource src(http);
|
|
auto out = src.detectBySetNo("bansealdass", "14");
|
|
CHECK_FALSE(out);
|
|
CHECK(out.error().find("selected set") != std::string::npos);
|
|
}
|
|
|
|
TEST_CASE("isAlphanumericPromoNumber detects Jump and Toei codes") {
|
|
CHECK(YuGiOhBandaiCardPreviewSource::isAlphanumericPromoNumber("TA2"));
|
|
CHECK(YuGiOhBandaiCardPreviewSource::isAlphanumericPromoNumber("j1"));
|
|
CHECK_FALSE(YuGiOhBandaiCardPreviewSource::isAlphanumericPromoNumber("14"));
|
|
}
|
|
|
|
TEST_CASE("preferredPageTitle omits Bandai suffix for promo sets") {
|
|
CHECK(YuGiOhBandaiCardPreviewSource::preferredPageTitle(
|
|
"Blue-Eyes White Dragon's 3-Body Connection", "banpromo-ta", "TA2") ==
|
|
"Blue-Eyes White Dragon's 3-Body Connection");
|
|
}
|
|
}
|