library(testthat) library(shiny) test_that("g6_proxy creation works correctly", { session <- list() class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_s3_class(proxy, "g6_proxy") expect_equal(proxy$id, "test_id") expect_equal(proxy$session, session) expect_error( g6_proxy("test_id", NULL), "g6_proxy must be called from the server function of a Shiny app" ) }) test_that("g6_data_proxy handles inputs correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) test_df <- data.frame(id = c("1", "2"), label = c("Node 1", "Node 2")) expect_error(g6_data_proxy(proxy, test_df, "add", "Node"), NA) expect_snapshot(error = TRUE, { g6_data_proxy(list(), test_df, "add", "Node") }) }) test_that("g6_add_nodes handles various input forms and flattening", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) nodes_df <- data.frame(id = c("1", "2")) expect_error(g6_add_nodes(proxy, nodes_df), NA) nodes_list <- list(list(id = "3"), list(id = "4")) expect_error(g6_add_nodes(proxy, nodes_list), NA) expect_error(g6_add_nodes(proxy, list(id = "5"), list(id = "6")), NA) expect_error( g6_add_nodes(proxy, list(list(list(id = "7")))), "Input is too deeply nested" ) expect_error( g6_add_nodes(proxy, g6_nodes(g6_node(id = "8"), g6_node(id = "9"))), NA ) expect_error(g6_add_nodes(proxy, g6_node(id = "10"), g6_node(id = "11")), NA) }) test_that("g6_remove_nodes works correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error(g6_remove_nodes(proxy, c("node1", "node2")), NA) }) test_that("g6_update_nodes works correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) update_df <- data.frame(id = "1") expect_error(g6_update_nodes(proxy, update_df), NA) }) test_that("g6_canvas_resize works correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error(g6_canvas_resize(proxy, 800, 600), NA) expect_error( g6_canvas_resize(list(), 800, 600), "Can't use g6_canvas_resize with g6 object" ) }) test_that("g6_fit_center works correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error(g6_fit_center(proxy), NA) animation <- list(duration = 300, easing = "ease-out") expect_error(g6_fit_center(proxy, animation), NA) expect_snapshot(error = TRUE, { g6_fit_center(proxy, "invalid") }) }) test_that("g6_focus_elements works correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error(g6_focus_elements(proxy, "node1"), NA) expect_error(g6_focus_elements(proxy, c("node1", "node2")), NA) animation <- list(duration = 300, easing = "ease-out") expect_error(g6_focus_elements(proxy, "node1", animation), NA) }) test_that("g6_hide_elements and g6_show_elements work correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error(g6_hide_elements(proxy, c("node1", "node2")), NA) expect_error(g6_show_elements(proxy, c("node1", "node2")), NA) }) test_that("g6_collapse_combo and g6_expand_combo work correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error(g6_collapse_combo(proxy, "combo1"), NA) expect_error(g6_expand_combo(proxy, "combo1"), NA) options <- list(animate = TRUE, align = TRUE) expect_error(g6_collapse_combo(proxy, "combo1", options), NA) expect_error(g6_expand_combo(proxy, "combo1", options), NA) }) test_that("g6_set_options works correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error( g6_set_options( proxy, fitView = TRUE, animate = TRUE, modes = list(default = list(type = "drag-canvas")) ), NA ) }) test_that("g6_add_plugin and g6_update_plugin work correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error( g6_add_plugin( proxy, minimap = list(size = list(width = 100, height = 100)) ), NA ) expect_error( g6_update_plugin( proxy, "minimap", size = list(width = 150, height = 150) ), NA ) }) test_that("g6_update_behavior works correctly", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error( g6_update_behavior( proxy, "drag-canvas", enableOptimize = TRUE ), NA ) }) test_that("g6_add_edges enforces source/target for creation", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) expect_error(g6_add_edges(proxy, list(source = "1", target = "2")), NA) edges_df <- data.frame(source = "1", target = "2") expect_error(g6_add_edges(proxy, edges_df), NA) }) test_that("as_g6_elements flattens any level of nesting and errors on excessive nesting", { expect_equal( flatten_g6_elements(list(list(source = 1, target = 2))), list(list(source = 1, target = 2)) ) expect_equal( flatten_g6_elements(list(list(list(source = 1, target = 2)))), list(list(source = 1, target = 2)) ) expect_error( as_g6_elements(list(list(list(list(id = "7")))), coerc_func = as_g6_nodes), "Input is too deeply nested" ) }) test_that("g6_update_layout proxy call works and errors on invalid proxy", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("test_id", session) # should not error for a valid proxy expect_error(g6_update_layout(proxy, type = "grid"), NA) # invalid proxy (not a g6_proxy) should error expect_error(g6_update_layout(list(), type = "grid")) }) test_that("g6_update_ports validates and sends correct structure", { session <- list( sendCustomMessage = function(type, message) { list(type = type, message = message) } ) class(session) <- "ShinySession" proxy <- g6_proxy("graph1", session) # Valid: add and remove expect_error( g6_update_ports( proxy, ops = list( A = list(add = g6_ports(g6_port("out1")), remove = c("in1")), B = list( update = g6_ports(g6_port("in2", label = "lbl")), remove = character() ) ) ), NA ) # Error: ops not a named list expect_error( g6_update_ports( proxy, ops = list(list(remove = "x")) ), "'ops' must be a named list" ) # Error: duplicate node IDs expect_error( g6_update_ports( proxy, ops = list(A = list(remove = "x"), A = list(remove = "y")) ), "Duplicate node IDs" ) # Error: remove not character expect_error( g6_update_ports( proxy, ops = list(A = list(remove = 123)) ), "remove' must be a character vector" ) # Error: add not valid ports expect_error( g6_update_ports( proxy, ops = list(A = list(add = list(list(type = "input")))) # missing key ), "key" ) }) test_that("g6_get_ports returns all ports grouped by node", { proxy <- structure( list( id = "graph1", session = list( ns = function(x = "") "", input = list( "graph1-state" = list( nodes = list( nodeA = list( style = list( ports = list( port1 = list(type = "input"), port2 = list(type = "output") ) ) ), nodeB = list( style = list( ports = list( port3 = list(type = "input") ) ) ) ) ) ) ) ), class = "g6_proxy" ) ports <- g6_get_ports(proxy) expect_type(ports, "list") expect_named(ports, c("nodeA", "nodeB")) expect_true(all(c("port1", "port2") %in% names(ports$nodeA))) expect_true("port3" %in% names(ports$nodeB)) }) test_that("g6_get_type_ports filters ports by type", { proxy <- structure( list( id = "graph1", session = list( ns = function(x = "") "", input = list( "graph1-state" = list( nodes = list( nodeA = list( style = list( ports = list( port1 = list(type = "input"), port2 = list(type = "output") ) ) ), nodeB = list( style = list( ports = list( port3 = list(type = "input") ) ) ) ) ) ) ) ), class = "g6_proxy" ) input_ports <- g6_get_input_ports(proxy) expect_true("port1" %in% names(input_ports$nodeA)) expect_false("port2" %in% names(input_ports$nodeA)) expect_true("port3" %in% names(input_ports$nodeB)) output_ports <- g6_get_output_ports(proxy) expect_true("port2" %in% names(output_ports$nodeA)) expect_false("port1" %in% names(output_ports$nodeA)) expect_length(output_ports$nodeB, 0) }) test_that("g6_get_ports returns empty list if no nodes", { proxy <- structure( list( id = "graph1", session = list( ns = function(x = "") "", input = list( "graph1-state" = list(nodes = NULL) ) ) ), class = "g6_proxy" ) ports <- g6_get_ports(proxy) expect_equal(ports, list()) }) test_that("g6_get_type_ports errors on invalid type", { proxy <- structure( list( id = "graph1", session = list( ns = function(x = "") "", input = list( "graph1-state" = list( nodes = list( nodeA = list( style = list( ports = list( port1 = list(type = "input") ) ) ) ) ) ) ) ), class = "g6_proxy" ) expect_error(g6_get_type_ports(proxy, "foo")) })