mirror of
https://github.com/sebastiandine/Card-Collection-Manager-3.git
synced 2026-08-28 23:01:09 +00:00
904 lines
29 KiB
C++
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>());
|
|
}
|
|
}
|