Minor: Add Asian Pokemon Card Support (#18)

This commit is contained in:
Sebastian Dine
2026-07-22 11:13:42 +02:00
committed by GitHub
parent e5c830e945
commit c9e6bc2b6b
87 changed files with 78068 additions and 162 deletions
+128
View File
@@ -3,6 +3,7 @@
#include "ccm/domain/Configuration.hpp"
#include "ccm/domain/DigiBattle99Card.hpp"
#include "ccm/domain/Enums.hpp"
#include "ccm/domain/JapanesePokemonCard.hpp"
#include "ccm/domain/MagicCard.hpp"
#include "ccm/domain/PokemonCard.hpp"
#include "ccm/domain/YuGiOhCard.hpp"
@@ -27,6 +28,9 @@ TEST_SUITE("domain enums round-trip JSON as strings") {
nlohmann::json jDigi = "DigiBattle99";
CHECK(jDigi.get<Game>() == Game::DigiBattle99);
nlohmann::json jJp = "JapanesePokemon";
CHECK(jJp.get<Game>() == Game::JapanesePokemon);
nlohmann::json j3 = Theme::Dark;
CHECK(j3.get<std::string>() == "Dark");
CHECK(j3.get<Theme>() == Theme::Dark);
@@ -37,11 +41,45 @@ TEST_SUITE("domain enums round-trip JSON as strings") {
CHECK(l.get<std::string>() == "Japanese");
CHECK(l.get<Language>() == Language::Japanese);
nlohmann::json k = Language::Korean;
CHECK(k.get<std::string>() == "Korean");
CHECK(k.get<Language>() == Language::Korean);
nlohmann::json sc = Language::SimplifiedChinese;
CHECK(sc.get<std::string>() == "S-Chinese");
CHECK(sc.get<Language>() == Language::SimplifiedChinese);
nlohmann::json tc = Language::TraditionalChinese;
CHECK(tc.get<std::string>() == "T-Chinese");
CHECK(tc.get<Language>() == Language::TraditionalChinese);
nlohmann::json legacyChinese = "Chinese";
CHECK(legacyChinese.get<Language>() == Language::SimplifiedChinese);
nlohmann::json c = Condition::LightPlayed;
CHECK(c.get<std::string>() == "LightPlayed");
CHECK(c.get<Condition>() == Condition::LightPlayed);
}
TEST_CASE("PokemonRegion") {
nlohmann::json j = PokemonRegion::Asia;
CHECK(j.get<std::string>() == "Asia");
CHECK(j.get<PokemonRegion>() == PokemonRegion::Asia);
nlohmann::json w = "West";
CHECK(w.get<PokemonRegion>() == PokemonRegion::West);
}
TEST_CASE("allGames excludes JapanesePokemon but string mapping remains") {
for (const auto game : allGames()) {
CHECK(game != Game::JapanesePokemon);
}
CHECK(allGames().size() == 4);
CHECK(gameFromString("JapanesePokemon") == Game::JapanesePokemon);
CHECK(pokemonBackendGame(PokemonRegion::West) == Game::Pokemon);
CHECK(pokemonBackendGame(PokemonRegion::Asia) == Game::JapanesePokemon);
}
TEST_CASE("invalid enum string throws") {
nlohmann::json bad = "Spanglish";
CHECK_THROWS(bad.get<Language>());
@@ -146,15 +184,37 @@ TEST_SUITE("PokemonCard JSON") {
c.holo = true;
c.signed_ = false;
c.altered = false;
c.region = PokemonRegion::West;
nlohmann::json j = c;
CHECK(j.at("setNo") == "4/102");
CHECK(j.at("firstEdition") == true);
CHECK(j.at("signed") == false);
CHECK(j.at("region") == "West");
const PokemonCard back = j.get<PokemonCard>();
CHECK(back == c);
}
TEST_CASE("region Asia round-trips and missing region defaults to West") {
PokemonCard c;
c.id = 1;
c.amount = 1;
c.name = "Charmander";
c.set = Set{"PMCG1", "Expansion Pack", "1996/10/20"};
c.setNo = "001";
c.language = Language::Japanese;
c.condition = Condition::NearMint;
c.region = PokemonRegion::Asia;
nlohmann::json j = c;
CHECK(j.at("region") == "Asia");
CHECK(j.get<PokemonCard>().region == PokemonRegion::Asia);
j.erase("region");
const PokemonCard legacy = j.get<PokemonCard>();
CHECK(legacy.region == PokemonRegion::West);
}
}
TEST_SUITE("DigiBattle99Card JSON") {
@@ -185,6 +245,34 @@ TEST_SUITE("DigiBattle99Card JSON") {
}
}
TEST_SUITE("JapanesePokemonCard JSON") {
TEST_CASE("uses 'setNo' and 'firstEdition' aliases") {
JapanesePokemonCard c;
c.id = 9;
c.amount = 1;
c.name = "Charmander";
c.set = Set{"PMCG1", "Expansion Pack", "1996/10/20"};
c.setNo = "001";
c.note = "";
c.images = {};
c.language = Language::Japanese;
c.condition = Condition::NearMint;
c.firstEdition = true;
c.holo = false;
c.signed_ = false;
c.altered = false;
nlohmann::json j = c;
CHECK(j.at("setNo") == "001");
CHECK(j.at("firstEdition") == true);
CHECK(j.at("signed") == false);
CHECK(j.at("language") == "Japanese");
const JapanesePokemonCard back = j.get<JapanesePokemonCard>();
CHECK(back == c);
}
}
TEST_SUITE("Configuration JSON matches Rust serde aliases") {
TEST_CASE("dataStorage / defaultGame / theme keys are present") {
Configuration cfg;
@@ -201,6 +289,16 @@ TEST_SUITE("Configuration JSON matches Rust serde aliases") {
CHECK(back == cfg);
}
TEST_CASE("legacy defaultGame JapanesePokemon coerces to Pokemon") {
nlohmann::json j = {
{"dataStorage", "/data"},
{"defaultGame", "JapanesePokemon"},
{"theme", "Light"},
};
const auto cfg = j.get<Configuration>();
CHECK(cfg.defaultGame == Game::Pokemon);
}
TEST_CASE("missing theme key defaults to Light") {
const nlohmann::json j = {
{"dataStorage", "/portable/data"},
@@ -559,6 +657,36 @@ TEST_SUITE("Domain JSON required fields") {
}
}
TEST_CASE("JapanesePokemonCard missing each required key throws") {
const nlohmann::json full = {
{"id", 9},
{"amount", 1},
{"name", "Charmander"},
{"set", nlohmann::json{
{"id", "PMCG1"},
{"name", "Expansion Pack"},
{"releaseDate", "1996/10/20"},
}},
{"setNo", "001"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "Japanese"},
{"condition", "NearMint"},
{"firstEdition", true},
{"holo", false},
{"signed", false},
{"altered", false},
};
for (const char* key :
{"id", "amount", "name", "set", "setNo", "note", "images", "language", "condition",
"firstEdition", "holo", "signed", "altered"}) {
nlohmann::json partial = full;
partial.erase(key);
CHECK_THROWS(partial.get<JapanesePokemonCard>());
}
}
TEST_CASE("Configuration missing required key throws") {
const nlohmann::json j = {
{"defaultGame", "Magic"},