// test_suite — smoke tests in-process sobre la API publica de data_table. // // Estos tests NO requieren imgui_test_engine. Solo verifican que las // estructuras se construyen, los enums son consistentes y los CellRenderer // configurados producen tablas con `column_specs` validos. // // Para tests UI-level con clicks reales: ver fase 2 del issue 0108 con // imgui_test_engine + FN_BUILD_TESTS=ON. #include "test_suite.h" #include "qa_state.h" #include "data_table/data_table.h" #include "core/data_table_types.h" #include "core/logger.h" namespace tables_qa { namespace { struct TestResult { const char* name; bool pass; }; #define TEST(NAME, EXPR) do { \ bool _ok = (EXPR); \ results.push_back({NAME, _ok}); \ if (!_ok) fn_log::log_warn("test failed: %s", NAME); \ else fn_log::log_info("test pass: %s", NAME); \ } while (0) } // anon bool run_test_suite() { fn_log::log_info("=== tables_qa: test suite start ==="); std::vector results; // --- Test 1: TableInput basic construction --- { data_table::TableInput tbl; tbl.name = "t1"; tbl.headers = {"a", "b"}; tbl.types = {data_table::ColumnType::Int, data_table::ColumnType::String}; tbl.rows = 0; tbl.cols = 2; TEST("TableInput construct", tbl.cols == 2 && tbl.headers.size() == 2); } // --- Test 2: ColumnSpec each renderer enum value --- { bool all_ok = true; for (int r = 0; r <= 10; r++) { if (r == 6 || r == 7) continue; // reserved data_table::ColumnSpec cs; cs.renderer = static_cast(r); cs.id = "col"; (void)cs; // construct OK } TEST("ColumnSpec enum construct", all_ok); } // --- Test 3: BadgeRule + ChipRule consistent --- { data_table::BadgeRule b{"ok", "#22c55e", "OK"}; data_table::ChipRule c{"ok", "#22c55e"}; TEST("BadgeRule fields", b.value == "ok" && b.color_hex == "#22c55e"); TEST("ChipRule fields", c.match == "ok" && c.color == "#22c55e"); } // --- Test 4: State default-constructible + persistent --- { data_table::State st1; data_table::State st2; // Different instances; no shared state contamination TEST("State default construct", true); (void)st1; (void)st2; } // --- Test 5: TableEvent enums --- { data_table::TableEvent ev; ev.kind = data_table::TableEventKind::ButtonClick; ev.action_id = "test"; TEST("TableEvent ButtonClick", ev.kind == data_table::TableEventKind::ButtonClick); } // --- Test 6: ColorScale config plausible --- { data_table::ColumnSpec cs; cs.renderer = data_table::CellRenderer::ColorScale; cs.range_min = 0.0; cs.range_max = 100.0; cs.range_alpha = 0.25f; TEST("ColorScale spec", cs.range_max > cs.range_min); } // --- Test 7: Duration thresholds order --- { data_table::ColumnSpec cs; cs.renderer = data_table::CellRenderer::Duration; cs.duration_warn_ms = 1000.0f; cs.duration_error_ms = 5000.0f; TEST("Duration thresholds", cs.duration_warn_ms < cs.duration_error_ms); } // --- Test 8: Button action_id non-empty when renderer Button --- { data_table::ColumnSpec cs; cs.renderer = data_table::CellRenderer::Button; cs.button_action = "retry"; cs.button_label = "Retry"; TEST("Button setup", !cs.button_action.empty()); } // --- Test 9: Multiple TableInputs in single render call (joins setup) --- { data_table::TableInput main_t, lookup_t; main_t.name = "main"; main_t.cols = 2; main_t.rows = 0; lookup_t.name = "lookup"; lookup_t.cols = 2; lookup_t.rows = 0; std::vector tables = {main_t, lookup_t}; TEST("Multi-table input", tables.size() == 2); } // --- Test 10: ColorStop ordering --- { std::vector stops = { {0.0f, "#22c55e"}, {0.5f, "#f59e0b"}, {1.0f, "#ef4444"}, }; TEST("ColorStop ordering", stops[0].position < stops[1].position && stops[1].position < stops[2].position); } int total = (int)results.size(); int passed = 0, failed = 0; for (const auto& r : results) { if (r.pass) passed++; else failed++; } auto& c = qa::counters(); c.last_test_total = total; c.last_test_passed = passed; c.last_test_failed = failed; fn_log::log_info("=== test suite done: %d/%d pass, %d failed ===", passed, total, failed); return failed == 0; } } // namespace tables_qa