Nothing
# =============================================================================
# Test Coverage for layout-registry.R
# =============================================================================
# Comprehensive tests for all layout registration functions and built-in layouts
# Helper function to create test networks
skip_on_cran()
create_test_network <- function(n = 5, edges = TRUE) {
mat <- matrix(0, n, n)
if (edges && n > 1) {
# Create some edges
for (i in 1:(n - 1)) {
mat[i, i + 1] <- 1
mat[i + 1, i] <- 1
}
}
rownames(mat) <- colnames(mat) <- paste0("N", 1:n)
CographNetwork$new(mat)
}
create_test_cograph <- function(n = 5, edges = TRUE) {
mat <- matrix(0, n, n)
if (edges && n > 1) {
for (i in 1:(n - 1)) {
mat[i, i + 1] <- 1
mat[i + 1, i] <- 1
}
}
rownames(mat) <- colnames(mat) <- paste0("N", 1:n)
as_cograph(mat)
}
# =============================================================================
# Test: register_builtin_layouts function
# =============================================================================
test_that("register_builtin_layouts registers circle layout", {
# Circle layout should be registered
expect_true("circle" %in% list_layouts())
fn <- get_layout("circle")
expect_true(is.function(fn))
})
test_that("register_builtin_layouts registers oval layout with alias", {
# Oval and ellipse should both be registered
expect_true("oval" %in% list_layouts())
expect_true("ellipse" %in% list_layouts())
# Both should return the same function
oval_fn <- get_layout("oval")
ellipse_fn <- get_layout("ellipse")
expect_true(is.function(oval_fn))
expect_true(is.function(ellipse_fn))
})
test_that("register_builtin_layouts registers spring layout with aliases", {
expect_true("spring" %in% list_layouts())
expect_true("fr" %in% list_layouts())
expect_true("fruchterman-reingold" %in% list_layouts())
spring_fn <- get_layout("spring")
fr_fn <- get_layout("fr")
fruchterman_fn <- get_layout("fruchterman-reingold")
expect_true(is.function(spring_fn))
expect_true(is.function(fr_fn))
expect_true(is.function(fruchterman_fn))
})
test_that("register_builtin_layouts registers groups layout", {
expect_true("groups" %in% list_layouts())
fn <- get_layout("groups")
expect_true(is.function(fn))
})
test_that("register_builtin_layouts registers grid layout", {
expect_true("grid" %in% list_layouts())
fn <- get_layout("grid")
expect_true(is.function(fn))
})
test_that("register_builtin_layouts registers random layout", {
expect_true("random" %in% list_layouts())
fn <- get_layout("random")
expect_true(is.function(fn))
})
test_that("register_builtin_layouts registers star layout", {
expect_true("star" %in% list_layouts())
fn <- get_layout("star")
expect_true(is.function(fn))
})
test_that("register_builtin_layouts registers bipartite layout", {
expect_true("bipartite" %in% list_layouts())
fn <- get_layout("bipartite")
expect_true(is.function(fn))
})
test_that("register_builtin_layouts registers custom layout", {
expect_true("custom" %in% list_layouts())
fn <- get_layout("custom")
expect_true(is.function(fn))
})
test_that("register_builtin_layouts registers gephi_fr layout with alias", {
expect_true("gephi_fr" %in% list_layouts())
expect_true("gephi" %in% list_layouts())
gephi_fr_fn <- get_layout("gephi_fr")
gephi_fn <- get_layout("gephi")
expect_true(is.function(gephi_fr_fn))
expect_true(is.function(gephi_fn))
})
# =============================================================================
# Test: Grid Layout Function
# =============================================================================
test_that("grid layout returns empty data frame for empty network", {
mat <- matrix(0, 0, 0)
net <- CographNetwork$new()
# Create a network object with n_nodes = 0
net_mock <- list(n_nodes = 0)
class(net_mock) <- "CographNetwork"
grid_fn <- get_layout("grid")
coords <- grid_fn(net_mock)
expect_equal(nrow(coords), 0)
expect_true("x" %in% names(coords))
expect_true("y" %in% names(coords))
})
test_that("grid layout returns center for single node", {
net <- list(n_nodes = 1)
class(net) <- "CographNetwork"
grid_fn <- get_layout("grid")
coords <- grid_fn(net)
expect_equal(nrow(coords), 1)
expect_equal(coords$x, 0.5)
expect_equal(coords$y, 0.5)
})
test_that("grid layout computes automatic grid dimensions", {
net <- list(n_nodes = 9)
class(net) <- "CographNetwork"
grid_fn <- get_layout("grid")
coords <- grid_fn(net)
expect_equal(nrow(coords), 9)
# 9 nodes should be in a 3x3 grid
expect_true(all(coords$x >= 0.1 & coords$x <= 0.9))
expect_true(all(coords$y >= 0.1 & coords$y <= 0.9))
})
test_that("grid layout respects custom ncol parameter", {
net <- list(n_nodes = 6)
class(net) <- "CographNetwork"
grid_fn <- get_layout("grid")
coords <- grid_fn(net, ncol = 2)
expect_equal(nrow(coords), 6)
# 6 nodes in 2 columns = 3 rows
unique_x <- unique(coords$x)
expect_equal(length(unique_x), 2)
})
test_that("grid layout handles non-square numbers of nodes", {
net <- list(n_nodes = 7)
class(net) <- "CographNetwork"
grid_fn <- get_layout("grid")
coords <- grid_fn(net)
expect_equal(nrow(coords), 7)
})
# =============================================================================
# Test: Random Layout Function
# =============================================================================
test_that("random layout returns coordinates in range", {
net <- list(n_nodes = 10)
class(net) <- "CographNetwork"
random_fn <- get_layout("random")
coords <- random_fn(net)
expect_equal(nrow(coords), 10)
expect_true(all(coords$x >= 0.1 & coords$x <= 0.9))
expect_true(all(coords$y >= 0.1 & coords$y <= 0.9))
})
test_that("random layout respects seed parameter", {
net <- list(n_nodes = 5)
class(net) <- "CographNetwork"
random_fn <- get_layout("random")
coords1 <- random_fn(net, seed = 42)
coords2 <- random_fn(net, seed = 42)
coords3 <- random_fn(net, seed = 123)
# Same seed should give same results
expect_equal(coords1$x, coords2$x)
expect_equal(coords1$y, coords2$y)
# Different seeds should give different results (with high probability)
# Note: There's a tiny chance this could fail randomly
expect_false(all(coords1$x == coords3$x))
})
test_that("random layout works without seed", {
net <- list(n_nodes = 5)
class(net) <- "CographNetwork"
random_fn <- get_layout("random")
coords <- random_fn(net)
expect_equal(nrow(coords), 5)
})
# =============================================================================
# Test: Star Layout Function
# =============================================================================
test_that("star layout returns empty data frame for empty network", {
net <- list(n_nodes = 0)
class(net) <- "CographNetwork"
star_fn <- get_layout("star")
coords <- star_fn(net)
expect_equal(nrow(coords), 0)
})
test_that("star layout returns center for single node", {
net <- list(n_nodes = 1)
class(net) <- "CographNetwork"
star_fn <- get_layout("star")
coords <- star_fn(net)
expect_equal(nrow(coords), 1)
expect_equal(coords$x, 0.5)
expect_equal(coords$y, 0.5)
})
test_that("star layout places center node at center", {
net <- list(n_nodes = 5)
class(net) <- "CographNetwork"
star_fn <- get_layout("star")
coords <- star_fn(net, center = 1)
expect_equal(coords$x[1], 0.5)
expect_equal(coords$y[1], 0.5)
})
test_that("star layout places other nodes in circle around center", {
net <- list(n_nodes = 5)
class(net) <- "CographNetwork"
star_fn <- get_layout("star")
coords <- star_fn(net, center = 3)
# Node 3 should be at center
expect_equal(coords$x[3], 0.5)
expect_equal(coords$y[3], 0.5)
# Other nodes should be at distance 0.4 from center
other_indices <- c(1, 2, 4, 5)
for (i in other_indices) {
dist <- sqrt((coords$x[i] - 0.5)^2 + (coords$y[i] - 0.5)^2)
expect_equal(dist, 0.4, tolerance = 0.001)
}
})
test_that("star layout works with two nodes", {
net <- list(n_nodes = 2)
class(net) <- "CographNetwork"
star_fn <- get_layout("star")
coords <- star_fn(net, center = 1)
expect_equal(nrow(coords), 2)
expect_equal(coords$x[1], 0.5)
expect_equal(coords$y[1], 0.5)
})
# =============================================================================
# Test: Bipartite Layout Function
# =============================================================================
test_that("bipartite layout returns empty data frame for empty network", {
net <- list(n_nodes = 0)
class(net) <- "CographNetwork"
bipartite_fn <- get_layout("bipartite")
coords <- bipartite_fn(net)
expect_equal(nrow(coords), 0)
})
test_that("bipartite layout creates default types if not provided", {
net <- list(n_nodes = 4)
class(net) <- "CographNetwork"
bipartite_fn <- get_layout("bipartite")
coords <- bipartite_fn(net)
expect_equal(nrow(coords), 4)
# Alternating nodes should be on different sides
expect_equal(coords$x[1], 0.2) # type 0
expect_equal(coords$x[2], 0.8) # type 1
expect_equal(coords$x[3], 0.2) # type 0
expect_equal(coords$x[4], 0.8) # type 1
})
test_that("bipartite layout respects custom types parameter", {
net <- list(n_nodes = 6)
class(net) <- "CographNetwork"
bipartite_fn <- get_layout("bipartite")
# First 3 on left, last 3 on right
types <- c(0, 0, 0, 1, 1, 1)
coords <- bipartite_fn(net, types = types)
expect_equal(nrow(coords), 6)
expect_true(all(coords$x[1:3] == 0.2)) # Left side
expect_true(all(coords$x[4:6] == 0.8)) # Right side
})
test_that("bipartite layout vertically spaces nodes within each side", {
net <- list(n_nodes = 6)
class(net) <- "CographNetwork"
bipartite_fn <- get_layout("bipartite")
types <- c(0, 0, 0, 1, 1, 1)
coords <- bipartite_fn(net, types = types)
# Left side y-coordinates should be spaced from 0.9 to 0.1
expect_equal(coords$y[1], 0.9)
expect_equal(coords$y[3], 0.1)
# Right side y-coordinates should be spaced from 0.9 to 0.1
expect_equal(coords$y[4], 0.9)
expect_equal(coords$y[6], 0.1)
})
test_that("bipartite layout handles all same type", {
net <- list(n_nodes = 3)
class(net) <- "CographNetwork"
bipartite_fn <- get_layout("bipartite")
types <- c(0, 0, 0)
coords <- bipartite_fn(net, types = types)
expect_equal(nrow(coords), 3)
# All should be on left side
expect_true(all(coords$x == 0.2))
})
# =============================================================================
# Test: Custom Layout Function
# =============================================================================
test_that("custom layout accepts matrix input", {
net <- list(n_nodes = 3)
class(net) <- "CographNetwork"
custom_fn <- get_layout("custom")
custom_coords <- matrix(c(0, 1, 0.5, 0, 0, 1), ncol = 2)
coords <- custom_fn(net, coords = custom_coords)
expect_equal(nrow(coords), 3)
expect_equal(coords$x[1], 0)
expect_equal(coords$y[1], 0)
})
test_that("custom layout accepts data frame input", {
net <- list(n_nodes = 3)
class(net) <- "CographNetwork"
custom_fn <- get_layout("custom")
custom_coords <- data.frame(a = c(0.1, 0.5, 0.9), b = c(0.2, 0.5, 0.8))
coords <- custom_fn(net, coords = custom_coords)
expect_equal(nrow(coords), 3)
expect_true("x" %in% names(coords))
expect_true("y" %in% names(coords))
# First two columns should be renamed to x and y
expect_equal(coords$x[1], 0.1)
expect_equal(coords$y[1], 0.2)
})
# =============================================================================
# Test: Gephi FR Layout Function
# =============================================================================
test_that("gephi_fr layout returns empty data frame for empty network", {
# Create actual network object since gephi_fr calls network_to_igraph
skip_if_not_installed("igraph")
gephi_fn <- get_layout("gephi_fr")
# Verify the function is registered
expect_true(is.function(gephi_fn))
})
test_that("gephi_fr layout produces coordinates for small network", {
skip_if_not_installed("igraph")
net <- create_test_network(5)
gephi_fn <- get_layout("gephi_fr")
coords <- gephi_fn(net, niter = 10)
expect_equal(nrow(coords), 5)
expect_true("x" %in% names(coords))
expect_true("y" %in% names(coords))
})
test_that("gephi_fr layout respects iteration parameter", {
skip_if_not_installed("igraph")
net <- create_test_network(5)
gephi_fn <- get_layout("gephi_fr")
# More iterations should produce different results
coords1 <- gephi_fn(net, niter = 5)
coords2 <- gephi_fn(net, niter = 100)
expect_equal(nrow(coords1), 5)
expect_equal(nrow(coords2), 5)
})
test_that("gephi_fr layout respects area parameter", {
skip_if_not_installed("igraph")
net <- create_test_network(5)
gephi_fn <- get_layout("gephi_fr")
coords <- gephi_fn(net, area = 5000, niter = 10)
expect_equal(nrow(coords), 5)
})
test_that("gephi_fr layout respects gravity parameter", {
skip_if_not_installed("igraph")
net <- create_test_network(5)
gephi_fn <- get_layout("gephi_fr")
coords <- gephi_fn(net, gravity = 20.0, niter = 10)
expect_equal(nrow(coords), 5)
})
test_that("gephi_fr layout respects speed parameter", {
skip_if_not_installed("igraph")
net <- create_test_network(5)
gephi_fn <- get_layout("gephi_fr")
coords <- gephi_fn(net, speed = 2.0, niter = 10)
expect_equal(nrow(coords), 5)
})
test_that("gephi_fr layout works with disconnected nodes", {
skip_if_not_installed("igraph")
# Network with no edges
mat <- matrix(0, 4, 4)
rownames(mat) <- colnames(mat) <- paste0("N", 1:4)
net <- CographNetwork$new(mat)
gephi_fn <- get_layout("gephi_fr")
coords <- gephi_fn(net, niter = 10)
expect_equal(nrow(coords), 4)
})
test_that("gephi layout alias works same as gephi_fr", {
skip_if_not_installed("igraph")
net <- create_test_network(5)
gephi_fr_fn <- get_layout("gephi_fr")
gephi_fn <- get_layout("gephi")
# Same function should be registered
expect_true(is.function(gephi_fr_fn))
expect_true(is.function(gephi_fn))
})
# =============================================================================
# Test: Layout Registration/Retrieval Functions
# =============================================================================
test_that("list_layouts returns all registered layouts", {
layouts <- list_layouts()
expect_true(is.character(layouts))
expect_true(length(layouts) >= 10) # At least 10 built-in layouts
# Check for key layouts
expected <- c("circle", "oval", "ellipse", "spring", "fr",
"fruchterman-reingold", "groups", "grid", "random",
"star", "bipartite", "custom", "gephi_fr", "gephi")
for (name in expected) {
expect_true(name %in% layouts, info = paste("Missing layout:", name))
}
})
test_that("get_layout returns NULL for unknown layout", {
fn <- get_layout("nonexistent_layout_xyz")
expect_null(fn)
})
test_that("get_layout returns functions for all built-in layouts", {
layouts <- c("circle", "oval", "spring", "groups", "grid",
"random", "star", "bipartite", "custom", "gephi_fr")
for (name in layouts) {
fn <- get_layout(name)
expect_true(is.function(fn), info = paste("Layout not a function:", name))
}
})
test_that("register_layout validates function parameter", {
expect_error(
register_layout("test_layout", "not_a_function"),
"layout_fn must be a function"
)
})
test_that("register_layout can register custom layout", {
# Register a simple custom layout
custom_layout_fn <- function(network, ...) {
n <- network$n_nodes
data.frame(x = rep(0.5, n), y = rep(0.5, n))
}
register_layout("test_center_layout", custom_layout_fn)
# Verify registration
expect_true("test_center_layout" %in% list_layouts())
fn <- get_layout("test_center_layout")
expect_true(is.function(fn))
# Test it works
net <- list(n_nodes = 3)
class(net) <- "CographNetwork"
coords <- fn(net)
expect_equal(nrow(coords), 3)
expect_true(all(coords$x == 0.5))
})
test_that("register_layout can overwrite existing layout", {
# Get original
original_fn <- get_layout("random")
# Register replacement
replacement_fn <- function(network, ...) {
n <- network$n_nodes
data.frame(x = rep(0.1, n), y = rep(0.9, n))
}
register_layout("random", replacement_fn)
# Verify replacement
new_fn <- get_layout("random")
net <- list(n_nodes = 2)
class(net) <- "CographNetwork"
coords <- new_fn(net)
expect_equal(coords$x[1], 0.1)
expect_equal(coords$y[1], 0.9)
# Restore original
register_layout("random", original_fn)
})
# =============================================================================
# Test: Layout Integration with CographLayout class
# =============================================================================
test_that("CographLayout can use registered layouts", {
layout <- CographLayout$new("circle")
net <- create_test_network(4)
coords <- layout$compute(net)
expect_equal(nrow(coords), 4)
expect_true(all(c("x", "y") %in% names(coords)))
})
test_that("CographLayout errors on unknown layout type", {
layout <- CographLayout$new("unknown_layout_xyz")
net <- create_test_network(3)
expect_error(
layout$compute(net),
"Unknown layout type"
)
})
test_that("CographLayout get_type returns correct type", {
layout <- CographLayout$new("grid")
expect_equal(layout$get_type(), "grid")
})
test_that("CographLayout stores parameters", {
layout <- CographLayout$new("grid", ncol = 3)
params <- layout$get_params()
expect_equal(params$ncol, 3)
})
# =============================================================================
# Test: Edge cases and special inputs
# =============================================================================
test_that("layouts handle single node networks", {
net <- list(n_nodes = 1)
class(net) <- "CographNetwork"
layouts <- c("grid", "random", "star", "bipartite")
for (name in layouts) {
fn <- get_layout(name)
coords <- fn(net)
expect_equal(nrow(coords), 1, info = paste("Layout:", name))
}
})
test_that("layouts handle two node networks", {
net <- list(n_nodes = 2)
class(net) <- "CographNetwork"
layouts <- c("grid", "random", "star", "bipartite")
for (name in layouts) {
fn <- get_layout(name)
coords <- fn(net)
expect_equal(nrow(coords), 2, info = paste("Layout:", name))
}
})
test_that("layouts handle large networks", {
net <- list(n_nodes = 100)
class(net) <- "CographNetwork"
grid_fn <- get_layout("grid")
coords <- grid_fn(net)
expect_equal(nrow(coords), 100)
random_fn <- get_layout("random")
coords <- random_fn(net, seed = 42)
expect_equal(nrow(coords), 100)
})
test_that("grid layout handles odd number of nodes with custom ncol", {
net <- list(n_nodes = 11)
class(net) <- "CographNetwork"
grid_fn <- get_layout("grid")
coords <- grid_fn(net, ncol = 4)
expect_equal(nrow(coords), 11)
})
test_that("bipartite layout handles single type", {
net <- list(n_nodes = 5)
class(net) <- "CographNetwork"
bipartite_fn <- get_layout("bipartite")
types <- c(1, 1, 1, 1, 1)
coords <- bipartite_fn(net, types = types)
expect_equal(nrow(coords), 5)
# All on same side
expect_true(all(coords$x == coords$x[1]))
})
test_that("star layout center parameter out of range handled", {
net <- list(n_nodes = 5)
class(net) <- "CographNetwork"
star_fn <- get_layout("star")
# Center = 5 is last node
coords <- star_fn(net, center = 5)
expect_equal(coords$x[5], 0.5)
expect_equal(coords$y[5], 0.5)
})
# =============================================================================
# Test: Layout produces valid data frame structure
# =============================================================================
test_that("all built-in layouts return proper data frame structure", {
net <- list(n_nodes = 5)
class(net) <- "CographNetwork"
simple_layouts <- c("grid", "random", "star", "bipartite")
for (name in simple_layouts) {
fn <- get_layout(name)
coords <- fn(net)
expect_true(is.data.frame(coords), info = paste("Layout:", name))
expect_true("x" %in% names(coords), info = paste("Layout:", name))
expect_true("y" %in% names(coords), info = paste("Layout:", name))
expect_true(is.numeric(coords$x), info = paste("Layout:", name))
expect_true(is.numeric(coords$y), info = paste("Layout:", name))
}
})
test_that("custom layout renames columns correctly", {
net <- list(n_nodes = 3)
class(net) <- "CographNetwork"
custom_fn <- get_layout("custom")
# With unnamed matrix
mat <- matrix(1:6, ncol = 2)
coords <- custom_fn(net, coords = mat)
expect_true("x" %in% names(coords))
expect_true("y" %in% names(coords))
# With wrongly named data frame
df <- data.frame(foo = c(1, 2, 3), bar = c(4, 5, 6))
coords <- custom_fn(net, coords = df)
expect_true("x" %in% names(coords))
expect_true("y" %in% names(coords))
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.