Files
fn_registry/cpp/tests/test_viz_render.cpp
T
egutierrez a03675113a chore: auto-commit (286 archivos)
- .claude/agents/fn-orquestador/SKILL.md
- .claude/commands/fn_claude.md
- .claude/rules/INDEX.md
- .claude/rules/cpp_apps.md
- .claude/rules/ids_naming.md
- CHANGELOG.md
- apps/dag_engine/README.md
- apps/dag_engine/api.go
- apps/dag_engine/dags_migrated/example.yaml
- apps/dag_engine/dags_migrated/example_lineage_tracking.yaml
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 16:33:22 +02:00

187 lines
6.2 KiB
C++

// Tests parciales para viz::render (cpp/functions/viz/viz_render.cpp).
//
// render() requiere un contexto ImGui + ImPlot vivo — no se puede ejercitar
// en tests headless. Este archivo cubre SOLO las funciones helper publicas
// (first_numeric_col, first_category_col, extract_numeric, extract_category)
// que son logica pura sin dependencia de ImGui/ImPlot.
//
// Smoke real del dispatcher: primitives_gallery --capture (golden images, issue 0048).
// Issue 0081-G.
#define CATCH_CONFIG_MAIN
#include "catch_amalgamated.hpp"
// Incluir solo el header de tipos (no ImGui, no ImPlot) para construir
// StageOutput de prueba.
#include "core/data_table_types.h"
// Declaraciones adelantadas de los helpers publicos (evita incluir viz_render.h
// que arrastra imgui.h). Replicar aqui es legal para tests headless.
#include <cmath>
#include <string>
#include <vector>
namespace data_table { struct StageOutput; }
// Incluir la implementacion completa via el .h para obtener las firmas
// publicas. viz_render.h incluye imgui.h, que en tests sin contexto GLFW
// es solo tipos — safe para compilar (no linkamos fn_framework aqui).
//
// Para evitar el pull-in de imgui.h (que necesita GLFW o al menos el stub),
// re-declaramos solo las funciones helper que necesitamos testear.
// Las implementaciones estan en viz_render.cpp que linkamos directamente.
namespace viz {
int first_numeric_col(const data_table::StageOutput& out);
int first_category_col(const data_table::StageOutput& out);
std::vector<double> extract_numeric(const data_table::StageOutput& out, int col);
std::vector<std::string> extract_category(const data_table::StageOutput& out, int col);
} // namespace viz
using namespace data_table;
// ---------------------------------------------------------------------------
// Helper: construir un StageOutput simple para tests
// ---------------------------------------------------------------------------
namespace {
struct TestTable {
std::vector<std::string> backing;
std::vector<const char*> cells;
std::vector<std::string> headers;
std::vector<ColumnType> types;
int rows = 0, cols = 0;
void add_row(std::initializer_list<const char*> row) {
for (const char* s : row) backing.emplace_back(s ? s : "");
++rows;
}
StageOutput build() {
StageOutput out;
cols = (int)headers.size();
cells.clear();
for (const auto& s : backing) cells.push_back(s.c_str());
out.headers = headers;
out.types = types;
out.rows = rows;
out.cols = cols;
out.cells = cells;
return out;
}
};
} // anon
// ---------------------------------------------------------------------------
// first_numeric_col
// ---------------------------------------------------------------------------
TEST_CASE("first_numeric_col returns -1 on empty output", "[viz_render]") {
StageOutput out;
REQUIRE(viz::first_numeric_col(out) == -1);
}
TEST_CASE("first_numeric_col returns 0 for all-numeric output", "[viz_render]") {
TestTable t;
t.headers = {"a", "b"};
t.types = {ColumnType::Float, ColumnType::Int};
t.add_row({"1.0", "2"});
auto out = t.build();
REQUIRE(viz::first_numeric_col(out) == 0);
}
TEST_CASE("first_numeric_col skips string columns", "[viz_render]") {
TestTable t;
t.headers = {"cat", "val"};
t.types = {ColumnType::String, ColumnType::Float};
t.add_row({"alfa", "3.14"});
auto out = t.build();
// Primera col es String -> primera numerica es col 1
REQUIRE(viz::first_numeric_col(out) == 1);
}
// ---------------------------------------------------------------------------
// first_category_col
// ---------------------------------------------------------------------------
TEST_CASE("first_category_col returns -1 on all-numeric output", "[viz_render]") {
TestTable t;
t.headers = {"x", "y"};
t.types = {ColumnType::Int, ColumnType::Float};
t.add_row({"1", "2.0"});
auto out = t.build();
REQUIRE(viz::first_category_col(out) == -1);
}
TEST_CASE("first_category_col returns first string column", "[viz_render]") {
TestTable t;
t.headers = {"num", "cat"};
t.types = {ColumnType::Int, ColumnType::String};
t.add_row({"42", "hello"});
auto out = t.build();
REQUIRE(viz::first_category_col(out) == 1);
}
// ---------------------------------------------------------------------------
// extract_numeric
// ---------------------------------------------------------------------------
TEST_CASE("extract_numeric returns empty for out-of-range col", "[viz_render]") {
TestTable t;
t.headers = {"x"};
t.types = {ColumnType::Float};
t.add_row({"1.5"});
auto out = t.build();
// col -1
REQUIRE(viz::extract_numeric(out, -1).empty());
// col >= cols
REQUIRE(viz::extract_numeric(out, 5).empty());
}
TEST_CASE("extract_numeric returns NaN for unparseable cells", "[viz_render]") {
TestTable t;
t.headers = {"val"};
t.types = {ColumnType::String};
t.add_row({"abc"});
t.add_row({"3.14"});
t.add_row({""});
auto out = t.build();
auto v = viz::extract_numeric(out, 0);
REQUIRE(v.size() == 3);
REQUIRE(std::isnan(v[0]));
REQUIRE(!std::isnan(v[1]));
REQUIRE(std::abs(v[1] - 3.14) < 1e-9);
REQUIRE(std::isnan(v[2]));
}
// ---------------------------------------------------------------------------
// extract_category
// ---------------------------------------------------------------------------
TEST_CASE("extract_category returns empty for out-of-range col", "[viz_render]") {
TestTable t;
t.headers = {"s"};
t.types = {ColumnType::String};
t.add_row({"hello"});
auto out = t.build();
REQUIRE(viz::extract_category(out, -1).empty());
REQUIRE(viz::extract_category(out, 10).empty());
}
TEST_CASE("extract_category returns empty strings for null cells", "[viz_render]") {
// Construimos un StageOutput con un cell ptr nulo manualmente
StageOutput out;
out.headers = {"s"};
out.types = {ColumnType::String};
out.rows = 2;
out.cols = 1;
// cell[0] = nullptr, cell[1] = "hello"
static const char* hello = "hello";
out.cells = {nullptr, hello};
auto v = viz::extract_category(out, 0);
REQUIRE(v.size() == 2);
REQUIRE(v[0].empty());
REQUIRE(v[1] == "hello");
}