// Smoke tests for graph_viewport (issue 0049i). // El widget completo necesita un contexto OpenGL + ImGui — eso vive en el // demo y en el test visual. Aqui solo cubrimos los helpers de seleccion // (logica pura sobre GraphData / GraphViewportState) que no dependen de GL // ni de ImGui frame state. #define CATCH_CONFIG_MAIN #include "catch_amalgamated.hpp" #include "viz/graph_viewport.h" #include "viz/graph_types.h" #include namespace { struct TG { std::vector nodes; GraphData data{}; void make(int N) { nodes.clear(); for (int i = 0; i < N; ++i) nodes.push_back(graph_node()); data.nodes = nodes.data(); data.node_count = (int)nodes.size(); data.node_capacity = (int)nodes.capacity(); data.edges = nullptr; data.edge_count = 0; data.edge_capacity = 0; data.types = nullptr; data.type_count = 0; data.rel_types = nullptr; data.rel_type_count = 0; } }; } // namespace TEST_CASE("selection: add sets NF_SELECTED and selected_node", "[viewport][selection]") { TG g; g.make(5); GraphViewportState st; graph_viewport_add_to_selection(g.data, st, 2); REQUIRE(st.selection.size() == 1); REQUIRE(st.selection[0] == 2); REQUIRE(st.selected_node == 2); REQUIRE((g.nodes[2].flags & NF_SELECTED) != 0); // Anadir el mismo no duplica graph_viewport_add_to_selection(g.data, st, 2); REQUIRE(st.selection.size() == 1); graph_viewport_add_to_selection(g.data, st, 4); REQUIRE(st.selection.size() == 2); REQUIRE(st.selected_node == 4); } TEST_CASE("selection: clear unsets all NF_SELECTED", "[viewport][selection]") { TG g; g.make(3); GraphViewportState st; graph_viewport_add_to_selection(g.data, st, 0); graph_viewport_add_to_selection(g.data, st, 1); graph_viewport_add_to_selection(g.data, st, 2); graph_viewport_clear_selection(g.data, st); REQUIRE(st.selection.empty()); REQUIRE(st.selected_node == -1); for (int i = 0; i < 3; ++i) { REQUIRE((g.nodes[i].flags & NF_SELECTED) == 0); } } TEST_CASE("selection: toggle adds then removes", "[viewport][selection]") { TG g; g.make(3); GraphViewportState st; graph_viewport_toggle_selection(g.data, st, 1); REQUIRE(graph_viewport_is_selected(st, 1)); REQUIRE((g.nodes[1].flags & NF_SELECTED) != 0); graph_viewport_toggle_selection(g.data, st, 1); REQUIRE_FALSE(graph_viewport_is_selected(st, 1)); REQUIRE((g.nodes[1].flags & NF_SELECTED) == 0); REQUIRE(st.selected_node == -1); } TEST_CASE("selection: out-of-range indices are ignored", "[viewport][selection]") { TG g; g.make(2); GraphViewportState st; graph_viewport_add_to_selection(g.data, st, -1); graph_viewport_add_to_selection(g.data, st, 5); graph_viewport_toggle_selection(g.data, st, -3); REQUIRE(st.selection.empty()); REQUIRE(st.selected_node == -1); } TEST_CASE("selection: is_selected reports membership", "[viewport][selection]") { TG g; g.make(4); GraphViewportState st; graph_viewport_add_to_selection(g.data, st, 0); graph_viewport_add_to_selection(g.data, st, 3); REQUIRE(graph_viewport_is_selected(st, 0)); REQUIRE_FALSE(graph_viewport_is_selected(st, 1)); REQUIRE_FALSE(graph_viewport_is_selected(st, 2)); REQUIRE(graph_viewport_is_selected(st, 3)); }