tests/testthat/test-coverage-input-igraph-41.R

# =============================================================================
# Test Coverage for input-igraph.R - Series 41
# =============================================================================
# Additional comprehensive tests targeting edge cases and branches
# that may not be covered in test-coverage-input-igraph-42.R

# Make internal functions available for testing
skip_on_cran()

parse_igraph <- cograph:::parse_igraph
apply_igraph_layout <- cograph:::apply_igraph_layout
apply_igraph_layout_by_name <- cograph:::apply_igraph_layout_by_name
network_to_igraph <- cograph:::network_to_igraph
normalize_coords <- cograph:::normalize_coords

# =============================================================================
# Test: parse_igraph() - Edge Cases for Vertex Names
# =============================================================================

test_that("parse_igraph handles graph with empty name attribute", {
  skip_if_not_installed("igraph")

  # Create graph with empty string names
  g <- igraph::make_ring(3)
  igraph::V(g)$name <- c("", "", "")
  result <- parse_igraph(g)

  # Empty strings are still valid names (not NA)
  expect_equal(result$nodes$label, c("", "", ""))
})

test_that("parse_igraph handles graph with numeric vertex names", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(4)
  igraph::V(g)$name <- c(100, 200, 300, 400)
  result <- parse_igraph(g)

  # Numeric names are preserved as-is
  expect_equal(as.character(result$nodes$label), c("100", "200", "300", "400"))
})

test_that("parse_igraph preserves vertex names with special characters", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(3)
  igraph::V(g)$name <- c("Node A", "Node-B", "Node_C")
  result <- parse_igraph(g)

  expect_equal(result$nodes$label, c("Node A", "Node-B", "Node_C"))
})

# =============================================================================
# Test: parse_igraph() - Complex Vertex Attributes
# =============================================================================

test_that("parse_igraph handles multiple vertex attributes", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(4)
  igraph::V(g)$name <- c("A", "B", "C", "D")
  igraph::V(g)$color <- c("red", "blue", "green", "yellow")
  igraph::V(g)$size <- c(10, 20, 30, 40)
  igraph::V(g)$shape <- c("circle", "square", "circle", "square")
  igraph::V(g)$group <- c(1, 1, 2, 2)
  igraph::V(g)$score <- c(0.1, 0.2, 0.3, 0.4)

  result <- parse_igraph(g)

  expect_true("color" %in% names(result$nodes))
  expect_true("size" %in% names(result$nodes))
  expect_true("shape" %in% names(result$nodes))
  expect_true("group" %in% names(result$nodes))
  expect_true("score" %in% names(result$nodes))

  expect_equal(result$nodes$shape, c("circle", "square", "circle", "square"))
  expect_equal(result$nodes$group, c(1, 1, 2, 2))
})

test_that("parse_igraph handles vertex attributes with NA values", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(3)
  igraph::V(g)$name <- c("A", "B", "C")
  igraph::V(g)$size <- c(10, NA, 30)
  igraph::V(g)$label_color <- c("black", "red", NA)

  result <- parse_igraph(g)

  expect_equal(result$nodes$size, c(10, NA, 30))
  expect_equal(result$nodes$label_color, c("black", "red", NA))
})

# =============================================================================
# Test: parse_igraph() - Complex Edge Attributes
# =============================================================================

test_that("parse_igraph handles multiple edge attributes", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(4)
  igraph::E(g)$weight <- c(0.5, 1.0, 1.5, 2.0)
  igraph::E(g)$color <- c("red", "green", "blue", "black")
  igraph::E(g)$lty <- c(1, 2, 1, 2)
  igraph::E(g)$label <- c("e1", "e2", "e3", "e4")
  igraph::E(g)$width <- c(1, 2, 3, 4)

  result <- parse_igraph(g)

  expect_true("color" %in% names(result$edges))
  expect_true("lty" %in% names(result$edges))
  expect_true("label" %in% names(result$edges))
  expect_true("width" %in% names(result$edges))

  expect_equal(result$edges$label, c("e1", "e2", "e3", "e4"))
})

test_that("parse_igraph handles edge attributes with NA values", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(3)
  igraph::E(g)$weight <- c(1, NA, 2)
  igraph::E(g)$type <- c("A", NA, "C")

  result <- parse_igraph(g)

  expect_equal(result$weights, c(1, NA, 2))
  expect_equal(result$edges$type, c("A", NA, "C"))
})

