Files
Card-Collection-Manager-3/tests/domain_json_tests.cpp
T
2026-07-30 14:51:53 +02:00

904 lines
29 KiB
C++

#include <doctest/doctest.h>
#include "ccm/domain/Configuration.hpp"
#include "ccm/domain/DigiBattle99Card.hpp"
#include "ccm/domain/DigiBattle99SetCatalog.hpp"
#include "ccm/domain/PokemonSetCatalog.hpp"
#include "ccm/domain/YuGiOhSetCatalog.hpp"
#include "ccm/domain/Enums.hpp"
#include "ccm/domain/JapanesePokemonCard.hpp"
#include "ccm/domain/MagicCard.hpp"
#include "ccm/domain/PokemonCard.hpp"
#include "ccm/domain/YuGiOhBandaiCard.hpp"
#include "ccm/domain/YuGiOhBandaiSetCatalog.hpp"
#include "ccm/domain/YuGiOhCard.hpp"
#include "ccm/domain/Set.hpp"
#include <nlohmann/json.hpp>
using namespace ccm;
TEST_SUITE("domain enums round-trip JSON as strings") {
TEST_CASE("Game") {
nlohmann::json j = Game::Magic;
CHECK(j.get<std::string>() == "Magic");
CHECK(j.get<Game>() == Game::Magic);
nlohmann::json j2 = "Pokemon";
CHECK(j2.get<Game>() == Game::Pokemon);
nlohmann::json jYgo = "YuGiOh";
CHECK(jYgo.get<Game>() == Game::YuGiOh);
nlohmann::json jDigi = "DigiBattle99";
CHECK(jDigi.get<Game>() == Game::DigiBattle99);
nlohmann::json jBandai = "YuGiOhBandai";
CHECK(jBandai.get<Game>() == Game::YuGiOhBandai);
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);
}
TEST_CASE("Language and Condition") {
nlohmann::json l = Language::Japanese;
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() == 5);
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>());
}
TEST_CASE("all enum values round-trip through string helpers") {
for (const auto game : allGames()) {
const auto name = to_string(game);
CHECK(gameFromString(name).has_value());
CHECK(*gameFromString(name) == game);
}
for (const auto language : allLanguages()) {
const auto name = to_string(language);
CHECK(languageFromString(name).has_value());
CHECK(*languageFromString(name) == language);
}
for (const auto condition : allConditions()) {
const auto name = to_string(condition);
CHECK(conditionFromString(name).has_value());
CHECK(*conditionFromString(name) == condition);
}
for (const auto theme : allThemes()) {
const auto name = to_string(theme);
CHECK(themeFromString(name).has_value());
CHECK(*themeFromString(name) == theme);
}
}
TEST_CASE("invalid enum helper inputs return nullopt") {
CHECK_FALSE(gameFromString("magic").has_value());
CHECK_FALSE(languageFromString("EN").has_value());
CHECK_FALSE(conditionFromString("Near Mint").has_value());
CHECK_FALSE(themeFromString("OLED").has_value());
}
TEST_CASE("invalid game, condition and theme JSON values throw") {
nlohmann::json badGame = "YGO";
CHECK_THROWS(badGame.get<Game>());
nlohmann::json badCondition = "Pristine";
CHECK_THROWS(badCondition.get<Condition>());
nlohmann::json badTheme = "Midnight";
CHECK_THROWS(badTheme.get<Theme>());
}
}
TEST_SUITE("Set JSON shape stays stable") {
TEST_CASE("uses 'releaseDate' alias") {
Set s{"abc", "Test Set", "2024/05/01"};
const nlohmann::json j = s;
CHECK(j.contains("releaseDate"));
CHECK_FALSE(j.contains("release_date"));
CHECK(j.at("releaseDate") == "2024/05/01");
const Set back = j.get<Set>();
CHECK(back == s);
}
}
TEST_SUITE("MagicCard JSON") {
TEST_CASE("round-trips with all original field names") {
MagicCard c;
c.id = 42;
c.amount = 3;
c.name = "Lightning Bolt";
c.set = Set{"lea", "Limited Edition Alpha", "1993/08/05"};
c.note = "rare promo";
c.images = {"foo+bar+0.png"};
c.language = Language::English;
c.condition = Condition::NearMint;
c.foil = true;
c.signed_ = false;
c.altered = false;
nlohmann::json j = c;
CHECK(j.contains("signed"));
CHECK(j.at("signed") == false);
CHECK(j.at("foil") == true);
const MagicCard back = j.get<MagicCard>();
CHECK(back == c);
}
}
TEST_SUITE("PokemonCard JSON") {
TEST_CASE("uses 'setNo' and 'firstEdition' aliases") {
PokemonCard c;
c.id = 7;
c.amount = 1;
c.name = "Charizard";
c.set = Set{"base1", "Base Set", "1999/01/09"};
c.setNo = "4/102";
c.note = "";
c.images = {};
c.language = Language::English;
c.condition = Condition::Excellent;
c.firstEdition = true;
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_CASE("West load migrates legacy pokemontcg set ids to TCGdex EN") {
nlohmann::json j = {
{"id", 1},
{"amount", 1},
{"name", "Charizard"},
{"set", {{"id", "sv1"}, {"name", "Scarlet & Violet"}, {"releaseDate", "2023/03/31"}}},
{"setNo", "6"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "NearMint"},
{"firstEdition", false},
{"holo", false},
{"signed", false},
{"altered", false},
{"region", "West"},
};
const PokemonCard back = j.get<PokemonCard>();
CHECK(back.set.id == "sv01");
}
TEST_CASE("Asia load does not rewrite set ids through West aliases") {
nlohmann::json j = {
{"id", 1},
{"amount", 1},
{"name", "Charmander"},
{"set", {{"id", "sv1"}, {"name", "Keep Asia id"}, {"releaseDate", "2023/01/01"}}},
{"setNo", "001"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "Japanese"},
{"condition", "NearMint"},
{"firstEdition", false},
{"holo", false},
{"signed", false},
{"altered", false},
{"region", "Asia"},
};
const PokemonCard back = j.get<PokemonCard>();
CHECK(back.set.id == "sv1");
}
}
TEST_SUITE("DigiBattle99Card JSON") {
TEST_CASE("uses 'setNo' and 'firstEdition' aliases") {
DigiBattle99Card c;
c.id = 3;
c.amount = 2;
c.name = "Agumon";
c.set = Set{"series-1-starter-set", "Series 1 Starter Set", "1999/06/01"};
c.setNo = "ST-01";
c.note = "starter";
c.images = {"a.png"};
c.language = Language::English;
c.condition = Condition::NearMint;
c.firstEdition = false;
c.holo = true;
c.signed_ = true;
c.altered = false;
nlohmann::json j = c;
CHECK(j.at("setNo") == "ST-01");
CHECK(j.at("firstEdition") == false);
CHECK(j.at("holo") == true);
CHECK(j.at("signed") == true);
const DigiBattle99Card back = j.get<DigiBattle99Card>();
CHECK(back == c);
}
}
TEST_SUITE("DigiBattle99SetCatalog JSON") {
TEST_CASE("round-trips packs and setNo alias") {
DigiBattle99SetCatalog catalog;
DigiBattle99SetCatalogPack pack;
pack.setId = "series-1-starter-set";
pack.setName = "Series 1 Starter Set";
pack.cards.push_back(DigiBattle99CatalogCard{"ST-01", "Agumon"});
pack.cards.push_back(DigiBattle99CatalogCard{"ST-126", "Agumon"});
catalog.packs.push_back(std::move(pack));
nlohmann::json j = catalog;
CHECK(j.at("packs").is_array());
CHECK(j.at("packs").at(0).at("id") == "series-1-starter-set");
CHECK(j.at("packs").at(0).at("cards").at(0).at("setNo") == "ST-01");
const DigiBattle99SetCatalog back = j.get<DigiBattle99SetCatalog>();
CHECK(back == catalog);
CHECK(back.findPack("series-1-starter-set") != nullptr);
CHECK(back.findPack("missing") == nullptr);
}
}
TEST_SUITE("YuGiOhBandaiCard JSON") {
TEST_CASE("round-trips with setNo, rarity, holo and signed alias") {
YuGiOhBandaiCard c;
c.id = 14;
c.amount = 2;
c.name = "Dark Magician";
c.set = Set{"ban1", "1st Generation", "1998/09/01"};
c.setNo = "14";
c.rarity = "Rare";
c.note = "classic";
c.images = {"a.png"};
c.language = Language::Japanese;
c.condition = Condition::NearMint;
c.holo = true;
c.signed_ = true;
c.altered = false;
nlohmann::json j = c;
CHECK(j.at("setNo") == "14");
CHECK(j.at("rarity") == "Rare");
CHECK(j.at("holo") == true);
CHECK(j.at("signed") == true);
CHECK_FALSE(j.contains("firstEdition"));
const YuGiOhBandaiCard back = j.get<YuGiOhBandaiCard>();
CHECK(back == c);
}
TEST_CASE("missing each required key throws") {
const nlohmann::json full = {
{"id", 14},
{"amount", 1},
{"name", "Dark Magician"},
{"set", nlohmann::json{
{"id", "ban1"},
{"name", "1st Generation"},
{"releaseDate", "1998/09/01"},
}},
{"setNo", "14"},
{"rarity", "Rare"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "Japanese"},
{"condition", "NearMint"},
{"holo", false},
{"signed", false},
{"altered", false},
};
for (const char* key : {
"id", "amount", "name", "set", "setNo", "rarity", "note", "images",
"language", "condition", "holo", "signed", "altered"}) {
nlohmann::json partial = full;
partial.erase(key);
CHECK_THROWS(partial.get<YuGiOhBandaiCard>());
}
}
}
TEST_SUITE("YuGiOhBandaiSetCatalog JSON") {
TEST_CASE("round-trips packs with rarity") {
YuGiOhBandaiSetCatalog catalog;
YuGiOhBandaiSetCatalogPack pack;
pack.setId = "ban1";
pack.setName = "1st Generation";
pack.cards.push_back(YuGiOhBandaiCatalogCard{"14", "Dark Magician", "Rare"});
pack.cards.push_back(YuGiOhBandaiCatalogCard{"9", "Blue-Eyes White Dragon", "Super Rare"});
catalog.packs.push_back(std::move(pack));
nlohmann::json j = catalog;
CHECK(j.at("packs").at(0).at("id") == "ban1");
CHECK(j.at("packs").at(0).at("cards").at(0).at("setNo") == "14");
CHECK(j.at("packs").at(0).at("cards").at(0).at("rarity") == "Rare");
const YuGiOhBandaiSetCatalog back = j.get<YuGiOhBandaiSetCatalog>();
CHECK(back == catalog);
CHECK(back.findPack("ban1") != nullptr);
CHECK(back.findPack("missing") == nullptr);
}
}
TEST_SUITE("YuGiOhSetCatalog JSON") {
TEST_CASE("round-trips packs and setNo alias") {
YuGiOhSetCatalog catalog;
YuGiOhSetCatalogPack pack;
pack.setId = "LOB";
pack.setName = "Legend of Blue Eyes White Dragon";
pack.cards.push_back(YuGiOhCatalogCard{"LOB-001", "Blue-Eyes White Dragon"});
pack.cards.push_back(YuGiOhCatalogCard{"LOB-EN005", "Dark Magician"});
catalog.packs.push_back(std::move(pack));
nlohmann::json j = catalog;
CHECK(j.at("packs").is_array());
CHECK(j.at("packs").at(0).at("id") == "LOB");
CHECK(j.at("packs").at(0).at("cards").at(0).at("setNo") == "LOB-001");
const YuGiOhSetCatalog back = j.get<YuGiOhSetCatalog>();
CHECK(back == catalog);
CHECK(back.findPack("LOB") != nullptr);
CHECK(back.findPack("missing") == nullptr);
}
}
TEST_SUITE("PokemonSetCatalog JSON") {
TEST_CASE("round-trips packs and setNo alias") {
PokemonSetCatalog catalog;
PokemonSetCatalogPack pack;
pack.setId = "base1";
pack.setName = "Base";
pack.cards.push_back(PokemonCatalogCard{"4", "Charizard"});
pack.cards.push_back(PokemonCatalogCard{"58", "Growlithe"});
catalog.packs.push_back(std::move(pack));
nlohmann::json j = catalog;
CHECK(j.at("packs").is_array());
CHECK(j.at("packs").at(0).at("id") == "base1");
CHECK(j.at("packs").at(0).at("cards").at(0).at("setNo") == "4");
const PokemonSetCatalog back = j.get<PokemonSetCatalog>();
CHECK(back == catalog);
CHECK(back.findPack("base1") != nullptr);
CHECK(back.findPack("missing") == nullptr);
}
}
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;
cfg.dataStorage = "/some/path";
cfg.defaultGame = Game::Pokemon;
cfg.theme = Theme::Dark;
nlohmann::json j = cfg;
CHECK(j.at("dataStorage") == "/some/path");
CHECK(j.at("defaultGame") == "Pokemon");
CHECK(j.at("theme") == "Dark");
const auto back = j.get<Configuration>();
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"},
{"defaultGame", "YuGiOh"},
};
const auto cfg = j.get<Configuration>();
CHECK(cfg.dataStorage == "/portable/data");
CHECK(cfg.defaultGame == Game::YuGiOh);
CHECK(cfg.theme == Theme::Light);
}
}
TEST_SUITE("YuGiOhCard JSON") {
TEST_CASE("round-trips with setNo and rarity fields") {
YuGiOhCard c;
c.id = 77;
c.amount = 2;
c.name = "Blue-Eyes White Dragon";
c.set = Set{"SDK-001", "Starter Deck Kaiba", "2002/03/29"};
c.setNo = "SDK-001";
c.rarity = "Ultra Rare";
c.note = "classic";
c.images = {"77+starter+blue-eyes+0.png"};
c.language = Language::English;
c.condition = Condition::NearMint;
c.firstEdition = true;
c.signed_ = false;
c.altered = false;
nlohmann::json j = c;
CHECK(j.at("setNo") == "SDK-001");
CHECK(j.at("rarity") == "Ultra Rare");
CHECK_FALSE(j.contains("rarityCode"));
CHECK(j.at("signed") == false);
const YuGiOhCard back = j.get<YuGiOhCard>();
CHECK(back == c);
}
TEST_CASE("legacy JSON without rarityCode key parses (domain uses rarity only)") {
const nlohmann::json j = {
{"id", 1},
{"amount", 1},
{"name", "Dark Magician"},
{"set", nlohmann::json{
{"id", "SDY"},
{"name", "Starter Deck: Yugi"},
{"releaseDate", "2002/03/29"},
}},
{"setNo", "SDY-006"},
{"rarity", "Ultra Rare"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "NearMint"},
{"firstEdition", false},
{"signed", false},
{"altered", false},
};
const auto card = j.get<YuGiOhCard>();
CHECK(card.rarity == "Ultra Rare");
CHECK(card.setNo == "SDY-006");
CHECK(card.set.id == "SDY");
}
TEST_CASE("serializes non-default flags and metadata fields") {
YuGiOhCard c;
c.id = 3;
c.amount = 4;
c.name = "Red-Eyes Black Dragon";
c.set = Set{"lob", "Legend of Blue Eyes", "2002/03/08"};
c.setNo = "LOB-070";
c.rarity = "Secret Rare";
c.note = "graded";
c.images = {};
c.language = Language::German;
c.condition = Condition::Played;
c.firstEdition = false;
c.signed_ = true;
c.altered = true;
const nlohmann::json j = c;
CHECK(j.at("firstEdition") == false);
CHECK(j.at("signed") == true);
CHECK(j.at("altered") == true);
CHECK(j.at("language") == "German");
CHECK(j.at("condition") == "Played");
CHECK(j.at("images") == nlohmann::json::array());
const YuGiOhCard back = j.get<YuGiOhCard>();
CHECK(back == c);
}
TEST_CASE("operator== distinguishes each field") {
YuGiOhCard base;
base.id = 10;
base.amount = 2;
base.name = "Dark Magician";
base.set = Set{"lob", "Legend of Blue Eyes", "2002/03/08"};
base.setNo = "LOB-005";
base.rarity = "Ultra Rare";
base.note = "note";
base.images = {"a.png"};
base.language = Language::English;
base.condition = Condition::NearMint;
base.firstEdition = true;
base.signed_ = false;
base.altered = false;
auto changed = base;
changed.id = 11;
CHECK_FALSE(changed == base);
changed = base;
changed.amount = 3;
CHECK_FALSE(changed == base);
changed = base;
changed.name = "Other";
CHECK_FALSE(changed == base);
changed = base;
changed.set.name = "Other Set";
CHECK_FALSE(changed == base);
changed = base;
changed.setNo = "LOB-006";
CHECK_FALSE(changed == base);
changed = base;
changed.rarity = "Rare";
CHECK_FALSE(changed == base);
changed = base;
changed.note = "other";
CHECK_FALSE(changed == base);
changed = base;
changed.images = {};
CHECK_FALSE(changed == base);
changed = base;
changed.language = Language::Japanese;
CHECK_FALSE(changed == base);
changed = base;
changed.condition = Condition::Played;
CHECK_FALSE(changed == base);
changed = base;
changed.firstEdition = false;
CHECK_FALSE(changed == base);
changed = base;
changed.signed_ = true;
CHECK_FALSE(changed == base);
changed = base;
changed.altered = true;
CHECK_FALSE(changed == base);
}
}
TEST_SUITE("Domain JSON required fields") {
TEST_CASE("Set missing required key throws") {
const nlohmann::json j = {
{"id", "lea"},
{"name", "Limited Edition Alpha"},
};
CHECK_THROWS(j.get<Set>());
}
TEST_CASE("MagicCard missing required key throws") {
const nlohmann::json j = {
{"id", 10},
{"amount", 1},
{"name", "Lightning Bolt"},
{"set", nlohmann::json{
{"id", "lea"},
{"name", "Limited Edition Alpha"},
{"releaseDate", "1993/08/05"},
}},
// note missing on purpose
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "NearMint"},
{"foil", false},
{"signed", false},
{"altered", false},
};
CHECK_THROWS(j.get<MagicCard>());
}
TEST_CASE("PokemonCard missing required key throws") {
const nlohmann::json j = {
{"id", 7},
{"amount", 1},
{"name", "Charizard"},
{"set", nlohmann::json{
{"id", "base1"},
{"name", "Base Set"},
{"releaseDate", "1999/01/09"},
}},
{"setNo", "4/102"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "Excellent"},
{"firstEdition", true},
// holo missing on purpose
{"signed", false},
{"altered", false},
};
CHECK_THROWS(j.get<PokemonCard>());
}
TEST_CASE("YuGiOhCard missing required key throws") {
const nlohmann::json j = {
{"id", 7},
{"amount", 1},
{"name", "Blue-Eyes White Dragon"},
{"set", nlohmann::json{
{"id", "sdk"},
{"name", "Starter Deck Kaiba"},
{"releaseDate", "2002/03/29"},
}},
{"setNo", "SDK-001"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "NearMint"},
{"firstEdition", true},
// rarity missing on purpose
{"signed", false},
{"altered", false},
};
CHECK_THROWS(j.get<YuGiOhCard>());
}
TEST_CASE("YuGiOhCard missing each required key throws") {
const nlohmann::json full = {
{"id", 7},
{"amount", 1},
{"name", "Blue-Eyes White Dragon"},
{"set", nlohmann::json{
{"id", "sdk"},
{"name", "Starter Deck Kaiba"},
{"releaseDate", "2002/03/29"},
}},
{"setNo", "SDK-001"},
{"rarity", "Ultra Rare"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "NearMint"},
{"firstEdition", true},
{"signed", false},
{"altered", false},
};
for (const char* key : {
"id", "amount", "name", "set", "setNo", "note", "images",
"language", "condition", "firstEdition", "rarity", "signed", "altered"}) {
nlohmann::json partial = full;
partial.erase(key);
CHECK_THROWS(partial.get<YuGiOhCard>());
}
}
TEST_CASE("MagicCard missing each required key throws") {
const nlohmann::json full = {
{"id", 10},
{"amount", 1},
{"name", "Lightning Bolt"},
{"set", nlohmann::json{
{"id", "lea"},
{"name", "Limited Edition Alpha"},
{"releaseDate", "1993/08/05"},
}},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "NearMint"},
{"foil", false},
{"signed", false},
{"altered", false},
};
for (const char* key : {"id", "amount", "name", "set", "note", "images", "language",
"condition", "foil", "signed", "altered"}) {
nlohmann::json partial = full;
partial.erase(key);
CHECK_THROWS(partial.get<MagicCard>());
}
}
TEST_CASE("PokemonCard missing each required key throws") {
const nlohmann::json full = {
{"id", 7},
{"amount", 1},
{"name", "Charizard"},
{"set", nlohmann::json{
{"id", "base1"},
{"name", "Base Set"},
{"releaseDate", "1999/01/09"},
}},
{"setNo", "4/102"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "Excellent"},
{"firstEdition", true},
{"holo", true},
{"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<PokemonCard>());
}
}
TEST_CASE("DigiBattle99Card missing each required key throws") {
const nlohmann::json full = {
{"id", 3},
{"amount", 1},
{"name", "Agumon"},
{"set", nlohmann::json{
{"id", "series-1-starter-set"},
{"name", "Series 1 Starter Set"},
{"releaseDate", "1999/06/01"},
}},
{"setNo", "ST-01"},
{"note", ""},
{"images", nlohmann::json::array()},
{"language", "English"},
{"condition", "NearMint"},
{"firstEdition", false},
{"holo", true},
{"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<DigiBattle99Card>());
}
}
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"},
{"theme", "Dark"},
};
CHECK_THROWS(j.get<Configuration>());
}
TEST_CASE("Configuration invalid theme value throws when present") {
const nlohmann::json j = {
{"dataStorage", "/portable/data"},
{"defaultGame", "Magic"},
{"theme", "Neon"},
};
CHECK_THROWS(j.get<Configuration>());
}
}