docs(flows): DoD obligatorio con user-facing surface + abrir issues 0100-0103 (taxonomia, frontmatter migration, dev_console, work dashboard)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -145,7 +145,7 @@ endif()
|
||||
|
||||
# --- Issue 0081-B — compute_stage + compute_pipeline (TQL pure logic) -------
|
||||
# tql_helpers.cpp added (issue 0081-I): compute_stage.cpp now delegates
|
||||
# aggregation_alias to tql_helpers to avoid ODR conflict in fn_table_viz lib.
|
||||
# aggregation_alias to tql_helpers to avoid ODR conflict in fn_module_data_table lib.
|
||||
add_fn_test(test_compute_stage test_compute_stage.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../functions/core/compute_stage.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../functions/core/tql_helpers.cpp)
|
||||
@@ -214,32 +214,32 @@ target_include_directories(tql_apply_test PRIVATE
|
||||
target_link_libraries(tql_apply_test PRIVATE lua54)
|
||||
add_test(NAME tql_apply_test COMMAND tql_apply_test)
|
||||
|
||||
# --- Issue 0081-I — fn_table_viz static lib smoke test ---------------------
|
||||
# Linker test: verifies that all 9 registry .cpp files in fn_table_viz resolve
|
||||
# --- Issue 0081-I — fn_module_data_table static lib smoke test ---------------------
|
||||
# Linker test: verifies that all 9 registry .cpp files in fn_module_data_table resolve
|
||||
# symbols correctly when linked as a static lib. Does NOT call data_table::render
|
||||
# (requires ImGui context + playground headers). Uses its own main().
|
||||
if(TARGET fn_table_viz)
|
||||
if(TARGET fn_module_data_table)
|
||||
add_executable(test_fn_table_viz_smoke
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_fn_table_viz_smoke.cpp)
|
||||
target_include_directories(test_fn_table_viz_smoke PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../functions
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../vendor/imgui
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../vendor/implot)
|
||||
target_link_libraries(test_fn_table_viz_smoke PRIVATE fn_table_viz)
|
||||
target_link_libraries(test_fn_table_viz_smoke PRIVATE fn_module_data_table)
|
||||
add_test(NAME test_fn_table_viz_smoke COMMAND test_fn_table_viz_smoke)
|
||||
endif()
|
||||
|
||||
# --- Issue 0081-N — declarative CellRenderer (Badge/Progress/Duration/Icon) --
|
||||
# Smoke + back-compat tests for TableInput.column_specs (v1.1.0).
|
||||
# Verifies type construction + link resolution; does NOT call render() (ImGui).
|
||||
if(TARGET fn_table_viz)
|
||||
if(TARGET fn_module_data_table)
|
||||
add_executable(test_column_specs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_column_specs.cpp)
|
||||
target_include_directories(test_column_specs PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../functions
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../vendor/imgui
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../vendor/implot)
|
||||
target_link_libraries(test_column_specs PRIVATE fn_table_viz)
|
||||
target_link_libraries(test_column_specs PRIVATE fn_module_data_table)
|
||||
add_test(NAME test_column_specs COMMAND test_column_specs)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// test_column_specs.cpp — Smoke / back-compat tests for declarative cell renderers.
|
||||
// Issue 0081-N, v1.1.0. Phase 2 (issue 0081-O, v1.2.0).
|
||||
// Phase 2.5 (issue 0081-O.5, v1.3.0): Dots renderer.
|
||||
// v1.4.0: CategoricalChip + ColorScale renderers (TestCategoricalChipRule,
|
||||
// TestColorScaleLerpTwoStops, TestColorScaleLerpThreeStops,
|
||||
// TestColorScaleOutOfRange).
|
||||
//
|
||||
// These tests verify:
|
||||
// 1. TableInput without column_specs compiles and links (back-compat).
|
||||
@@ -9,6 +12,11 @@
|
||||
// 7. Tooltip field: ColumnSpec with tooltip_on_hover=true compiles and links.
|
||||
// 8. render() overload with events_out=nullptr back-compat (symbol resolution only).
|
||||
// 9. Dots renderer: ColumnSpec with CellRenderer::Dots + badges constructs correctly.
|
||||
// 10. Dots TQL roundtrip: State::aux_column_specs accepts Dots spec.
|
||||
// 11. TestCategoricalChipRule: ChipRule with match="success" produces correct color.
|
||||
// 12. TestColorScaleLerpTwoStops: t=0→first color, t=1→last color, t=0.5→midpoint.
|
||||
// 13. TestColorScaleLerpThreeStops: t=0.25 lies between stop0 and stop1.
|
||||
// 14. TestColorScaleOutOfRange: t<0 saturates at first; t>1 saturates at last.
|
||||
//
|
||||
// None of these tests call data_table::render() (requires ImGui context).
|
||||
// They only verify that the new types are usable and that the symbols from
|
||||
@@ -18,7 +26,7 @@
|
||||
// Run: ./cpp/build/linux/tests/test_column_specs
|
||||
|
||||
#include "core/data_table_types.h"
|
||||
#include "viz/data_table.h"
|
||||
#include "data_table/data_table.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
@@ -396,6 +404,206 @@ static void test_dots_tql_roundtrip() {
|
||||
"(State::aux_column_specs accepts Dots spec)\n");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test 11: TestCategoricalChipRule — ChipRule with match="success" correct color.
|
||||
// Verifies ChipRule struct construction + ColumnSpec.chips field accessible.
|
||||
// ---------------------------------------------------------------------------
|
||||
static void test_categorical_chip_rule() {
|
||||
ColumnSpec cs;
|
||||
cs.id = "state";
|
||||
cs.renderer = CellRenderer::CategoricalChip;
|
||||
cs.chips = {
|
||||
ChipRule{"success", "#22c55e"},
|
||||
ChipRule{"failure", "#ef4444"},
|
||||
ChipRule{"pending", "#f59e0b"},
|
||||
};
|
||||
|
||||
assert(cs.renderer == CellRenderer::CategoricalChip);
|
||||
assert(cs.chips.size() == 3);
|
||||
assert(cs.chips[0].match == "success");
|
||||
assert(cs.chips[0].color == "#22c55e");
|
||||
assert(cs.chips[1].match == "failure");
|
||||
assert(cs.chips[1].color == "#ef4444");
|
||||
assert(cs.chips[2].match == "pending");
|
||||
|
||||
// No matching rule for "unknown" — chips lookup returns nullptr (logic check).
|
||||
const ChipRule* found = nullptr;
|
||||
const char* test_val = "unknown";
|
||||
for (const auto& cr : cs.chips) {
|
||||
if (cr.match == test_val) { found = &cr; break; }
|
||||
}
|
||||
assert(found == nullptr && "no rule should match 'unknown'");
|
||||
|
||||
// Match "success" should find first rule.
|
||||
const ChipRule* found2 = nullptr;
|
||||
for (const auto& cr : cs.chips) {
|
||||
if (cr.match == std::string("success")) { found2 = &cr; break; }
|
||||
}
|
||||
assert(found2 != nullptr && found2->color == "#22c55e");
|
||||
|
||||
std::printf("PASS: TestCategoricalChipRule "
|
||||
"(3 chip rules, match/no-match logic correct)\n");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Headless color lerp helpers (mirrors the static functions in data_table.cpp,
|
||||
// replicated here so tests run without ImGui context).
|
||||
// Uses a plain struct RGB3 instead of std::tuple to avoid extra includes.
|
||||
// ---------------------------------------------------------------------------
|
||||
struct RGB3 { float r, g, b; };
|
||||
|
||||
static float lerp_f(float a, float b, float t) { return a + t * (b - a); }
|
||||
|
||||
// Parse "#rrggbb" -> RGB3 floats in [0,1]. Returns {-1,-1,-1} on failure.
|
||||
static RGB3 parse_rgb(const std::string& hex) {
|
||||
const char* p = hex.c_str();
|
||||
if (*p == '#') ++p;
|
||||
unsigned int r = 0, g = 0, b = 0;
|
||||
if (std::sscanf(p, "%02x%02x%02x", &r, &g, &b) != 3)
|
||||
return {-1.f, -1.f, -1.f};
|
||||
return {r / 255.f, g / 255.f, b / 255.f};
|
||||
}
|
||||
|
||||
// Lerp between two ColorStop RGB colors at a given global t.
|
||||
static RGB3 lerp_between(const ColorStop& lo, const ColorStop& hi, float t_global) {
|
||||
float span = hi.position - lo.position;
|
||||
float f = (span > 1e-6f) ? (t_global - lo.position) / span : 0.f;
|
||||
RGB3 ca = parse_rgb(lo.color);
|
||||
RGB3 cb = parse_rgb(hi.color);
|
||||
return {lerp_f(ca.r,cb.r,f), lerp_f(ca.g,cb.g,f), lerp_f(ca.b,cb.b,f)};
|
||||
}
|
||||
|
||||
// lerp_stops: full N-stop lerp (same logic as lerp_color_along_stops in data_table.cpp).
|
||||
static RGB3 lerp_stops(const std::vector<ColorStop>& stops, float t) {
|
||||
static const ColorStop kDefault[] = {
|
||||
{0.0f, "#22c55e"}, {0.5f, "#f59e0b"}, {1.0f, "#ef4444"}
|
||||
};
|
||||
static const int kDefaultN = 3;
|
||||
|
||||
// Build a working sorted copy.
|
||||
std::vector<ColorStop> s;
|
||||
if (stops.empty()) {
|
||||
for (int i = 0; i < kDefaultN; ++i) s.push_back(kDefault[i]);
|
||||
} else {
|
||||
s = stops;
|
||||
}
|
||||
// Simple insertion sort (N is tiny, avoids std::sort include).
|
||||
for (size_t i = 1; i < s.size(); ++i) {
|
||||
ColorStop key = s[i];
|
||||
int j = (int)i - 1;
|
||||
while (j >= 0 && s[j].position > key.position) { s[j+1] = s[j]; --j; }
|
||||
s[j+1] = key;
|
||||
}
|
||||
|
||||
t = t < 0.f ? 0.f : (t > 1.f ? 1.f : t);
|
||||
if (t <= s.front().position) return parse_rgb(s.front().color);
|
||||
if (t >= s.back().position) return parse_rgb(s.back().color);
|
||||
for (size_t i = 0; i + 1 < s.size(); ++i) {
|
||||
if (t >= s[i].position && t <= s[i+1].position)
|
||||
return lerp_between(s[i], s[i+1], t);
|
||||
}
|
||||
return parse_rgb(s.back().color);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test 12: TestColorScaleLerpTwoStops — t=0→first, t=1→last, t=0.5→midpoint.
|
||||
// ---------------------------------------------------------------------------
|
||||
static void test_color_scale_lerp_two_stops() {
|
||||
std::vector<ColorStop> stops = {
|
||||
{0.0f, "#000000"}, // black
|
||||
{1.0f, "#ffffff"}, // white
|
||||
};
|
||||
ColumnSpec cs;
|
||||
cs.renderer = CellRenderer::ColorScale;
|
||||
cs.range_min = 0.0;
|
||||
cs.range_max = 1.0;
|
||||
cs.range_stops = stops;
|
||||
cs.range_alpha = 0.25f;
|
||||
|
||||
assert(cs.renderer == CellRenderer::ColorScale);
|
||||
assert(cs.range_stops.size() == 2);
|
||||
|
||||
// t=0.0 → black (0,0,0)
|
||||
RGB3 c0 = lerp_stops(stops, 0.0f);
|
||||
assert(c0.r < 0.01f && c0.g < 0.01f && c0.b < 0.01f);
|
||||
|
||||
// t=1.0 → white (1,1,1)
|
||||
RGB3 c1 = lerp_stops(stops, 1.0f);
|
||||
assert(c1.r > 0.99f && c1.g > 0.99f && c1.b > 0.99f);
|
||||
|
||||
// t=0.5 → midpoint (0.5, 0.5, 0.5) within floating-point tolerance
|
||||
RGB3 c5 = lerp_stops(stops, 0.5f);
|
||||
assert(c5.r > 0.49f && c5.r < 0.51f);
|
||||
assert(c5.g > 0.49f && c5.g < 0.51f);
|
||||
assert(c5.b > 0.49f && c5.b < 0.51f);
|
||||
|
||||
std::printf("PASS: TestColorScaleLerpTwoStops "
|
||||
"(t=0→black, t=1→white, t=0.5→mid-grey)\n");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test 13: TestColorScaleLerpThreeStops — t=0.25 between stop0 and stop1.
|
||||
// Stops: {0.0,red}, {0.5,green}, {1.0,blue}.
|
||||
// At t=0.25 we expect halfway between red and green.
|
||||
// ---------------------------------------------------------------------------
|
||||
static void test_color_scale_lerp_three_stops() {
|
||||
// red=#ff0000, green=#00ff00, blue=#0000ff
|
||||
std::vector<ColorStop> stops = {
|
||||
{0.0f, "#ff0000"}, // red
|
||||
{0.5f, "#00ff00"}, // green
|
||||
{1.0f, "#0000ff"}, // blue
|
||||
};
|
||||
|
||||
// t=0.25 is halfway between stop0 (t=0) and stop1 (t=0.5).
|
||||
// Lerp factor f = (0.25 - 0.0) / (0.5 - 0.0) = 0.5.
|
||||
// Expected: R = lerp(1,0,0.5)=0.5, G = lerp(0,1,0.5)=0.5, B = lerp(0,0,0.5)=0.
|
||||
RGB3 ca = lerp_stops(stops, 0.25f);
|
||||
assert(ca.r > 0.49f && ca.r < 0.51f && "R should be ~0.5 at t=0.25");
|
||||
assert(ca.g > 0.49f && ca.g < 0.51f && "G should be ~0.5 at t=0.25");
|
||||
assert(ca.b < 0.01f && "B should be ~0 at t=0.25");
|
||||
|
||||
// t=0.75 is halfway between stop1 (t=0.5) and stop2 (t=1.0).
|
||||
// Expected: R=0, G=0.5, B=0.5.
|
||||
RGB3 cb = lerp_stops(stops, 0.75f);
|
||||
assert(cb.r < 0.01f && "R should be ~0 at t=0.75");
|
||||
assert(cb.g > 0.49f && cb.g < 0.51f && "G should be ~0.5 at t=0.75");
|
||||
assert(cb.b > 0.49f && cb.b < 0.51f && "B should be ~0.5 at t=0.75");
|
||||
|
||||
std::printf("PASS: TestColorScaleLerpThreeStops "
|
||||
"(t=0.25 between stop0/stop1, t=0.75 between stop1/stop2)\n");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test 14: TestColorScaleOutOfRange — t<0 saturates at first; t>1 at last.
|
||||
// ---------------------------------------------------------------------------
|
||||
static void test_color_scale_out_of_range() {
|
||||
std::vector<ColorStop> stops = {
|
||||
{0.0f, "#ff0000"}, // red at t=0
|
||||
{1.0f, "#0000ff"}, // blue at t=1
|
||||
};
|
||||
|
||||
// t=-0.5 → clamp to 0 → red
|
||||
RGB3 cu = lerp_stops(stops, -0.5f);
|
||||
assert(cu.r > 0.99f && "under-range should saturate at first stop (red)");
|
||||
assert(cu.b < 0.01f);
|
||||
|
||||
// t=1.5 → clamp to 1 → blue
|
||||
RGB3 co = lerp_stops(stops, 1.5f);
|
||||
assert(co.r < 0.01f && "over-range should saturate at last stop (blue)");
|
||||
assert(co.b > 0.99f);
|
||||
|
||||
// ColumnSpec struct fields accessible and defaults sensible.
|
||||
ColumnSpec cs;
|
||||
cs.renderer = CellRenderer::ColorScale;
|
||||
cs.range_min = -10.0;
|
||||
cs.range_max = 10.0;
|
||||
assert(cs.range_alpha == 0.25f && "default range_alpha should be 0.25");
|
||||
assert(cs.range_stops.empty() && "default range_stops should be empty (→ use default gradient)");
|
||||
|
||||
std::printf("PASS: TestColorScaleOutOfRange "
|
||||
"(t<0 saturates at first stop, t>1 saturates at last stop)\n");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// main
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -411,6 +619,10 @@ int main() {
|
||||
test_render_backcompat_overload();
|
||||
test_dots_column_spec();
|
||||
test_dots_tql_roundtrip();
|
||||
std::printf("=== ALL TESTS PASSED (10/10) ===\n");
|
||||
test_categorical_chip_rule();
|
||||
test_color_scale_lerp_two_stops();
|
||||
test_color_scale_lerp_three_stops();
|
||||
test_color_scale_out_of_range();
|
||||
std::printf("=== ALL TESTS PASSED (14/14) ===\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "core/auto_detect_type.h"
|
||||
#include "core/compute_column_stats.h"
|
||||
#include "viz/viz_render.h"
|
||||
#include "viz/data_table.h"
|
||||
#include "data_table/data_table.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
Reference in New Issue
Block a user