test_that("parse_igraph handles negative and zero weights", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(4)
  igraph::E(g)$weight <- c(-1, 0, 0.5, -0.5)

  result <- parse_igraph(g)

  expect_equal(result$weights, c(-1, 0, 0.5, -0.5))
})

# =============================================================================
# Test: parse_igraph() - Various Graph Types
# =============================================================================

test_that("parse_igraph handles bipartite graph", {
  skip_if_not_installed("igraph")

  g <- igraph::make_full_bipartite_graph(3, 2)
  result <- parse_igraph(g)

  expect_equal(nrow(result$nodes), 5)
  # Bipartite full graph: 3*2 = 6 edges
  expect_equal(nrow(result$edges), 6)
})

test_that("parse_igraph handles tree graph", {
  skip_if_not_installed("igraph")

  g <- igraph::make_tree(7, children = 2, mode = "undirected")
  result <- parse_igraph(g)

  expect_equal(nrow(result$nodes), 7)
  expect_equal(nrow(result$edges), 6)  # tree has n-1 edges
})

test_that("parse_igraph handles lattice graph", {
  skip_if_not_installed("igraph")

  g <- igraph::make_lattice(c(3, 3))
  result <- parse_igraph(g)

  expect_equal(nrow(result$nodes), 9)
})

test_that("parse_igraph handles large graph", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(100)
  result <- parse_igraph(g)

  expect_equal(nrow(result$nodes), 100)
  expect_equal(nrow(result$edges), 100)
})

test_that("parse_igraph handles directed graph with multiple edge attributes", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(4, directed = TRUE)
  igraph::E(g)$weight <- c(0.1, 0.2, 0.3, 0.4)
  igraph::E(g)$type <- c("forward", "forward", "back", "back")

  result <- parse_igraph(g)

  expect_true(result$directed)
  expect_true("type" %in% names(result$edges))
  expect_equal(result$edges$type, c("forward", "forward", "back", "back"))
})

# =============================================================================
# Test: network_to_igraph() - Edge Cases
# =============================================================================

test_that("network_to_igraph handles directed cograph_network", {
  skip_if_not_installed("igraph")

  mat <- matrix(c(0, 1, 0,
                  0, 0, 1,
                  1, 0, 0), nrow = 3, byrow = TRUE)
  rownames(mat) <- colnames(mat) <- c("A", "B", "C")
  net <- as_cograph(mat, directed = TRUE)

  g <- network_to_igraph(net)

  expect_true(igraph::is_directed(g))
  expect_equal(igraph::ecount(g), 3)
})

test_that("network_to_igraph handles network with many edges", {
  skip_if_not_installed("igraph")

  mat <- create_test_matrix(n = 10, density = 0.8, weighted = TRUE)
  rownames(mat) <- colnames(mat) <- LETTERS[1:10]
  net <- as_cograph(mat)

  g <- network_to_igraph(net)

  expect_true(inherits(g, "igraph"))
  expect_equal(igraph::vcount(g), 10)
})

test_that("network_to_igraph handles network with no labels", {
  skip_if_not_installed("igraph")

  # Create a network and remove labels
  mat <- matrix(c(0, 1, 1, 0), nrow = 2)
  net <- as_cograph(mat)
  net$nodes$label <- NULL

  # Should still work
  g <- network_to_igraph(net)
  expect_true(inherits(g, "igraph"))
  expect_equal(igraph::vcount(g), 2)
})

test_that("network_to_igraph handles network with NULL weight column", {
  skip_if_not_installed("igraph")

  mat <- matrix(c(0, 1, 1, 0), nrow = 2)
  net <- as_cograph(mat)
  net$edges$weight <- NULL

  g <- network_to_igraph(net)

  expect_true(inherits(g, "igraph"))
  # Weight attribute should not be set
  expect_false("weight" %in% igraph::edge_attr_names(g))
})

test_that("network_to_igraph handles single-node network", {
  skip_if_not_installed("igraph")

  mat <- matrix(0, nrow = 1, ncol = 1)
  rownames(mat) <- colnames(mat) <- "A"
  net <- as_cograph(mat)

  g <- network_to_igraph(net)

  expect_equal(igraph::vcount(g), 1)
  expect_equal(igraph::ecount(g), 0)
})

# =============================================================================
# Test: normalize_coords() - Edge Cases
# =============================================================================

test_that("normalize_coords handles two nodes in same position", {
  coords <- matrix(c(5, 5, 10, 10), ncol = 2)
  result <- normalize_coords(coords)

  # Should have valid coordinates
  expect_equal(nrow(result), 2)
  expect_true(all(is.numeric(result)))
})

