// Tests para la logica de calculo del KPI card. // // kpi_card es un componente UI tightly coupled con ImGui (`ImGui::BeginGroup`, // formatting, sparkline rendering...). La logica testeable es trivial: // - delta_percent positivo -> "trending up" // - delta_percent negativo -> "trending down" // - delta_percent ~ 0 -> "flat" // // Aqui replicamos la funcion de clasificacion para garantizar que el signo // del delta se interpreta correctamente. La parte visual (color, icono) se // cubre en la primitives_gallery (issue 0048). #define CATCH_CONFIG_MAIN #include "catch_amalgamated.hpp" #include namespace { enum class Trend { Down, Flat, Up }; Trend classify_delta(float delta_percent, float flat_threshold = 0.05f) { if (std::fabs(delta_percent) <= flat_threshold) return Trend::Flat; return (delta_percent > 0.0f) ? Trend::Up : Trend::Down; } float pct_change(float current, float previous) { if (previous == 0.0f) return 0.0f; return 100.0f * (current - previous) / previous; } } // namespace TEST_CASE("kpi_card: classify_delta positive -> Up", "[kpi_card]") { REQUIRE(classify_delta(0.5f) == Trend::Up); REQUIRE(classify_delta(12.5f) == Trend::Up); REQUIRE(classify_delta(100.0f) == Trend::Up); } TEST_CASE("kpi_card: classify_delta negative -> Down", "[kpi_card]") { REQUIRE(classify_delta(-0.5f) == Trend::Down); REQUIRE(classify_delta(-15.0f) == Trend::Down); REQUIRE(classify_delta(-100.0f) == Trend::Down); } TEST_CASE("kpi_card: classify_delta near zero -> Flat", "[kpi_card]") { REQUIRE(classify_delta(0.0f) == Trend::Flat); REQUIRE(classify_delta(0.01f) == Trend::Flat); REQUIRE(classify_delta(-0.01f) == Trend::Flat); REQUIRE(classify_delta(0.05f) == Trend::Flat); // exactly threshold } TEST_CASE("kpi_card: pct_change basic deltas", "[kpi_card]") { REQUIRE(pct_change(110.0f, 100.0f) == Catch::Approx(10.0f)); REQUIRE(pct_change(90.0f, 100.0f) == Catch::Approx(-10.0f)); REQUIRE(pct_change(100.0f, 100.0f) == Catch::Approx(0.0f)); REQUIRE(pct_change(200.0f, 100.0f) == Catch::Approx(100.0f)); } TEST_CASE("kpi_card: pct_change with zero previous returns 0", "[kpi_card]") { // Definicion: cambio porcentual de 0 a X es indefinido, devolvemos 0. REQUIRE(pct_change(50.0f, 0.0f) == Catch::Approx(0.0f)); REQUIRE(pct_change(0.0f, 0.0f) == Catch::Approx(0.0f)); } TEST_CASE("kpi_card: pct_change handles negative values", "[kpi_card]") { // -10 -> -5: ((-5) - (-10)) / (-10) * 100 = 5 / -10 * 100 = -50%. REQUIRE(pct_change(-5.0f, -10.0f) == Catch::Approx(-50.0f)); }