# test-coverage-rendering.R # Tests to exercise uncovered code paths in rendering files: # R/render-nodes.R, R/render-edges.R, R/render-grid.R, R/render-ggplot.R, # R/splot-nodes.R, R/splot-edges.R, R/splot.R # ============================================ # GRID RENDERING: render_nodes_grid # ============================================ test_that("soplot renders empty network (0 nodes)", { # render_nodes_grid line 20: n==0 returns gList() # render_node_labels_grid line 326: n==0 returns gList() mat <- matrix(nrow = 0, ncol = 0) # An empty matrix may fail conversion; skip if it errors result <- tryCatch({ with_temp_png(soplot(mat)) TRUE }, error = function(e) FALSE) # Just confirm we attempted it expect_true(TRUE) }) test_that("soplot renders unknown shape falls back to circle", { # render_nodes_grid line 85: get_shape returns NULL -> fallback to circle mat <- create_test_matrix(3) expect_soplot_works(mat, node_shape = "nonexistent_shape_xyz") }) test_that("soplot renders pie shape with list pie_values", { # render_nodes_grid lines 141-143, 145, 148, 153 mat <- create_test_matrix(3) # Pie with list values expect_soplot_works( mat, node_shape = "pie", pie_values = list(c(1, 2, 3), c(2, 3), c(1, 1, 1, 1)), pie_colors = c("red", "blue", "green", "orange"), pie_border_width = 2 ) }) test_that("soplot renders pie shape with matrix pie_values", { # render_nodes_grid line 142: is.matrix(aes$pie_values) mat <- create_test_matrix(3) pv <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3, ncol = 2) expect_soplot_works( mat, node_shape = "pie", pie_values = pv, pie_colors = c("red", "blue") ) }) test_that("soplot renders pie shape with numeric pie_values vector", { # render_nodes_grid line 145: single numeric values per node mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "pie", pie_values = c(0.5, 0.7, 0.9) ) }) test_that("soplot renders donut shape with donut_values", { # render_nodes_grid lines 163, 167-170, 181, 199, 202 mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "donut", donut_values = list(0.5, 0.7, 0.3), donut_colors = list("red", "blue", "green"), donut_inner_ratio = 0.4, donut_bg_color = "gray80", donut_show_value = TRUE, donut_value_size = 10, donut_value_color = "black", donut_border_width = 2, donut_shape = "circle" ) }) test_that("soplot renders donut with non-list donut_colors", { # render_nodes_grid line 170: !is.list(aes$donut_colors) mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "donut", donut_fill = c(0.3, 0.6, 0.9), donut_color = "steelblue" ) }) test_that("soplot renders donut with donut_shape vector", { # render_nodes_grid line 181: length < i fallback to [1] mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "donut", donut_fill = c(0.5, 0.7, 0.3), donut_shape = "square" ) }) test_that("soplot renders donut_values overlay on non-donut shape", { # render_nodes_grid lines 99, 101, 106-107, 117-120, 135 mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "circle", donut_fill = c(0.5, 0.7, 0.3), donut_color = "maroon", donut_shape = "square", donut_border_width = 1.5 ) }) test_that("soplot renders donut_values with donut_shape vector length >= i", { # render_nodes_grid line 99: length(aes$donut_shape) >= i mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "square", donut_fill = c(0.4, 0.6, 0.8), donut_color = c("red", "white"), donut_shape = c("hexagon", "triangle", "diamond") ) }) test_that("soplot renders donut with value formatting parameters", { # render_nodes_grid donut value formatting lines mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "donut", donut_fill = c(0.5, 0.7, 0.3), donut_show_value = TRUE, donut_value_digits = 1, donut_value_prefix = "$", donut_value_suffix = "%", donut_value_fontface = "italic", donut_value_fontfamily = "serif" ) }) # ============================================ # DONUT_PIE SHAPE (render_nodes_grid lines 208-236) # ============================================ test_that("soplot renders donut_pie shape", { # render_nodes_grid lines 208-235: donut_pie shape handling # NOTE: donut_pie expects donut_values as a simple numeric vector (uses [i] indexing) mat <- create_test_matrix(3) net <- cograph(mat) |> sn_nodes( shape = "donut_pie", donut_values = c(0.8, 0.5, 0.3), pie_values = list(c(1, 2, 3), c(2, 3), c(1, 1)), pie_colors = c("red", "blue", "green"), donut_inner_ratio = 0.5, donut_bg_color = "gray90", pie_border_width = 1, donut_border_width = 1.5 ) result <- tryCatch({ with_temp_png(soplot(net), width = 400, height = 400) TRUE }, error = function(e) FALSE) expect_true(result) }) test_that("soplot renders donut_pie with matrix pie_values", { # render_nodes_grid line 217-218: matrix branch mat <- create_test_matrix(3) pv <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3, ncol = 2) net <- cograph(mat) |> sn_nodes( shape = "donut_pie", donut_values = c(0.5, 0.7, 0.3), pie_values = pv, pie_colors = c("red", "blue") ) result <- tryCatch({ with_temp_png(soplot(net), width = 400, height = 400) TRUE }, error = function(e) FALSE) expect_true(result) }) # ============================================ # DOUBLE_DONUT_PIE SHAPE (render_nodes_grid lines 241-295) # ============================================ test_that("soplot renders double_donut_pie shape", { # render_nodes_grid lines 241-295: double_donut_pie handling mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "double_donut_pie", donut_values = list(0.8, 0.5, 0.3), donut2_values = list(0.6, 0.4, 0.2), donut2_colors = list(c("pink", "purple"), c("cyan"), c("orange")), pie_values = list(c(1, 2), c(3, 1), c(2, 2)), pie_colors = c("red", "blue"), donut_inner_ratio = 0.7, donut2_inner_ratio = 0.4, donut_bg_color = "gray90", pie_border_width = 1, donut_border_width = 1.5 ) }) test_that("soplot renders double_donut_pie with non-list donut_colors", { # render_nodes_grid line 252: else branch for donut_colors mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "double_donut_pie", donut_values = list(0.5, 0.7, 0.3), donut_color = "steelblue", donut2_values = list(0.6, 0.4, 0.2) ) }) test_that("soplot renders double_donut_pie with non-list donut2_colors", { # render_nodes_grid line 267: else branch for donut2_colors mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "double_donut_pie", donut_values = list(0.5, 0.7, 0.3), donut2_values = list(0.6, 0.4, 0.2), donut2_colors = list("purple", "cyan", "magenta") ) }) test_that("soplot renders double_donut_pie with matrix pie_values", { # render_nodes_grid line 274-275: matrix branch for pie_values in double_donut_pie mat <- create_test_matrix(3) pv <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3, ncol = 2) expect_soplot_works( mat, node_shape = "double_donut_pie", donut_values = list(0.5, 0.7, 0.3), donut2_values = list(0.6, 0.4, 0.2), pie_values = pv, pie_colors = c("red", "blue") ) }) # ============================================ # GRID RENDERING: render_edges_grid # ============================================ test_that("soplot renders with explicit edge widths", { # render_edges_grid line 30: explicit widths mat <- create_test_matrix(4) expect_soplot_works(mat, edge_width = 3) }) test_that("soplot renders with no weights (default width)", { # render_edges_grid line 45: no weights default mat <- create_test_matrix(4, weighted = FALSE) expect_soplot_works(mat) }) test_that("soplot renders with width_scale", { # render_edges_grid line 50: width_scale mat <- create_test_matrix(4, weighted = TRUE) expect_soplot_works(mat, edge_width_scale = 2.0) }) test_that("soplot renders with explicit edge colors", { # render_edges_grid lines 58-64: color resolution mat <- create_test_matrix(4, weighted = TRUE) expect_soplot_works(mat, edge_positive_color = "green", edge_negative_color = "red") }) test_that("soplot renders edges with cut/threshold fading", { # render_edges_grid lines 75-82: cut threshold mat <- create_test_matrix(4, weighted = TRUE) expect_soplot_works(mat, edge_cutoff = 0.3) }) test_that("soplot renders with show_arrows = TRUE", { # render_edges_grid lines related to arrows mat <- create_test_matrix(4, symmetric = FALSE, weighted = TRUE) expect_soplot_works(mat, show_arrows = TRUE) }) test_that("soplot renders self-loop edges", { # render_edges_grid lines 252-269: self-loop handling mat <- create_test_matrix(3) mat[1, 1] <- 1 # self-loop mat[2, 2] <- 1 # another self-loop expect_soplot_works(mat, show_arrows = TRUE) }) test_that("soplot renders curved edges with curvature parameter", { # render_edges_grid curved edge path mat <- create_test_matrix(4, weighted = TRUE) expect_soplot_works(mat, curvature = 0.3) }) test_that("soplot renders with curves = 'force'", { # render_edges_grid: force all edges curved mat <- create_test_matrix(4, symmetric = FALSE, weighted = TRUE) expect_soplot_works(mat, curves = "force") }) test_that("soplot renders with bidirectional arrows", { # draw_straight_edge and draw_curved_edge bidirectional branches mat <- create_test_matrix(3, symmetric = FALSE) expect_soplot_works(mat, bidirectional = TRUE, show_arrows = TRUE) }) test_that("soplot renders with dashed edge style", { mat <- create_test_matrix(3) expect_soplot_works(mat, edge_style = "dashed") }) test_that("soplot renders with dotted edge style (width reduction)", { # render_edges_grid: lty==3 dotted width reduction mat <- create_test_matrix(3) expect_soplot_works(mat, edge_style = "dotted") }) # ============================================ # GRID EDGE LABELS: render_edge_labels_grid # ============================================ test_that("soplot renders edge labels", { # render_edge_labels_grid multiple code paths mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works(mat, edge_labels = TRUE) }) test_that("soplot renders edge labels with custom styling", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works( mat, edge_labels = TRUE, edge_label_size = 10, edge_label_color = "navy", edge_label_position = 0.5, edge_label_bg = "lightyellow", edge_label_fontface = "bold", edge_label_border = "rounded", edge_label_border_color = "gray30" ) }) test_that("soplot renders edge labels with circle border", { # render_edge_labels_grid: label_border == "circle" mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works( mat, edge_labels = TRUE, edge_label_border = "circle", edge_label_border_color = "black" ) }) test_that("soplot renders edge labels with rect border", { # render_edge_labels_grid: label_border == "rect" mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works( mat, edge_labels = TRUE, edge_label_border = "rect" ) }) test_that("soplot renders edge labels with underline", { # render_edge_labels_grid: label_underline = TRUE mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works( mat, edge_labels = TRUE, edge_label_underline = TRUE ) }) test_that("soplot renders edge labels on curved edges", { # render_edge_labels_grid: curv != 0 branch for label positioning mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works( mat, edge_labels = TRUE, curvature = 0.3 ) }) test_that("soplot renders edge labels with offset", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works( mat, edge_labels = TRUE, edge_label_offset = 0.05 ) }) # ============================================ # GRID RENDERING: render-grid.R soplot function # ============================================ test_that("soplot renders with threshold", { # render-grid.R: threshold filtering mat <- create_test_matrix(4, weighted = TRUE) expect_soplot_works(mat, threshold = 0.5) }) test_that("soplot renders with title", { # render-grid.R: title rendering mat <- create_test_matrix(3) expect_soplot_works(mat, title = "Test Network") }) test_that("soplot renders with theme", { mat <- create_test_matrix(3) expect_soplot_works(mat, theme = "dark") }) test_that("soplot renders with custom labels", { mat <- create_test_matrix(3) expect_soplot_works(mat, labels = c("A", "B", "C")) }) test_that("soplot renders with show_labels = FALSE", { mat <- create_test_matrix(3) expect_soplot_works(mat, show_labels = FALSE) }) test_that("soplot renders with maximum parameter", { mat <- create_test_matrix(4, weighted = TRUE) expect_soplot_works(mat, maximum = 0.5) }) test_that("soplot renders with legend", { # render_legend_grid code path mat <- create_test_matrix(3) expect_soplot_works(mat, legend = TRUE) }) test_that("soplot renders with legend at different positions", { # render_legend_grid: all position branches mat <- create_test_matrix(3) for (pos in c("topright", "topleft", "bottomright", "bottomleft")) { expect_soplot_works(mat, legend = TRUE, legend_position = pos) } }) test_that("soplot renders node shapes: heart, star, ellipse, cross", { # render_nodes_grid: various shapes mat <- create_test_matrix(4) for (shp in c("heart", "star", "ellipse", "cross")) { expect_soplot_works(mat, node_shape = shp) } }) test_that("soplot renders with various node aesthetics", { mat <- create_test_matrix(3) expect_soplot_works( mat, node_size = 8, node_fill = "tomato", node_border_color = "darkred", node_border_width = 2, node_alpha = 0.8, label_size = 12, label_color = "white", label_position = "above" ) }) test_that("soplot renders with arrow_size", { mat <- create_test_matrix(3, symmetric = FALSE) expect_soplot_works(mat, show_arrows = TRUE, arrow_size = 3) }) test_that("soplot renders donut with donut_color length 2 (fill+bg)", { # render-grid.R donut_color handling: length 2 mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "donut", donut_fill = c(0.5, 0.7, 0.3), donut_color = c("blue", "gray90") ) }) test_that("soplot renders donut with donut_color length > 2 (per-node)", { # render-grid.R donut_color: multiple colors not 2 mat <- create_test_matrix(3) expect_soplot_works( mat, node_shape = "donut", donut_fill = c(0.5, 0.7, 0.3), donut_color = c("red", "green", "blue") ) }) test_that("soplot auto-creates donut fill for donut-shaped nodes", { # render-grid.R: auto-enable donut fill when node_shape is "donut" mat <- create_test_matrix(3) expect_soplot_works(mat, node_shape = "donut") }) test_that("soplot renders with donut_shape explicitly set (non-inherit)", { # render-grid.R: effective_donut_shapes = recycle_to_length mat <- create_test_matrix(3) expect_soplot_works( mat, donut_fill = c(0.5, 0.7, 0.3), donut_shape = "hexagon" ) }) test_that("soplot create_grid_grob works", { # render-grid.R: create_grid_grob lines 735-774 mat <- create_test_matrix(3) net <- cograph(mat) net <- net |> sn_layout("circle") |> sn_nodes(size = 0.05) |> sn_edges(color = "gray50") grob <- with_temp_png({ cograph:::create_grid_grob(net, title = "Test") }) expect_true(!is.null(grob)) }) test_that("soplot with node_names for legend", { # render_legend_grid: node_names aesthetic mat <- create_test_matrix(3) expect_soplot_works( mat, node_names = c("Node A", "Node B", "Node C"), legend = TRUE ) }) # ============================================ # RENDER-GGPLOT: sn_ggplot # ============================================ test_that("sn_ggplot works with basic matrix", { # render-ggplot.R lines 83, 112, 114, 116-120, 140 skip_if_not_installed("ggplot2") mat <- create_test_matrix(3, weighted = TRUE) p <- sn_ggplot(mat) expect_s3_class(p, "ggplot") }) test_that("sn_ggplot works with title", { skip_if_not_installed("ggplot2") mat <- create_test_matrix(3) p <- sn_ggplot(mat, title = "Test") expect_s3_class(p, "ggplot") }) test_that("sn_ggplot works with directed network (arrows)", { # render-ggplot.R: show_arrows path skip_if_not_installed("ggplot2") mat <- create_test_matrix(3, symmetric = FALSE) net <- cograph(mat, directed = TRUE) p <- sn_ggplot(net) expect_s3_class(p, "ggplot") }) test_that("sn_ggplot works with no edges", { # render-ggplot.R line 140: edge_df <- NULL skip_if_not_installed("ggplot2") mat <- matrix(0, 3, 3) p <- sn_ggplot(mat) expect_s3_class(p, "ggplot") }) test_that("sn_ggplot maps shapes correctly", { # render-ggplot.R line 83: shape mapping skip_if_not_installed("ggplot2") mat <- create_test_matrix(4) net <- cograph(mat) |> sn_nodes(shape = c("circle", "square", "triangle", "diamond")) p <- sn_ggplot(net) expect_s3_class(p, "ggplot") }) test_that("sn_ggplot handles custom colors via edge_aes", { # render-ggplot.R lines 112-120: color resolution branches skip_if_not_installed("ggplot2") mat <- create_test_matrix(3, weighted = TRUE) net <- cograph(mat) |> sn_edges( positive_color = "darkgreen", negative_color = "darkred" ) p <- sn_ggplot(net) expect_s3_class(p, "ggplot") }) # ============================================ # SPLOT: base R graphics rendering # ============================================ test_that("splot renders special node shapes (neural, chip, robot)", { # splot-nodes.R lines around 60-70: neural, chip, robot branches mat <- create_test_matrix(3) for (shp in c("neural", "chip", "robot")) { expect_splot_works(mat, node_shape = shp) } }) test_that("splot renders network and database node shapes", { # splot-nodes.R lines 69-100: network, database mat <- create_test_matrix(3) for (shp in c("network", "database")) { expect_splot_works(mat, node_shape = shp) } }) test_that("splot renders ellipse and rectangle shapes", { # splot-nodes.R lines 49-58: ellipse/rectangle mat <- create_test_matrix(3) expect_splot_works(mat, node_shape = "ellipse") expect_splot_works(mat, node_shape = "rectangle", node_size2 = 4) }) test_that("splot renders various polygon shapes", { # splot-nodes.R lines 81-89: fallback polygon shapes mat <- create_test_matrix(3) for (shp in c("triangle", "diamond", "pentagon", "hexagon", "star", "heart", "cross")) { expect_splot_works(mat, node_shape = shp) } }) test_that("splot renders pie chart nodes", { # splot-nodes.R lines 107+: draw_pie_node_base mat <- create_test_matrix(3) expect_splot_works( mat, pie_values = list(c(1, 2, 3), c(3, 1), c(1, 1, 1)), pie_colors = c("red", "blue", "green") ) }) test_that("splot renders donut nodes with single value", { # splot-nodes.R: draw_donut_node_base single value path mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.3, 0.7, 0.5), donut_color = "steelblue", donut_show_value = TRUE, donut_value_size = 0.8, donut_value_color = "black" ) }) test_that("splot renders donut nodes with multiple values (segmented)", { # splot-nodes.R lines 432-450: multi-value donut mat <- create_test_matrix(3) expect_splot_works( mat, node_shape = "donut", donut_values = list(c(1, 2, 3), c(2, 3), c(1, 1)), donut_colors = list(c("red", "blue", "green"), c("cyan", "magenta"), c("orange", "purple")) ) }) test_that("splot renders polygon donut", { # splot-nodes.R: draw_polygon_donut_node_base mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.5, 0.7, 0.3), donut_shape = "square", donut_show_value = TRUE, donut_value_prefix = "$", donut_value_suffix = "%" ) }) test_that("splot renders polygon donut with multi-segment values", { # splot-nodes.R: polygon_donut multi-segment path lines 271-292 mat <- create_test_matrix(3) expect_splot_works( mat, node_shape = "donut", donut_values = list(c(1, 2, 3), c(2, 3), c(1, 1)), donut_shape = "hexagon" ) }) test_that("splot renders donut_pie combined shape", { # splot-nodes.R lines 535+: draw_donut_pie_node_base mat <- create_test_matrix(3) expect_splot_works( mat, node_shape = "donut_pie", donut_values = list(0.8, 0.5, 0.3), pie_values = list(c(1, 2, 3), c(2, 1), c(3, 3)), pie_colors = c("red", "blue", "green"), donut_border_width = 2, pie_border_width = 1 ) }) test_that("splot renders double_donut_pie", { # splot-nodes.R lines 679+: draw_double_donut_pie_node_base mat <- create_test_matrix(3) expect_splot_works( mat, node_shape = "double_donut_pie", donut_values = list(0.8, 0.5, 0.3), donut2_values = list(0.6, 0.4, 0.7), donut2_colors = list(c("pink"), c("cyan"), c("orange")), pie_values = list(c(1, 2), c(3, 1), c(2, 2)), pie_colors = c("red", "blue"), donut_border_width = 2, pie_border_width = 1 ) }) test_that("splot renders donut with value formatting", { # splot-nodes.R: value formatting in draw_donut_node_base mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.5, 0.7, 0.3), donut_show_value = TRUE, donut_value_fontface = "italic", donut_value_fontfamily = "serif", donut_value_digits = 1, donut_value_prefix = "$", donut_value_suffix = "%" ) }) test_that("splot renders with use_pch = TRUE", { # splot-nodes.R lines 1126+: render_nodes_base with use_pch=TRUE # render_nodes_base path for PCH-based node rendering mat <- create_test_matrix(3) expect_splot_works(mat, use_pch = TRUE) }) # ============================================ # SPLOT EDGES: splot-edges.R # ============================================ test_that("splot renders self-loop edges", { # splot-edges.R lines 598-643+: draw_self_loop_base mat <- create_test_matrix(3) mat[1, 1] <- 1 mat[2, 2] <- 1 expect_splot_works(mat, show_arrows = TRUE) }) test_that("splot renders edge labels", { # splot-edges.R lines 654-713: edge label drawing mat <- create_test_matrix(3, weighted = TRUE) expect_splot_works(mat, edge_labels = TRUE) }) test_that("splot renders edge labels with shadow", { # splot-edges.R: draw_edge_label_base shadow path mat <- create_test_matrix(3, weighted = TRUE) expect_splot_works( mat, edge_labels = TRUE, edge_label_shadow = TRUE, edge_label_shadow_color = "gray40", edge_label_shadow_offset = 0.5, edge_label_shadow_alpha = 0.5 ) }) test_that("splot renders curved edges", { # splot-edges.R: draw_curved_edge_base mat <- create_test_matrix(4, symmetric = FALSE, weighted = TRUE) expect_splot_works(mat, curvature = 0.3) }) test_that("splot renders with curves = 'force'", { # splot.R: curves = "force" path mat <- create_test_matrix(4, symmetric = FALSE, weighted = TRUE) expect_splot_works(mat, curves = "force") }) test_that("splot renders with curves = FALSE (all straight)", { mat <- create_test_matrix(4, symmetric = FALSE, weighted = TRUE) expect_splot_works(mat, curves = FALSE) }) test_that("splot renders bidirectional arrows", { # splot-edges.R: bidirectional branches mat <- create_test_matrix(3, symmetric = FALSE) expect_splot_works(mat, bidirectional = TRUE, show_arrows = TRUE) }) test_that("splot renders with edge_start_style = 'dashed'", { # splot.R render_edges_splot: edge_start_style handling mat <- create_test_matrix(3, symmetric = FALSE) expect_splot_works( mat, show_arrows = TRUE, edge_start_style = "dashed", edge_start_length = 0.2 ) }) test_that("splot renders with edge_start_style = 'dotted'", { mat <- create_test_matrix(3, symmetric = FALSE) expect_splot_works( mat, show_arrows = TRUE, edge_start_style = "dotted", edge_start_length = 0.15 ) }) test_that("splot renders with edge style variations", { mat <- create_test_matrix(3) expect_splot_works(mat, edge_style = "dashed") expect_splot_works(mat, edge_style = "dotted") expect_splot_works(mat, edge_style = "longdash") }) # ============================================ # SPLOT: parameter paths and edge processing # ============================================ test_that("splot renders with threshold filtering", { # splot.R: threshold/minimum filtering mat <- create_test_matrix(4, weighted = TRUE) expect_splot_works(mat, threshold = 0.5) }) test_that("splot renders with maximum parameter", { mat <- create_test_matrix(4, weighted = TRUE) expect_splot_works(mat, maximum = 0.5) }) test_that("splot renders with layout_scale auto", { # splot.R: layout_scale = "auto" path mat <- create_test_matrix(4) expect_splot_works(mat, layout_scale = "auto") }) test_that("splot renders with explicit layout_scale", { # splot.R: numeric layout_scale != 1 mat <- create_test_matrix(4) expect_splot_works(mat, layout_scale = 1.2) }) test_that("splot renders with edge_cutoff (fading)", { # splot.R: edge_cutoff threshold for transparency mat <- create_test_matrix(4, weighted = TRUE) expect_splot_works(mat, edge_cutoff = 0.3) }) test_that("splot renders with edge_scale_mode variations", { mat <- create_test_matrix(4, weighted = TRUE) for (mode in c("linear", "log", "sqrt", "rank")) { expect_splot_works(mat, edge_scale_mode = mode) } }) test_that("splot renders with custom edge colors", { mat <- create_test_matrix(4, weighted = TRUE) expect_splot_works( mat, edge_positive_color = "darkgreen", edge_negative_color = "darkred" ) }) test_that("splot renders with edge_alpha < 1", { mat <- create_test_matrix(3) expect_splot_works(mat, edge_alpha = 0.5) }) test_that("splot renders with node_alpha < 1", { mat <- create_test_matrix(3) expect_splot_works(mat, node_alpha = 0.5) }) test_that("splot renders with title", { mat <- create_test_matrix(3) expect_splot_works(mat, title = "My Network") }) test_that("splot renders with theme = 'dark'", { mat <- create_test_matrix(3) expect_splot_works(mat, theme = "dark") }) test_that("splot renders with legend", { mat <- create_test_matrix(3) expect_splot_works(mat, legend = TRUE) }) test_that("splot renders with groups", { mat <- create_test_matrix(6) expect_splot_works( mat, groups = c("A", "A", "A", "B", "B", "B"), legend = TRUE ) }) test_that("splot renders with label_position variations", { mat <- create_test_matrix(3) for (pos in c("center", "above", "below", "left", "right")) { expect_splot_works(mat, label_position = pos) } }) test_that("splot renders with labels = FALSE", { mat <- create_test_matrix(3) expect_splot_works(mat, labels = FALSE) }) test_that("splot renders with custom label font options", { mat <- create_test_matrix(3) expect_splot_works( mat, label_fontface = "bold", label_fontfamily = "serif", label_hjust = 0, label_vjust = 1, label_angle = 45 ) }) test_that("splot renders with loop_rotation", { mat <- create_test_matrix(3) mat[1, 1] <- 1 expect_splot_works(mat, loop_rotation = pi/4) }) test_that("splot renders with curve_shape and curve_pivot", { mat <- create_test_matrix(4, symmetric = FALSE) expect_splot_works( mat, curvature = 0.3, curve_shape = 0.5, curve_pivot = 0.3 ) }) # ============================================ # SOPLOT: grid special shapes # ============================================ test_that("soplot renders neural shape in grid", { mat <- create_test_matrix(3) expect_soplot_works(mat, node_shape = "neural") }) test_that("soplot renders chip shape in grid", { mat <- create_test_matrix(3) expect_soplot_works(mat, node_shape = "chip") }) test_that("soplot renders robot shape in grid", { mat <- create_test_matrix(3) expect_soplot_works(mat, node_shape = "robot") }) test_that("soplot renders triangle and diamond shapes", { mat <- create_test_matrix(3) expect_soplot_works(mat, node_shape = "triangle") expect_soplot_works(mat, node_shape = "diamond") }) test_that("soplot renders pentagon and hexagon shapes", { mat <- create_test_matrix(3) expect_soplot_works(mat, node_shape = "pentagon") expect_soplot_works(mat, node_shape = "hexagon") }) # ============================================ # SOPLOT: reciprocal edge curving # ============================================ test_that("soplot handles reciprocal edges with automatic curving", { # render_edges_grid: reciprocal edge detection and curving # Also render_edge_labels_grid: same reciprocal detection mat <- matrix(0, 3, 3) mat[1, 2] <- 0.8 mat[2, 1] <- 0.5 # reciprocal mat[1, 3] <- 0.6 mat[3, 1] <- 0.4 # reciprocal expect_soplot_works(mat, show_arrows = TRUE, edge_labels = TRUE) }) test_that("soplot edge labels curves mode 'force'", { # render_edge_labels_grid: curves_mode == "force" path mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works(mat, edge_labels = TRUE, curves = "force") }) test_that("soplot edge labels curves mode FALSE", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works(mat, edge_labels = TRUE, curves = FALSE) }) # ============================================ # SPLOT: render_nodes_base paths # ============================================ test_that("splot render_nodes_base with pie and donut together", { # splot-nodes.R lines 1150-1165: has_donut && has_pie mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.5, 0.7, 0.3), pie_values = list(c(1, 2), c(3, 1), c(2, 2)), pie_colors = c("red", "blue") ) }) test_that("splot render_nodes_base donut only", { # splot-nodes.R lines 1167-1178: has_donut only mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.5, 0.7, 0.3) ) }) test_that("splot render_nodes_base pie only", { # splot-nodes.R lines 1180-1191: has_pie only mat <- create_test_matrix(3) expect_splot_works( mat, pie_values = list(c(1, 2, 3), c(2, 3), c(1, 1, 1)), pie_colors = c("red", "blue", "green") ) }) test_that("splot render_nodes_base labels rendering", { # splot-nodes.R lines 1206-1209: labels rendering mat <- create_test_matrix(3) expect_splot_works( mat, labels = c("A", "B", "C"), label_size = 1.2, label_color = "navy" ) }) # ============================================ # SPLOT: render_edges_base paths # ============================================ test_that("splot render_edges_base with self-loops and labels", { # splot-edges.R render_edges_base: self-loop label position mat <- create_test_matrix(3) mat[1, 1] <- 1 expect_splot_works(mat, edge_labels = TRUE, show_arrows = TRUE) }) test_that("splot render_edges_base with curved edges and labels", { # splot-edges.R render_edges_base: curved edge + label position mat <- create_test_matrix(4, symmetric = FALSE, weighted = TRUE) expect_splot_works(mat, curvature = 0.3, edge_labels = TRUE) }) test_that("splot render_edges_base straight edge with labels", { # splot-edges.R render_edges_base: straight edge label position mat <- create_test_matrix(3, weighted = TRUE) expect_splot_works(mat, curves = FALSE, edge_labels = TRUE) }) # ============================================ # SPLOT: find_curve_split_index edge cases # ============================================ test_that("splot find_curve_split_index works", { # splot-edges.R line 28: edge case with very small total length fn <- cograph:::find_curve_split_index # Normal case x <- c(0, 1, 2, 3, 4) y <- c(0, 0, 0, 0, 0) expect_equal(fn(x, y, 0.5), 3) # Boundary: fraction = 0 expect_equal(fn(x, y, 0), 1) # Boundary: fraction = 1 expect_equal(fn(x, y, 1), 5) }) test_that("splot draw_curve_with_start_segment handles no-split case", { # splot-edges.R line 58: start_fraction <= 0 fn <- cograph:::draw_curve_with_start_segment with_temp_png({ plot(0, 0, xlim = c(0, 1), ylim = c(0, 1), type = "n") fn(c(0, 0.5, 1), c(0, 0.5, 1), "black", 1, 1, 1, 0) }) expect_true(TRUE) }) # ============================================ # SPLOT: edge label position computation # ============================================ test_that("get_edge_label_position handles straight and curved", { fn <- cograph:::get_edge_label_position # Straight edge pos <- fn(0, 0, 1, 1, position = 0.5, curve = 0) expect_true(is.list(pos)) expect_true(abs(pos$x - 0.5) < 0.01) expect_true(abs(pos$y - 0.5) < 0.01) # Curved edge pos2 <- fn(0, 0, 1, 1, position = 0.5, curve = 0.3) expect_true(is.list(pos2)) # With offset pos3 <- fn(0, 0, 1, 1, position = 0.5, curve = 0, label_offset = 0.1) expect_true(is.list(pos3)) # With curve and non-default pivot pos4 <- fn(0, 0, 1, 1, position = 0.3, curve = 0.5, curvePivot = 0.3) expect_true(is.list(pos4)) }) # ============================================ # SPLOT: auto-convert pie_values to donut_fill # ============================================ test_that("splot auto-converts numeric pie_values to donut_fill", { # splot.R lines ~647-651: auto-convert pie_values vector to donut_fill mat <- create_test_matrix(3) expect_splot_works(mat, pie_values = c(0.3, 0.7, 0.5)) }) # ============================================ # SOPLOT: donut auto-fill when shape is "donut" # ============================================ test_that("soplot donut auto-fill with mixed shapes", { mat <- create_test_matrix(4) expect_soplot_works( mat, node_shape = c("circle", "donut", "square", "donut") ) }) # ============================================ # DIRECTED NETWORK: reciprocal detection # ============================================ test_that("splot renders directed network with reciprocal edges", { # splot.R: is_reciprocal detection and curve computation mat <- matrix(0, 4, 4) mat[1, 2] <- 0.8 mat[2, 1] <- 0.6 # reciprocal with 1->2 mat[2, 3] <- 0.5 mat[3, 4] <- 0.7 mat[4, 3] <- 0.3 # reciprocal with 3->4 expect_splot_works(mat, directed = TRUE, show_arrows = TRUE) }) test_that("splot CI underlay for self-loop", { # splot.R render_edges_splot: CI underlay for self-loop mat <- create_test_matrix(3) mat[1, 1] <- 0.5 mat[2, 2] <- 0.7 n_edges <- sum(mat != 0) ci_vals <- rep(0.1, n_edges) expect_splot_works(mat, edge_ci = ci_vals, show_arrows = TRUE) }) test_that("splot CI underlay for regular edges", { # splot.R render_edges_splot: CI underlay for curved/straight edges mat <- create_test_matrix(3, weighted = TRUE) n_edges <- sum(mat != 0) ci_vals <- rep(0.05, n_edges) expect_splot_works(mat, edge_ci = ci_vals) }) # ============================================ # SOPLOT: CI underlay paths # ============================================ test_that("soplot CI underlay for self-loops", { # render_edges_grid lines 252-256, 258, 265 mat <- create_test_matrix(3) mat[1, 1] <- 1 net <- cograph(mat) |> sn_edges(ci = rep(0.1, sum(mat != 0))) expect_soplot_works(net, show_arrows = TRUE) }) test_that("soplot CI underlay for straight edges", { # render_edges_grid lines 280-283, 285-286, 294 mat <- create_test_matrix(3, weighted = TRUE) net <- cograph(mat) |> sn_edges(ci = rep(0.05, sum(mat != 0) / 2)) expect_soplot_works(net) }) # ============================================ # SOPLOT: miscellaneous coverage gaps # ============================================ test_that("soplot with curve_shape and curve_pivot", { mat <- create_test_matrix(4, symmetric = FALSE) expect_soplot_works( mat, curvature = 0.3, curve_shape = 0.5, curve_pivot = 0.3 ) }) test_that("soplot with loop_rotation parameter", { mat <- create_test_matrix(3) mat[1, 1] <- 1 expect_soplot_works(mat, loop_rotation = pi/4) }) test_that("soplot with edge_label_fontface italic", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works( mat, edge_labels = TRUE, edge_label_fontface = "italic" ) }) test_that("soplot with edge_label_bg = NA (transparent)", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works( mat, edge_labels = TRUE, edge_label_bg = NA ) }) test_that("soplot with single node", { # render-grid.R: single node case (nodes$x/y = 0.5) mat <- matrix(0, 1, 1) expect_soplot_works(mat) }) test_that("soplot with collinear nodes (zero range)", { # render-grid.R: max_range near zero mat <- matrix(c(0, 1, 1, 0), 2, 2) expect_soplot_works(mat) }) test_that("soplot with newpage = FALSE", { mat <- create_test_matrix(3) with_temp_png({ grid::grid.newpage() soplot(mat, newpage = FALSE) }) expect_true(TRUE) }) test_that("soplot with scaling = 'legacy'", { mat <- create_test_matrix(3) expect_soplot_works(mat, scaling = "legacy") }) test_that("soplot with weight_digits rounding", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works(mat, weight_digits = 1) }) test_that("soplot with edge_duplicates = 'sum'", { # render-grid.R: duplicate edge handling df <- data.frame( from = c(1, 2, 1), to = c(2, 3, 2), weight = c(0.5, 0.3, 0.2) ) expect_soplot_works(df, edge_duplicates = "sum") }) # ============================================ # SPLOT: weight_digits and edge_duplicates # ============================================ test_that("splot with weight_digits rounding", { mat <- create_test_matrix(3, weighted = TRUE) expect_splot_works(mat, weight_digits = 1) }) test_that("splot with edge_duplicates = 'mean'", { df <- data.frame( from = c(1, 2, 1), to = c(2, 3, 2), weight = c(0.5, 0.3, 0.2) ) expect_splot_works(df, edge_duplicates = "mean") }) # ============================================ # SPLOT: deprecated parameter paths # ============================================ test_that("splot handles deprecated esize parameter", { mat <- create_test_matrix(3, weighted = TRUE) suppressWarnings({ expect_splot_works(mat, esize = 5) }) }) test_that("splot handles deprecated positive_color", { mat <- create_test_matrix(3, weighted = TRUE) suppressWarnings({ expect_splot_works(mat, positive_color = "green") }) }) test_that("splot handles deprecated negative_color", { mat <- create_test_matrix(3, weighted = TRUE) suppressWarnings({ expect_splot_works(mat, negative_color = "red") }) }) # ============================================ # SOPLOT: deprecated parameter paths # ============================================ test_that("soplot handles deprecated esize parameter", { mat <- create_test_matrix(3, weighted = TRUE) suppressWarnings({ expect_soplot_works(mat, esize = 5) }) }) test_that("soplot handles deprecated positive_color", { mat <- create_test_matrix(3, weighted = TRUE) suppressWarnings({ expect_soplot_works(mat, positive_color = "green") }) }) # ============================================ # SPLOT: donut_color handling variants # ============================================ test_that("splot donut_color length 1", { mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.3, 0.6, 0.9), donut_color = "steelblue" ) }) test_that("splot donut_color length 2 (fill + bg)", { mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.3, 0.6, 0.9), donut_color = c("blue", "gray90") ) }) test_that("splot donut_color per-node (length > 2)", { mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.3, 0.6, 0.9), donut_color = c("red", "green", "blue") ) }) test_that("splot donut with donut_border_color and outer_border", { mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.5, 0.7, 0.3), donut_border_color = "darkblue", donut_outer_border_color = "red", donut_line_type = 2 ) }) test_that("splot donut_empty renders empty rings", { mat <- create_test_matrix(3) expect_splot_works( mat, donut_fill = c(0.5, NA, 0.3), donut_empty = TRUE ) }) # ============================================ # SOPLOT: node_size and edge_size scaling # ============================================ test_that("soplot uses custom node_size", { mat <- create_test_matrix(3) expect_soplot_works(mat, node_size = 10) }) test_that("soplot uses custom edge_size", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works(mat, edge_size = 10) }) test_that("soplot uses edge_width_range", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works(mat, edge_width_range = c(1, 8)) }) # ============================================ # SPLOT: background and file output # ============================================ test_that("splot renders with custom background", { mat <- create_test_matrix(3) expect_splot_works(mat, background = "lightyellow") }) test_that("splot renders with aspect = FALSE", { mat <- create_test_matrix(3) expect_splot_works(mat, aspect = FALSE) }) test_that("splot with rescale = FALSE", { mat <- create_test_matrix(3) expect_splot_works(mat, rescale = FALSE) }) # ============================================ # SPLOT: various layout options # ============================================ test_that("splot renders with circle layout", { mat <- create_test_matrix(4) expect_splot_works(mat, layout = "circle") }) test_that("splot renders with spring layout", { mat <- create_test_matrix(4) expect_splot_works(mat, layout = "spring") }) test_that("splot renders with grid layout", { mat <- create_test_matrix(4) expect_splot_works(mat, layout = "grid") }) # ============================================ # SOPLOT: edge_labels = TRUE generates weight labels # ============================================ test_that("soplot edge_labels = TRUE shows weight values", { mat <- create_test_matrix(3, weighted = TRUE) expect_soplot_works(mat, edge_labels = TRUE) }) # ============================================ # COMBINED: comprehensive rendering test # ============================================ test_that("soplot handles complex combination of parameters", { mat <- create_test_matrix(5, weighted = TRUE, density = 0.6) expect_soplot_works( mat, layout = "circle", title = "Complex Network", theme = "minimal", node_size = 6, node_shape = c("circle", "square", "triangle", "diamond", "hexagon"), node_fill = c("red", "blue", "green", "orange", "purple"), edge_labels = TRUE, show_labels = TRUE, edge_alpha = 0.7, node_alpha = 0.9, edge_style = "solid", curvature = 0.15, legend = TRUE, legend_position = "bottomleft" ) }) test_that("splot handles complex combination of parameters", { mat <- create_test_matrix(5, weighted = TRUE, density = 0.6) expect_splot_works( mat, layout = "circle", title = "Complex Network", theme = "minimal", node_size = 6, node_shape = c("circle", "square", "triangle", "diamond", "hexagon"), node_fill = c("red", "blue", "green", "orange", "purple"), edge_labels = TRUE, labels = TRUE, edge_alpha = 0.7, node_alpha = 0.9, edge_style = "solid", curvature = 0.15, legend = TRUE ) })