test_that("normalize_coords handles very large coordinate values", {
  coords <- matrix(c(1e10, 1e10, 2e10, 1e10, 1.5e10, 2e10), ncol = 2)
  result <- normalize_coords(coords)

  expect_true(all(result >= 0.1 - 1e-10))
  expect_true(all(result <= 0.9 + 1e-10))
})

test_that("normalize_coords handles very small coordinate differences", {
  coords <- matrix(c(1e-10, 2e-10, 3e-10, 1e-10, 2e-10, 3e-10), ncol = 2)
  result <- normalize_coords(coords)

  expect_true(all(result >= 0.1 - 1e-10))
  expect_true(all(result <= 0.9 + 1e-10))
})

test_that("normalize_coords handles mixed positive and negative coordinates", {
  coords <- matrix(c(-50, 0, 50, -50, 0, 50), ncol = 2)
  result <- normalize_coords(coords)

  # Check min and max are at 0.1 and 0.9
  expect_equal(min(result[, 1]), 0.1)
  expect_equal(max(result[, 1]), 0.9)
})

test_that("normalize_coords handles 2-node case", {
  coords <- matrix(c(0, 10, 0, 10), ncol = 2)
  result <- normalize_coords(coords)

  # Should properly scale
  expect_equal(nrow(result), 2)
  expect_equal(result[1, 1], 0.1)
  expect_equal(result[2, 1], 0.9)
})

# =============================================================================
# Test: apply_igraph_layout_by_name() - Additional Layout Aliases
# =============================================================================

test_that("apply_igraph_layout_by_name works with full layout names", {
  skip_if_not_installed("igraph")

  mat <- matrix(c(0, 1, 1, 1,
                  1, 0, 1, 1,
                  1, 1, 0, 1,
                  1, 1, 1, 0), nrow = 4)
  net <- as_cograph(mat)

  # Test various full names
  layouts <- c(
    "layout_with_fr",
    "layout_with_kk",
    "layout_in_circle",
    "layout_as_star",
    "layout_on_grid",
    "layout_randomly"
  )

  for (layout in layouts) {
    coords <- apply_igraph_layout_by_name(net, layout, seed = 42)
    expect_equal(nrow(coords), 4,
                 info = paste("Failed for layout:", layout))
    expect_true(all(c("x", "y") %in% names(coords)),
                info = paste("Missing x/y for layout:", layout))
  }
})

test_that("apply_igraph_layout_by_name works with igraph_ prefix", {
  skip_if_not_installed("igraph")

  mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3)
  net <- as_cograph(mat)

  prefixed <- c(
    "igraph_nicely",
    "igraph_fr",
    "igraph_kk",
    "igraph_star",
    "igraph_grid",
    "igraph_random"
  )

  for (layout in prefixed) {
    coords <- apply_igraph_layout_by_name(net, layout, seed = 42)
    expect_equal(nrow(coords), 3,
                 info = paste("Failed for layout:", layout))
  }
})

test_that("apply_igraph_layout_by_name MDS layout works", {
  skip_if_not_installed("igraph")

  # MDS needs connected graph
  mat <- create_test_topology("complete", n = 5)
  net <- as_cograph(mat)

  coords <- suppressWarnings(
    apply_igraph_layout_by_name(net, "mds", seed = 42)
  )

  expect_equal(nrow(coords), 5)
})

test_that("apply_igraph_layout_by_name graphopt layout works", {
  skip_if_not_installed("igraph")

  mat <- create_test_topology("complete", n = 5)
  net <- as_cograph(mat)

  coords <- apply_igraph_layout_by_name(net, "igraph_graphopt", seed = 42)

  expect_equal(nrow(coords), 5)
})

# =============================================================================
# Test: apply_igraph_layout() - Direct Function Use
# =============================================================================

test_that("apply_igraph_layout works with layout_with_kk", {
  skip_if_not_installed("igraph")

  mat <- matrix(c(0, 1, 1, 1, 0, 1, 1, 1, 0), nrow = 3)
  net <- as_cograph(mat)

  coords <- apply_igraph_layout(net, igraph::layout_with_kk)

  expect_equal(nrow(coords), 3)
  expect_true(all(coords$x >= 0.1 & coords$x <= 0.9))
  expect_true(all(coords$y >= 0.1 & coords$y <= 0.9))
})

