# Comprehensive tests for R/class-network.R # This file tests the CographNetwork R6 class, cograph_network S3 class, # and all related getter/setter functions # ============================================================================= # Test Fixtures # ============================================================================= # Simple symmetric adjacency matrix (undirected) create_symmetric_matrix <- function(n = 3) { mat <- matrix(0, nrow = n, ncol = n) for (i in 1:(n-1)) { for (j in (i+1):n) { mat[i, j] <- mat[j, i] <- runif(1, 0.1, 1) } } rownames(mat) <- colnames(mat) <- paste0("N", seq_len(n)) mat } # Asymmetric matrix (directed) create_directed_matrix <- function(n = 3) { mat <- matrix(runif(n * n, 0, 1), nrow = n, ncol = n) diag(mat) <- 0 rownames(mat) <- colnames(mat) <- paste0("N", seq_len(n)) mat } # ============================================================================= # CographNetwork R6 Class Tests # ============================================================================= test_that("CographNetwork$new() creates empty network", { net <- CographNetwork$new() expect_s3_class(net, "CographNetwork") expect_equal(net$n_nodes, 0L) expect_equal(net$n_edges, 0L) expect_false(net$is_directed) }) test_that("CographNetwork$new() creates network from matrix", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) expect_s3_class(net, "CographNetwork") expect_equal(net$n_nodes, 3L) expect_true(net$n_edges > 0) }) test_that("CographNetwork$new() handles directed parameter", { mat <- matrix(c(0, 1, 0, 0, 0, 1, 0, 0, 0), nrow = 3) # Force directed net_dir <- CographNetwork$new(mat, directed = TRUE) expect_true(net_dir$is_directed) # Force undirected net_undir <- CographNetwork$new(mat, directed = FALSE) expect_false(net_undir$is_directed) }) test_that("CographNetwork$new() accepts nodes data frame with labels", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("1", "2", "3") labels <- c("Alpha", "Beta", "Gamma") nodes_df <- data.frame(label = c("1", "2", "3"), labels = labels) net <- CographNetwork$new(mat, nodes = nodes_df) # node_labels active binding uses 'labels' column (priority: labels > label) expect_equal(net$node_labels, labels) }) test_that("CographNetwork$new() node_labels returns label column when no labels column", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("A", "B", "C") net <- CographNetwork$new(mat) # Should return the label column (from rownames) expect_equal(net$node_labels, c("A", "B", "C")) }) test_that("CographNetwork$new() initializes default aesthetics", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) node_aes <- net$get_node_aes() expect_true(is.list(node_aes)) expect_equal(node_aes$size, 0.05) expect_equal(node_aes$shape, "circle") expect_equal(node_aes$fill, "#4A90D9") edge_aes <- net$get_edge_aes() expect_true(is.list(edge_aes)) expect_equal(edge_aes$width, 1) expect_equal(edge_aes$positive_color, "#2E7D32") expect_equal(edge_aes$negative_color, "#C62828") }) test_that("CographNetwork clone_network() creates independent copy", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net1 <- CographNetwork$new(mat) net1$set_theme("dark") net2 <- net1$clone_network() expect_s3_class(net2, "CographNetwork") expect_equal(net2$n_nodes, net1$n_nodes) expect_equal(net2$n_edges, net1$n_edges) expect_equal(net2$get_theme(), "dark") }) test_that("CographNetwork set_nodes() and get_nodes() work", { net <- CographNetwork$new() nodes_df <- data.frame( id = 1:3, label = c("A", "B", "C"), x = c(0, 1, 0.5), y = c(0, 0, 1) ) net$set_nodes(nodes_df) result <- net$get_nodes() expect_equal(nrow(result), 3) expect_equal(result$label, c("A", "B", "C")) }) test_that("CographNetwork set_edges() and get_edges() work", { net <- CographNetwork$new() edges_df <- data.frame( from = c(1, 2), to = c(2, 3), weight = c(0.5, 0.8) ) net$set_edges(edges_df) result <- net$get_edges() expect_equal(nrow(result), 2) expect_equal(result$weight, c(0.5, 0.8)) }) test_that("CographNetwork set_directed() and is_directed work", { net <- CographNetwork$new() net$set_directed(TRUE) expect_true(net$is_directed) net$set_directed(FALSE) expect_false(net$is_directed) }) test_that("CographNetwork set_weights() work", { net <- CographNetwork$new() weights <- c(0.3, 0.5, 0.7) net$set_weights(weights) expect_true(net$has_weights) }) test_that("CographNetwork has_weights is FALSE for all-1 weights", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) # All 1s or NULLs => has_weights should be FALSE # Actually the matrix has 1s, needs checking # If weights are all 1, has_weights should be FALSE expect_false(net$has_weights) }) test_that("CographNetwork set_layout_coords() with matrix", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) # Use named matrix columns for proper conversion coords <- matrix(c(0, 1, 0.5, 0, 0, 1), ncol = 2) colnames(coords) <- c("x", "y") net$set_layout_coords(coords) layout <- net$get_layout() expect_equal(layout$x, c(0, 1, 0.5)) expect_equal(layout$y, c(0, 0, 1)) }) test_that("CographNetwork set_layout_coords() with data.frame", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) coords <- data.frame(x = c(0, 1, 0.5), y = c(0, 0, 1)) net$set_layout_coords(coords) layout <- net$get_layout() expect_equal(layout$x, c(0, 1, 0.5)) }) test_that("CographNetwork set_layout_coords() updates node positions", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) coords <- data.frame(x = c(10, 20, 30), y = c(100, 200, 300)) net$set_layout_coords(coords) nodes <- net$get_nodes() expect_equal(nodes$x, c(10, 20, 30)) expect_equal(nodes$y, c(100, 200, 300)) }) test_that("CographNetwork set_node_aes() merges with defaults", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) net$set_node_aes(list(size = 0.1, fill = "red")) aes <- net$get_node_aes() expect_equal(aes$size, 0.1) expect_equal(aes$fill, "red") # Other defaults should still be present expect_equal(aes$shape, "circle") }) test_that("CographNetwork set_edge_aes() merges with defaults", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) net$set_edge_aes(list(width = 3, color = "blue")) aes <- net$get_edge_aes() expect_equal(aes$width, 3) expect_equal(aes$color, "blue") # Other defaults should still be present expect_equal(aes$positive_color, "#2E7D32") }) test_that("CographNetwork set_theme() and get_theme() work", { net <- CographNetwork$new() net$set_theme("minimal") expect_equal(net$get_theme(), "minimal") net$set_theme("dark") expect_equal(net$get_theme(), "dark") }) test_that("CographNetwork set_layout_info() and get_layout_info() work", { net <- CographNetwork$new() info <- list(name = "spring", seed = 42, iterations = 100) net$set_layout_info(info) result <- net$get_layout_info() expect_equal(result$name, "spring") expect_equal(result$seed, 42) }) test_that("CographNetwork set_plot_params() and get_plot_params() work", { net <- CographNetwork$new() params <- list(title = "My Network", margin = 0.1) net$set_plot_params(params) result <- net$get_plot_params() expect_equal(result$title, "My Network") expect_equal(result$margin, 0.1) }) test_that("CographNetwork print() method works", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- CographNetwork$new(mat) expect_output(net$print(), "CographNetwork") expect_output(net$print(), "Nodes:") expect_output(net$print(), "Edges:") expect_output(net$print(), "Directed:") }) test_that("CographNetwork active bindings work", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("A", "B", "C") net <- CographNetwork$new(mat) expect_equal(net$n_nodes, 3) expect_true(net$n_edges > 0) expect_false(net$is_directed) # Symmetric matrix expect_equal(net$node_labels, c("A", "B", "C")) }) # ============================================================================= # is_cograph_network() Tests # ============================================================================= test_that("is_cograph_network() identifies CographNetwork R6 objects", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net_r6 <- CographNetwork$new(mat) expect_true(is_cograph_network(net_r6)) }) test_that("is_cograph_network() identifies cograph_network S3 objects", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net_s3 <- as_cograph(mat) expect_true(is_cograph_network(net_s3)) }) test_that("is_cograph_network() returns FALSE for non-network objects", { expect_false(is_cograph_network(matrix(1:9, 3, 3))) expect_false(is_cograph_network(list(a = 1, b = 2))) expect_false(is_cograph_network(data.frame(x = 1:3))) expect_false(is_cograph_network(NULL)) expect_false(is_cograph_network(42)) expect_false(is_cograph_network("network")) }) # ============================================================================= # .create_cograph_network() Tests (internal constructor) # ============================================================================= test_that(".create_cograph_network() creates valid structure", { nodes <- data.frame(id = 1:3, label = c("A", "B", "C")) edges <- data.frame(from = c(1, 2), to = c(2, 3), weight = c(0.5, 0.8)) net <- .create_cograph_network( nodes = nodes, edges = edges, directed = FALSE, meta = list(source = "test") ) expect_s3_class(net, "cograph_network") expect_s3_class(net, "list") expect_equal(net$meta$source, "test") expect_false(net$directed) }) test_that(".create_cograph_network() handles empty edges", { nodes <- data.frame(id = 1:3, label = c("A", "B", "C")) edges <- data.frame(from = integer(0), to = integer(0)) net <- .create_cograph_network( nodes = nodes, edges = edges, directed = FALSE, meta = list(source = "test") ) expect_equal(nrow(net$edges), 0) expect_true("weight" %in% names(net$edges)) }) test_that(".create_cograph_network() adds default weight column", { nodes <- data.frame(id = 1:3, label = c("A", "B", "C")) edges <- data.frame(from = c(1, 2), to = c(2, 3)) # No weight net <- .create_cograph_network( nodes = nodes, edges = edges, directed = FALSE ) expect_equal(net$edges$weight, c(1, 1)) }) test_that(".create_cograph_network() preserves optional fields", { nodes <- data.frame(id = 1:3, label = c("A", "B", "C")) edges <- data.frame(from = c(1, 2), to = c(2, 3), weight = c(0.5, 0.8)) weights_mat <- matrix(0, 3, 3) tna_meta <- list(type = "single", group_name = "Test") layout_meta <- list(name = "spring", seed = 42) net <- .create_cograph_network( nodes = nodes, edges = edges, directed = TRUE, meta = list( source = "tna", tna = tna_meta, layout = layout_meta ), weights = weights_mat ) expect_equal(net$meta$tna$type, "single") expect_equal(net$meta$tna$group_name, "Test") expect_equal(net$meta$layout$name, "spring") expect_equal(net$meta$source, "tna") }) # ============================================================================= # as_cograph() / to_cograph() Tests # ============================================================================= test_that("as_cograph() returns same object if already cograph_network", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net1 <- as_cograph(mat) net2 <- as_cograph(net1) expect_identical(net1, net2) }) test_that("as_cograph() creates network from symmetric matrix", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) expect_s3_class(net, "cograph_network") expect_equal(n_nodes(net), 4) expect_false(is_directed(net)) expect_equal(net$meta$source, "matrix") }) test_that("as_cograph() creates network from asymmetric matrix", { mat <- create_directed_matrix(4) net <- as_cograph(mat) expect_s3_class(net, "cograph_network") expect_equal(n_nodes(net), 4) expect_true(is_directed(net)) }) test_that("as_cograph() can force directed parameter", { mat <- create_symmetric_matrix(3) net_undir <- as_cograph(mat, directed = FALSE) expect_false(is_directed(net_undir)) net_dir <- as_cograph(mat, directed = TRUE) expect_true(is_directed(net_dir)) }) test_that("as_cograph() creates network from edge list data.frame", { edges <- data.frame( from = c("A", "B", "C"), to = c("B", "C", "A"), weight = c(0.5, 0.8, 0.3) ) net <- as_cograph(edges) expect_s3_class(net, "cograph_network") expect_equal(n_nodes(net), 3) expect_equal(net$meta$source, "edgelist") }) test_that("as_cograph() preserves weight matrix", { mat <- matrix(c(0, 0.5, 0.3, 0.2, 0, 0.4, 0.1, 0.6, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("A", "B", "C") net <- as_cograph(mat) expect_true(!is.null(net$weights)) expect_true(is.matrix(net$weights)) expect_equal(dim(net$weights), c(3, 3)) }) test_that("to_cograph() is an alias for as_cograph()", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net1 <- as_cograph(mat) net2 <- to_cograph(mat) expect_equal(n_nodes(net1), n_nodes(net2)) expect_equal(n_edges(net1), n_edges(net2)) expect_equal(is_directed(net1), is_directed(net2)) }) # ============================================================================= # get_nodes() Tests # ============================================================================= test_that("get_nodes() returns nodes data frame", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("A", "B", "C") net <- as_cograph(mat) nodes <- get_nodes(net) expect_true(is.data.frame(nodes)) expect_equal(nrow(nodes), 3) expect_true("id" %in% names(nodes)) expect_true("label" %in% names(nodes)) }) test_that("get_nodes() errors on non-cograph_network", { expect_error(get_nodes(list(a = 1)), "Cannot extract nodes") expect_error(get_nodes(matrix(1:4, 2, 2)), "Cannot extract nodes") }) # ============================================================================= # get_edges() Tests # ============================================================================= test_that("get_edges() returns edges data frame", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) edges <- get_edges(net) expect_true(is.data.frame(edges)) expect_true("from" %in% names(edges)) expect_true("to" %in% names(edges)) expect_true("weight" %in% names(edges)) }) test_that("get_edges() returns empty data frame for network with no edges", { nodes <- data.frame(id = 1:3, label = c("A", "B", "C")) net <- .create_cograph_network( nodes = nodes, edges = NULL, directed = FALSE ) edges <- get_edges(net) expect_equal(nrow(edges), 0) expect_true("from" %in% names(edges)) }) test_that("get_edges() errors on non-cograph_network", { expect_error(get_edges(list(a = 1)), "Cannot extract edges") expect_error(get_edges(42), "Cannot extract edges") }) # ============================================================================= # get_labels() Tests # ============================================================================= test_that("get_labels() returns character vector of labels", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("Alpha", "Beta", "Gamma") net <- as_cograph(mat) labels <- get_labels(net) expect_true(is.character(labels)) expect_equal(labels, c("Alpha", "Beta", "Gamma")) }) test_that("get_labels() errors on non-cograph_network", { expect_error(get_labels(list(a = 1)), "Cannot extract labels") }) test_that("get_labels() priority: labels > label", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("id1", "id2", "id3") net <- as_cograph(mat) # Default: uses label column (which comes from rownames) expect_equal(get_labels(net), c("id1", "id2", "id3")) # Add 'label' column - should use it net$nodes$label <- c("Label1", "Label2", "Label3") expect_equal(get_labels(net), c("Label1", "Label2", "Label3")) # Add 'labels' column - should take priority over 'label' net$nodes$labels <- c("Display1", "Display2", "Display3") expect_equal(get_labels(net), c("Display1", "Display2", "Display3")) }) # ============================================================================= # set_nodes() Tests # ============================================================================= test_that("set_nodes() replaces nodes data frame", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) new_nodes <- data.frame(id = 1:3, label = c("X", "Y", "Z")) net <- set_nodes(net, new_nodes) expect_equal(get_labels(net), c("X", "Y", "Z")) }) test_that("set_nodes() adds id column if missing", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) new_nodes <- data.frame(label = c("A", "B", "C")) net <- set_nodes(net, new_nodes) expect_true("id" %in% names(get_nodes(net))) expect_equal(get_nodes(net)$id, 1:3) }) test_that("set_nodes() adds label column if missing", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) new_nodes <- data.frame(id = 1:3) net <- set_nodes(net, new_nodes) expect_true("label" %in% names(get_nodes(net))) }) test_that("set_nodes() errors on non-cograph_network", { expect_error(set_nodes(list(a = 1), data.frame(id = 1)), "must be a cograph_network") }) test_that("set_nodes() errors on non-data.frame nodes", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) expect_error(set_nodes(net, c(1, 2, 3)), "must be a data frame") }) # ============================================================================= # set_edges() Tests # ============================================================================= test_that("set_edges() replaces edges", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) new_edges <- data.frame(from = c(1, 2), to = c(2, 3), weight = c(0.9, 0.1)) net <- set_edges(net, new_edges) edges <- get_edges(net) expect_equal(nrow(edges), 2) expect_equal(edges$weight, c(0.9, 0.1)) }) test_that("set_edges() adds weight column if missing", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) new_edges <- data.frame(from = c(1, 2), to = c(2, 3)) net <- set_edges(net, new_edges) edges <- get_edges(net) expect_true("weight" %in% names(edges)) expect_equal(edges$weight, c(1, 1)) }) test_that("set_edges() errors without from/to columns", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) expect_error( set_edges(net, data.frame(source = 1, target = 2)), "must have 'from' and 'to' columns" ) }) test_that("set_edges() errors on non-cograph_network", { expect_error( set_edges(list(a = 1), data.frame(from = 1, to = 2)), "must be a cograph_network" ) }) test_that("set_edges() errors on non-data.frame edges", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) expect_error(set_edges(net, c(1, 2, 3)), "must be a data frame") }) # ============================================================================= # set_layout() Tests # ============================================================================= test_that("set_layout() sets layout from data.frame", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) layout <- data.frame(x = c(0, 1, 0.5), y = c(0, 0, 1)) net <- set_layout(net, layout) nodes <- get_nodes(net) expect_equal(nodes$x, c(0, 1, 0.5)) expect_equal(nodes$y, c(0, 0, 1)) }) test_that("set_layout() sets layout from matrix", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) layout_mat <- matrix(c(0, 1, 0.5, 0, 0, 1), ncol = 2) net <- set_layout(net, layout_mat) nodes <- get_nodes(net) expect_equal(nodes$x, c(0, 1, 0.5)) expect_equal(nodes$y, c(0, 0, 1)) }) test_that("set_layout() errors without x/y columns", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) expect_error( set_layout(net, data.frame(a = 1:3, b = 4:6)), "must have 'x' and 'y' columns" ) }) test_that("set_layout() errors on mismatched rows", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) expect_error( set_layout(net, data.frame(x = 1:5, y = 1:5)), "same number of rows" ) }) test_that("set_layout() errors on non-cograph_network", { expect_error( set_layout(list(a = 1), data.frame(x = 1, y = 1)), "must be a cograph_network" ) }) # ============================================================================= # n_nodes() Tests # ============================================================================= test_that("n_nodes() returns correct count", { mat <- matrix(c(0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0), nrow = 4) net <- as_cograph(mat) expect_equal(n_nodes(net), 4) }) test_that("n_nodes() returns 0 for empty network", { nodes <- data.frame(id = integer(0), label = character(0)) net <- .create_cograph_network(nodes = nodes, edges = NULL, directed = FALSE) expect_equal(n_nodes(net), 0) }) test_that("n_nodes() errors on non-cograph_network", { expect_error(n_nodes(matrix(1:4, 2, 2)), "Cannot count nodes") expect_error(n_nodes(list(a = 1)), "Cannot count nodes") }) # ============================================================================= # n_edges() Tests # ============================================================================= test_that("n_edges() returns correct count", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) # Undirected: 3 edges (each pair counted once) expect_true(n_edges(net) > 0) }) test_that("n_edges() returns 0 for network with no edges", { nodes <- data.frame(id = 1:3, label = c("A", "B", "C")) edges <- data.frame(from = integer(0), to = integer(0), weight = numeric(0)) net <- .create_cograph_network(nodes = nodes, edges = edges, directed = FALSE) expect_equal(n_edges(net), 0) }) test_that("n_edges() errors on non-cograph_network", { expect_error(n_edges(matrix(1:4, 2, 2)), "Cannot count edges") expect_error(n_edges(42), "Cannot count edges") }) # ============================================================================= # is_directed() Tests # ============================================================================= test_that("is_directed() returns FALSE for symmetric matrix", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) expect_false(is_directed(net)) }) test_that("is_directed() returns TRUE for asymmetric matrix", { mat <- matrix(c(0, 1, 0, 0, 0, 1, 0, 0, 0), nrow = 3) net <- as_cograph(mat) expect_true(is_directed(net)) }) test_that("is_directed() works with igraph", { skip_if_not_installed("igraph") g_dir <- igraph::make_ring(5, directed = TRUE) g_undir <- igraph::make_ring(5, directed = FALSE) expect_true(is_directed(g_dir)) expect_false(is_directed(g_undir)) }) test_that("is_directed() errors on unknown object", { expect_error(is_directed(list(a = 1)), "Cannot determine directedness") expect_error(is_directed(42), "Cannot determine directedness") }) # ============================================================================= # nodes() Tests (deprecated function) # ============================================================================= test_that("nodes() returns same as get_nodes() (deprecated)", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("A", "B", "C") net <- as_cograph(mat) result1 <- nodes(net) result2 <- get_nodes(net) expect_equal(result1, result2) }) # ============================================================================= # set_groups() Tests # ============================================================================= test_that("set_groups() works with named list", { mat <- create_symmetric_matrix(6) net <- as_cograph(mat) groups_list <- list( G1 = c("N1", "N2", "N3"), G2 = c("N4", "N5", "N6") ) net <- set_groups(net, groups_list) result <- get_groups(net) expect_true(is.data.frame(result)) expect_true("node" %in% names(result)) expect_true("group" %in% names(result)) expect_equal(nrow(result), 6) }) test_that("set_groups() works with vector", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) groups_vec <- c("A", "A", "B", "B") net <- set_groups(net, groups_vec) result <- get_groups(net) expect_equal(nrow(result), 4) }) test_that("set_groups() works with layers vector argument", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) net <- set_groups(net, nodes = c("N1", "N2", "N3", "N4"), layers = c("Top", "Top", "Bottom", "Bottom") ) result <- get_groups(net) expect_true("layer" %in% names(result)) expect_equal(nrow(result), 4) }) test_that("set_groups() works with clusters vector argument", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) net <- set_groups(net, nodes = c("N1", "N2", "N3", "N4"), clusters = c("C1", "C1", "C2", "C2") ) result <- get_groups(net) expect_true("cluster" %in% names(result)) }) test_that("set_groups() works with data.frame", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) df <- data.frame( nodes = c("N1", "N2", "N3", "N4"), layers = c("A", "A", "B", "B") ) net <- set_groups(net, df) result <- get_groups(net) # Should normalize "nodes" to "node" and "layers" to "layer" expect_true("node" %in% names(result)) expect_true("layer" %in% names(result)) }) test_that("set_groups() respects type parameter", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) net_layer <- set_groups(net, c("A", "A", "B", "B"), type = "layer") net_cluster <- set_groups(net, c("A", "A", "B", "B"), type = "cluster") expect_true("layer" %in% names(get_groups(net_layer))) expect_true("cluster" %in% names(get_groups(net_cluster))) }) test_that("set_groups() errors on duplicate node assignments", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) df <- data.frame( node = c("N1", "N1", "N3", "N4"), # N1 is duplicated group = c("A", "B", "A", "B") ) expect_error(set_groups(net, df), "Duplicate node assignments") }) test_that("set_groups() errors on missing nodes", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) df <- data.frame( node = c("X1", "X2", "X3", "X4"), # None of these exist group = c("A", "A", "B", "B") ) expect_error(set_groups(net, df), "Nodes not found") }) test_that("set_groups() errors on incomplete node assignment", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) df <- data.frame( node = c("N1", "N2"), # Missing N3, N4 group = c("A", "B") ) expect_error(set_groups(net, df), "Nodes missing from group assignment") }) test_that("set_groups() errors on only one group", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) # All same group expect_error( set_groups(net, c("A", "A", "A", "A")), "At least 2 groups are required" ) }) test_that("set_groups() errors on mismatched vector lengths", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) expect_error( set_groups(net, layers = c("A", "B")), # Only 2 elements "must match number of nodes" ) }) test_that("set_groups() errors on non-cograph_network", { expect_error( set_groups(list(a = 1), c("A", "B")), "must be a cograph_network" ) }) test_that("set_groups() errors without groups or vectors", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) expect_error( set_groups(net), "Must provide either 'groups' or vector arguments" ) }) test_that("set_groups() works with community detection method", { skip_if_not_installed("igraph") # Create a network with clear community structure mat <- matrix(0, 6, 6) mat[1, 2] <- mat[2, 1] <- 0.9 mat[1, 3] <- mat[3, 1] <- 0.8 mat[2, 3] <- mat[3, 2] <- 0.85 mat[4, 5] <- mat[5, 4] <- 0.9 mat[4, 6] <- mat[6, 4] <- 0.8 mat[5, 6] <- mat[6, 5] <- 0.85 mat[3, 4] <- mat[4, 3] <- 0.1 # Weak inter-community link rownames(mat) <- colnames(mat) <- paste0("N", 1:6) net <- as_cograph(mat) net <- set_groups(net, "louvain") result <- get_groups(net) expect_true(is.data.frame(result)) expect_equal(nrow(result), 6) }) # ============================================================================= # get_groups() Tests # ============================================================================= test_that("get_groups() returns NULL when no groups set", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) expect_null(get_groups(net)) }) test_that("get_groups() returns data frame after set_groups()", { mat <- create_symmetric_matrix(4) net <- as_cograph(mat) net <- set_groups(net, c("A", "A", "B", "B")) result <- get_groups(net) expect_true(is.data.frame(result)) expect_equal(nrow(result), 4) }) test_that("get_groups() errors on non-cograph_network", { expect_error(get_groups(list(a = 1)), "must be a cograph_network") }) # ============================================================================= # Edge cases and integration tests # ============================================================================= test_that("cograph_network works with very small networks", { # Single node mat <- matrix(0, 1, 1) rownames(mat) <- colnames(mat) <- "A" net <- as_cograph(mat) expect_equal(n_nodes(net), 1) expect_equal(n_edges(net), 0) }) test_that("cograph_network works with disconnected networks", { # 4 nodes, only 1-2 connected, 3-4 isolated mat <- matrix(0, 4, 4) mat[1, 2] <- mat[2, 1] <- 1 rownames(mat) <- colnames(mat) <- paste0("N", 1:4) net <- as_cograph(mat) expect_equal(n_nodes(net), 4) # Should have 1 edge (1-2) expect_equal(n_edges(net), 1) }) test_that("cograph_network handles negative weights", { mat <- matrix(c(0, -0.5, 0.3, -0.5, 0, 0.2, 0.3, 0.2, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("A", "B", "C") net <- as_cograph(mat) expect_s3_class(net, "cograph_network") edges <- get_edges(net) expect_true(any(edges$weight < 0)) }) test_that("cograph_network handles sparse networks", { mat <- matrix(0, 10, 10) mat[1, 2] <- mat[2, 1] <- 0.5 mat[3, 4] <- mat[4, 3] <- 0.3 rownames(mat) <- colnames(mat) <- paste0("N", 1:10) net <- as_cograph(mat) expect_equal(n_nodes(net), 10) expect_equal(n_edges(net), 2) }) test_that("cograph_network preserves special characters in labels", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("Node 1", "Node-2", "Node_3") net <- as_cograph(mat) labels <- get_labels(net) expect_equal(labels, c("Node 1", "Node-2", "Node_3")) }) test_that("cograph_network handles matrix without row/colnames", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) # No rownames/colnames net <- as_cograph(mat) expect_equal(n_nodes(net), 3) labels <- get_labels(net) expect_true(all(nchar(labels) > 0)) # Should have auto-generated labels }) test_that("chained setter operations work correctly", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) rownames(mat) <- colnames(mat) <- c("A", "B", "C") net <- as_cograph(mat) # Chain multiple operations net <- set_nodes(net, data.frame(id = 1:3, label = c("X", "Y", "Z"))) net <- set_layout(net, data.frame(x = c(0, 1, 0.5), y = c(0, 0, 1))) net <- set_groups(net, c("G1", "G1", "G2")) expect_equal(get_labels(net), c("X", "Y", "Z")) expect_equal(get_nodes(net)$x, c(0, 1, 0.5)) expect_true(!is.null(get_groups(net))) }) test_that("S3 class hierarchy is correct", { mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3) net <- as_cograph(mat) classes <- class(net) expect_true("cograph_network" %in% classes) expect_true("list" %in% classes) })