test_that("apply_igraph_layout works with layout_as_star", {
  skip_if_not_installed("igraph")

  mat <- matrix(c(0, 1, 1, 1, 1,
                  1, 0, 0, 0, 0,
                  1, 0, 0, 0, 0,
                  1, 0, 0, 0, 0,
                  1, 0, 0, 0, 0), nrow = 5)
  net <- as_cograph(mat)

  coords <- apply_igraph_layout(net, igraph::layout_as_star)

  expect_equal(nrow(coords), 5)
})

test_that("apply_igraph_layout works with layout_on_grid", {
  skip_if_not_installed("igraph")

  mat <- create_test_matrix(n = 9, density = 0.3)
  net <- as_cograph(mat)

  coords <- apply_igraph_layout(net, igraph::layout_on_grid)

  expect_equal(nrow(coords), 9)
})

test_that("apply_igraph_layout handles empty network gracefully", {
  skip_if_not_installed("igraph")

  mat <- matrix(0, 4, 4)
  rownames(mat) <- colnames(mat) <- LETTERS[1:4]
  net <- as_cograph(mat)

  # Should work even with no edges
  coords <- apply_igraph_layout(net, igraph::layout_in_circle)

  expect_equal(nrow(coords), 4)
})

# =============================================================================
# Test: Round-Trip Conversion Edge Cases
# =============================================================================

test_that("igraph to cograph preserves all vertex attribute types", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(3)
  igraph::V(g)$name <- c("A", "B", "C")
  igraph::V(g)$numeric_attr <- c(1.5, 2.5, 3.5)
  igraph::V(g)$integer_attr <- c(1L, 2L, 3L)
  igraph::V(g)$char_attr <- c("x", "y", "z")
  igraph::V(g)$logical_attr <- c(TRUE, FALSE, TRUE)

  result <- parse_igraph(g)

  expect_equal(result$nodes$numeric_attr, c(1.5, 2.5, 3.5))
  expect_equal(result$nodes$integer_attr, c(1L, 2L, 3L))
  expect_equal(result$nodes$char_attr, c("x", "y", "z"))
  expect_equal(result$nodes$logical_attr, c(TRUE, FALSE, TRUE))
})

test_that("igraph to cograph preserves all edge attribute types", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(4)
  igraph::E(g)$weight <- c(0.1, 0.2, 0.3, 0.4)
  igraph::E(g)$numeric_attr <- c(1.1, 2.2, 3.3, 4.4)
  igraph::E(g)$char_attr <- c("a", "b", "c", "d")
  igraph::E(g)$logical_attr <- c(TRUE, FALSE, TRUE, FALSE)

  result <- parse_igraph(g)

  expect_equal(result$edges$numeric_attr, c(1.1, 2.2, 3.3, 4.4))
  expect_equal(result$edges$char_attr, c("a", "b", "c", "d"))
  expect_equal(result$edges$logical_attr, c(TRUE, FALSE, TRUE, FALSE))
})

# =============================================================================
# Test: Integration - Full Workflow
# =============================================================================

test_that("full workflow: parse igraph -> apply layout -> coordinates valid", {
  skip_if_not_installed("igraph")

  # Create igraph with attributes
  g <- igraph::make_full_graph(5)
  igraph::V(g)$name <- LETTERS[1:5]
  igraph::E(g)$weight <- runif(igraph::ecount(g))

  # Parse to cograph format
  parsed <- parse_igraph(g)

  # Create network directly from igraph (avoids edge duplication)
  net <- as_cograph(g)

  # Apply layout
  coords <- apply_igraph_layout_by_name(net, "fr", seed = 42)

  # Validate
  expect_equal(nrow(coords), 5)
  expect_true(all(coords$x >= 0.1 & coords$x <= 0.9))
  expect_true(all(coords$y >= 0.1 & coords$y <= 0.9))
})

test_that("workflow: cograph_network to igraph and back preserves structure", {
  skip_if_not_installed("igraph")

  # Create cograph_network
  mat <- create_test_topology("complete", n = 4)
  rownames(mat) <- colnames(mat) <- c("W", "X", "Y", "Z")
  net <- as_cograph(mat)

  # Convert to igraph
  g <- network_to_igraph(net)

  # Convert back
  parsed <- parse_igraph(g)

  # Verify
  expect_equal(nrow(parsed$nodes), 4)
  expect_equal(parsed$nodes$label, c("W", "X", "Y", "Z"))
})

# =============================================================================
# Test: Error Handling and Validation
# =============================================================================

test_that("parse_igraph with numeric input errors correctly", {
  skip_if_not_installed("igraph")

  expect_error(parse_igraph(123), "Input must be an igraph object")
})

test_that("parse_igraph with NULL input errors correctly", {
  skip_if_not_installed("igraph")

  expect_error(parse_igraph(NULL), "Input must be an igraph object")
})

test_that("parse_igraph with vector input errors correctly", {
  skip_if_not_installed("igraph")

  expect_error(parse_igraph(c(1, 2, 3)), "Input must be an igraph object")
})

test_that("network_to_igraph with data.frame errors correctly", {
  skip_if_not_installed("igraph")

  df <- data.frame(from = c(1, 2), to = c(2, 3))
  expect_error(network_to_igraph(df),
               "network must be a CographNetwork or cograph_network object")
})

test_that("network_to_igraph with matrix errors correctly", {
  skip_if_not_installed("igraph")

  mat <- matrix(1:4, 2, 2)
  expect_error(network_to_igraph(mat),
               "network must be a CographNetwork or cograph_network object")
})

test_that("apply_igraph_layout_by_name with invalid layout errors correctly", {
  skip_if_not_installed("igraph")

  mat <- matrix(c(0, 1, 1, 0), nrow = 2)
  net <- as_cograph(mat)

  expect_error(apply_igraph_layout_by_name(net, "invalid_layout_xyz"),
               "Unknown igraph layout")
})

test_that("error message includes available layout options", {
  skip_if_not_installed("igraph")

  mat <- matrix(c(0, 1, 1, 0), nrow = 2)
  net <- as_cograph(mat)

  err <- tryCatch(
    apply_igraph_layout_by_name(net, "bad_layout"),
    error = function(e) conditionMessage(e)
  )

  expect_true(grepl("kk", err))
  expect_true(grepl("fr", err))
})

# =============================================================================
# Test: Graph Topologies
# =============================================================================

test_that("parse_igraph handles Watts-Strogatz small world graph", {
  skip_if_not_installed("igraph")

  g <- igraph::sample_smallworld(dim = 1, size = 10, nei = 2, p = 0.1)
  result <- parse_igraph(g)

  expect_equal(nrow(result$nodes), 10)
  expect_false(result$directed)
})

test_that("parse_igraph handles Barabasi-Albert graph", {
  skip_if_not_installed("igraph")

  g <- igraph::sample_pa(n = 20, m = 2, directed = FALSE)
  result <- parse_igraph(g)

  expect_equal(nrow(result$nodes), 20)
})

test_that("parse_igraph handles Erdos-Renyi random graph", {
  skip_if_not_installed("igraph")

  set.seed(42)
  g <- igraph::sample_gnp(n = 15, p = 0.3)
  result <- parse_igraph(g)

  expect_equal(nrow(result$nodes), 15)
})

test_that("parse_igraph handles Kautz graph", {
  skip_if_not_installed("igraph")

  g <- igraph::make_kautz_graph(m = 2, n = 1)
  result <- parse_igraph(g)

  expect_true(inherits(result, "list"))
  expect_true(result$directed)  # Kautz graphs are directed
})

test_that("parse_igraph handles De Bruijn graph", {
  skip_if_not_installed("igraph")

  g <- igraph::make_de_bruijn_graph(m = 2, n = 2)
  result <- parse_igraph(g)

  expect_true(inherits(result, "list"))
  expect_true(result$directed)  # De Bruijn graphs are directed
})

# =============================================================================
# Test: Coordinate Normalization with Extreme Values
# =============================================================================

test_that("normalize_coords preserves relative positions", {
  coords <- matrix(c(0, 50, 100, 0, 50, 100), ncol = 2)
  result <- normalize_coords(coords)

  # Middle point should be at 0.5
  expect_equal(result[2, 1], 0.5)
  expect_equal(result[2, 2], 0.5)
})

test_that("normalize_coords handles 4 nodes in a square pattern", {
  coords <- matrix(c(0, 0, 10, 10, 0, 10, 0, 10), ncol = 2)
  result <- normalize_coords(coords)

  # All coordinates should be between 0.1 and 0.9
  expect_true(all(result >= 0.1 - 1e-10))
  expect_true(all(result <= 0.9 + 1e-10))
})

test_that("normalize_coords handles infinity values by using na.rm", {
  # This tests the na.rm = TRUE in range()
  coords <- matrix(c(0, 10, 20, 0, 10, 20), ncol = 2)
  # We can't pass Inf directly, but we can test normal values work
  result <- normalize_coords(coords)

  expect_true(all(is.finite(result)))
})

# =============================================================================
# Test: Layout Edge Cases
# =============================================================================

test_that("layout works on disconnected graph", {
  skip_if_not_installed("igraph")

  # Create disconnected graph (two components)
  mat <- create_test_topology("disconnected", n = 6)
  net <- as_cograph(mat)

  # Should still produce valid layout
  coords <- apply_igraph_layout_by_name(net, "ni", seed = 42)

  expect_equal(nrow(coords), 6)
  # Allow small floating-point tolerance (e.g., 0.90000000000000013)
  expect_true(all(coords$x >= 0.1 - 1e-10 & coords$x <= 0.9 + 1e-10))
})

test_that("layout handles graph with self-loop", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(3)
  g <- igraph::add_edges(g, c(1, 1))  # Self-loop

  result <- parse_igraph(g)
  net <- as_cograph(result$nodes, result$edges, directed = FALSE)

  # Should not error
  coords <- apply_igraph_layout_by_name(net, "ci", seed = 42)
  expect_equal(nrow(coords), 3)
})

test_that("layout_as_tree handles non-tree structure", {
  skip_if_not_installed("igraph")

  # Complete graph is not a tree
  mat <- create_test_topology("complete", n = 4)
  net <- as_cograph(mat)

  # Tree layout should still work (may just not look like a tree)
  coords <- suppressWarnings(
    apply_igraph_layout_by_name(net, "tr", seed = 42)
  )

  expect_equal(nrow(coords), 4)
})

# =============================================================================
# Test: CographNetwork R6 Compatibility
# =============================================================================

test_that("parse_igraph result can create CographNetwork R6", {
  skip_if_not_installed("igraph")

  g <- igraph::make_ring(5)
  igraph::V(g)$name <- LETTERS[1:5]

  parsed <- parse_igraph(g)

  # Create adjacency matrix from parsed data
  n <- nrow(parsed$nodes)
  mat <- matrix(0, n, n)
  rownames(mat) <- colnames(mat) <- parsed$nodes$label

  for (i in seq_len(nrow(parsed$edges))) {
    from_idx <- parsed$edges$from[i]
    to_idx <- parsed$edges$to[i]
    weight <- if (!is.null(parsed$edges$weight)) parsed$edges$weight[i] else 1
    mat[from_idx, to_idx] <- weight
    if (!parsed$directed) {
      mat[to_idx, from_idx] <- weight
    }
  }

  net <- CographNetwork$new(mat)
  expect_true(inherits(net, "CographNetwork"))
  expect_equal(net$n_nodes, 5)
})

test_that("apply_igraph_layout works with R6 and produces normalized coords", {
  skip_if_not_installed("igraph")

  mat <- create_test_topology("ring", n = 6)
  net <- CographNetwork$new(mat)

  coords <- apply_igraph_layout(net, igraph::layout_with_fr)

  # Verify normalization
  expect_true(all(coords$x >= 0.1 - 1e-10))
  expect_true(all(coords$x <= 0.9 + 1e-10))
  expect_true(all(coords$y >= 0.1 - 1e-10))
  expect_true(all(coords$y <= 0.9 + 1e-10))
})

# =============================================================================
# Test: Seed Parameter Behavior
# =============================================================================

test_that("different seeds produce different layouts for randomized algorithms", {
  skip_if_not_installed("igraph")

  mat <- create_test_matrix(n = 6, density = 0.5)
  net <- as_cograph(mat)

  coords1 <- apply_igraph_layout_by_name(net, "fr", seed = 1)
  coords2 <- apply_igraph_layout_by_name(net, "fr", seed = 999)

  # With high probability, different seeds produce different layouts
  # But this could occasionally be the same by chance, so we just check they run
  expect_equal(nrow(coords1), 6)
  expect_equal(nrow(coords2), 6)
})

test_that("NULL seed allows non-deterministic layouts", {
  skip_if_not_installed("igraph")

  mat <- create_test_matrix(n = 4, density = 0.5)
  net <- as_cograph(mat)

  # Should not error with NULL seed
  coords <- apply_igraph_layout_by_name(net, "rd", seed = NULL)
  expect_equal(nrow(coords), 4)
})

Try the cograph package in your browser

Any scripts or data that you put into this service are public.

cograph documentation built on April 1, 2026, 1:07 a.m.