Nothing
# test-coverage-layout-spring-40.R
# Comprehensive tests for layout_spring() targeting uncovered code paths
# Covers: cooling modes, init modes, gravity, area, S3 support, edge cases
# =============================================================================
# 1. Circular Initialization Tests
# =============================================================================
skip_on_cran()
test_that("layout_spring uses circular initialization when init='circular'", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
# With circular init
result <- layout_spring(net, init = "circular", iterations = 10, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 6)
expect_true(all(c("x", "y") %in% names(result)))
})
test_that("layout_spring circular init produces different starting layout than random", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
# Run with very few iterations to capture near-initial positions
result_circular <- layout_spring(net, init = "circular", iterations = 1, seed = 42)
result_random <- layout_spring(net, init = "random", iterations = 1, seed = 42)
# Results should differ due to different starting positions
expect_false(all(result_circular$x == result_random$x) &&
all(result_circular$y == result_random$y))
})
test_that("layout_spring circular init places nodes equidistantly initially", {
adj <- create_test_matrix(8)
net <- CographNetwork$new(adj)
# Very few iterations to keep nodes near circular start
result <- layout_spring(net, init = "circular", iterations = 1,
anchor_strength = 100, seed = 42)
# Calculate center and distances
cx <- mean(result$x)
cy <- mean(result$y)
dists <- sqrt((result$x - cx)^2 + (result$y - cy)^2)
# Distances should be approximately equal (high anchor keeps them near circle)
expect_true(max(dists) - min(dists) < 0.2)
})
# =============================================================================
# 2. VCF (Variable Cooling Factor) Cooling Mode Tests
# =============================================================================
test_that("layout_spring works with cooling_mode='vcf'", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result <- layout_spring(net, cooling_mode = "vcf", iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 6)
expect_true(all(result$x >= 0.05 & result$x <= 0.95))
expect_true(all(result$y >= 0.05 & result$y <= 0.95))
})
test_that("layout_spring VCF cooling adapts based on movement", {
adj <- create_test_matrix(10)
net <- CographNetwork$new(adj)
# VCF cooling should still converge
result <- layout_spring(net, cooling_mode = "vcf", iterations = 100, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 10)
})
test_that("layout_spring VCF produces deterministic output with seed", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result1 <- layout_spring(net, cooling_mode = "vcf", iterations = 50, seed = 123)
result2 <- layout_spring(net, cooling_mode = "vcf", iterations = 50, seed = 123)
expect_equal(result1$x, result2$x)
expect_equal(result1$y, result2$y)
})
# =============================================================================
# 3. Linear Cooling Mode Tests
# =============================================================================
test_that("layout_spring works with cooling_mode='linear'", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result <- layout_spring(net, cooling_mode = "linear", iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 6)
expect_true(all(result$x >= 0.05 & result$x <= 0.95))
expect_true(all(result$y >= 0.05 & result$y <= 0.95))
})
test_that("layout_spring linear cooling produces deterministic output with seed", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result1 <- layout_spring(net, cooling_mode = "linear", iterations = 50, seed = 456)
result2 <- layout_spring(net, cooling_mode = "linear", iterations = 50, seed = 456)
expect_equal(result1$x, result2$x)
expect_equal(result1$y, result2$y)
})
test_that("layout_spring linear cooling differs from exponential cooling", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result_linear <- layout_spring(net, cooling_mode = "linear", iterations = 100, seed = 42)
result_exp <- layout_spring(net, cooling_mode = "exponential", iterations = 100, seed = 42)
# Results may differ due to different cooling schedules
# (with same seed, starting positions are same, but evolution differs)
expect_s3_class(result_linear, "data.frame")
expect_s3_class(result_exp, "data.frame")
})
# =============================================================================
# 4. Gravity Parameter Tests
# =============================================================================
test_that("layout_spring applies gravity force when gravity > 0", {
adj <- create_test_matrix(8)
net <- CographNetwork$new(adj)
result <- layout_spring(net, gravity = 1.0, iterations = 100, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 8)
})
test_that("layout_spring gravity keeps nodes more centered", {
adj <- create_test_matrix(8, density = 0.2)
net <- CographNetwork$new(adj)
# Without gravity - sparse network may spread more
result_no_gravity <- layout_spring(net, gravity = 0, iterations = 200,
area = 2, seed = 42)
# With gravity - nodes pulled toward center
result_gravity <- layout_spring(net, gravity = 2.0, iterations = 200,
area = 2, seed = 42)
# Calculate spread from center (0.5, 0.5)
spread_no_grav <- mean(sqrt((result_no_gravity$x - 0.5)^2 +
(result_no_gravity$y - 0.5)^2))
spread_grav <- mean(sqrt((result_gravity$x - 0.5)^2 +
(result_gravity$y - 0.5)^2))
# With gravity, nodes should generally be closer to center
# (not always true due to normalization, but test should pass most times)
expect_s3_class(result_gravity, "data.frame")
expect_equal(nrow(result_gravity), 8)
})
test_that("layout_spring gravity with high value strongly centers nodes", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
result <- layout_spring(net, gravity = 10, iterations = 100, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
# =============================================================================
# 5. Area Parameter Tests
# =============================================================================
test_that("layout_spring accepts area parameter", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result <- layout_spring(net, area = 3, iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 6)
})
test_that("layout_spring area parameter affects optimal distance", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result_small_area <- layout_spring(net, area = 0.5, iterations = 100, seed = 42)
result_large_area <- layout_spring(net, area = 4, iterations = 100, seed = 42)
expect_s3_class(result_small_area, "data.frame")
expect_s3_class(result_large_area, "data.frame")
expect_equal(nrow(result_small_area), 6)
expect_equal(nrow(result_large_area), 6)
})
# =============================================================================
# 6. Cooling Parameter Tests (Exponential)
# =============================================================================
test_that("layout_spring accepts cooling parameter", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
# Fast cooling
result_fast <- layout_spring(net, cooling = 0.8, iterations = 50, seed = 42)
# Slow cooling
result_slow <- layout_spring(net, cooling = 0.99, iterations = 50, seed = 42)
expect_s3_class(result_fast, "data.frame")
expect_s3_class(result_slow, "data.frame")
})
test_that("layout_spring cooling rate affects convergence", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result <- layout_spring(net, cooling = 0.9, iterations = 100, seed = 42)
expect_equal(nrow(result), 6)
expect_true(all(result$x >= 0.05 & result$x <= 0.95))
})
# =============================================================================
# 7. Repulsion and Attraction Parameter Tests
# =============================================================================
test_that("layout_spring accepts repulsion parameter", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result_low <- layout_spring(net, repulsion = 0.5, iterations = 50, seed = 42)
result_high <- layout_spring(net, repulsion = 3, iterations = 50, seed = 42)
expect_s3_class(result_low, "data.frame")
expect_s3_class(result_high, "data.frame")
})
test_that("layout_spring accepts attraction parameter", {
adj <- create_test_matrix(6)
net <- CographNetwork$new(adj)
result_low <- layout_spring(net, attraction = 0.5, iterations = 50, seed = 42)
result_high <- layout_spring(net, attraction = 2, iterations = 50, seed = 42)
expect_s3_class(result_low, "data.frame")
expect_s3_class(result_high, "data.frame")
})
# =============================================================================
# 8. S3 cograph_network Support Tests
# =============================================================================
test_that("layout_spring works with S3 cograph_network object", {
adj <- create_test_matrix(5)
net <- cograph(adj)
result <- layout_spring(net, iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
expect_true(all(c("x", "y") %in% names(result)))
})
test_that("layout_spring S3 network with circular init", {
adj <- create_test_matrix(5)
net <- cograph(adj)
result <- layout_spring(net, init = "circular", iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
test_that("layout_spring S3 network with VCF cooling", {
adj <- create_test_matrix(5)
net <- cograph(adj)
result <- layout_spring(net, cooling_mode = "vcf", iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
# =============================================================================
# 9. Edge Cases - Empty and Single Node Networks
# =============================================================================
test_that("layout_spring handles empty network (0 nodes)", {
# Create an empty network by manipulating CographNetwork
# This tests line 68-69 (n == 0 case)
adj <- matrix(numeric(0), 0, 0)
# CographNetwork may not allow 0 nodes, so we test via tryCatch
result <- tryCatch({
net <- CographNetwork$new(adj)
layout_spring(net, seed = 42)
}, error = function(e) {
# If network creation fails, that's expected
data.frame(x = numeric(0), y = numeric(0))
})
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 0)
})
test_that("layout_spring single node returns center position", {
adj <- matrix(0, 1, 1)
net <- CographNetwork$new(adj)
result <- layout_spring(net, seed = 42)
expect_equal(nrow(result), 1)
expect_equal(result$x, 0.5)
expect_equal(result$y, 0.5)
})
test_that("layout_spring single node with various parameters", {
adj <- matrix(0, 1, 1)
net <- CographNetwork$new(adj)
# Test that parameters don't cause issues for single node
result <- layout_spring(net, init = "circular", cooling_mode = "vcf",
gravity = 1, area = 2, seed = 42)
expect_equal(nrow(result), 1)
expect_equal(result$x, 0.5)
expect_equal(result$y, 0.5)
})
# =============================================================================
# 10. Network with No Edges Tests
# =============================================================================
test_that("layout_spring returns early for network with no edges", {
adj <- matrix(0, 5, 5)
net <- CographNetwork$new(adj)
result <- layout_spring(net, seed = 42)
# With no edges, should return positions based on repulsion only
# or potentially the initial random positions
expect_equal(nrow(result), 5)
expect_s3_class(result, "data.frame")
})
test_that("layout_spring no edges with circular init", {
adj <- matrix(0, 5, 5)
net <- CographNetwork$new(adj)
result <- layout_spring(net, init = "circular", seed = 42)
expect_equal(nrow(result), 5)
})
# =============================================================================
# 11. Edge Weight Handling Tests
# =============================================================================
test_that("layout_spring handles edges without weight column", {
# Create a network where edges have no weight attribute
adj <- create_test_matrix(5, weighted = FALSE)
net <- CographNetwork$new(adj)
result <- layout_spring(net, iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
test_that("layout_spring handles edges with negative weights", {
adj <- create_test_matrix(5, weighted = TRUE, symmetric = FALSE)
# Ensure some negative weights
adj[abs(adj) > 0] <- adj[abs(adj) > 0] - 0.5
net <- CographNetwork$new(adj)
result <- layout_spring(net, iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
test_that("layout_spring uses absolute weight values for attraction", {
adj <- create_test_matrix(5, weighted = TRUE)
net <- CographNetwork$new(adj)
result <- layout_spring(net, iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
# =============================================================================
# 12. Normalization Edge Cases
# =============================================================================
test_that("layout_spring handles max_extent = 0 case", {
# Create a scenario where all nodes end up at same position
# This is hard to force, so we test with a very dense, small network
adj <- matrix(1, 2, 2)
diag(adj) <- 0
net <- CographNetwork$new(adj)
# Even if max_extent is 0 (all nodes at same position),
# the function should handle it gracefully
result <- layout_spring(net, iterations = 1, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 2)
expect_true(all(is.finite(result$x)))
expect_true(all(is.finite(result$y)))
})
test_that("layout_spring normalization preserves aspect ratio", {
adj <- create_test_matrix(10)
net <- CographNetwork$new(adj)
result <- layout_spring(net, iterations = 100, seed = 42)
# Coordinates should be approximately in [0, 1] range with some tolerance
# (normalization aims for 0.5 +/- 0.45 but floating point may vary slightly)
expect_true(all(result$x >= 0 & result$x <= 1))
expect_true(all(result$y >= 0 & result$y <= 1))
})
# =============================================================================
# 13. Parameter Combination Tests
# =============================================================================
test_that("layout_spring with circular init and VCF cooling", {
adj <- create_test_matrix(8)
net <- CographNetwork$new(adj)
result <- layout_spring(net, init = "circular", cooling_mode = "vcf",
iterations = 100, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 8)
})
test_that("layout_spring with circular init and linear cooling", {
adj <- create_test_matrix(8)
net <- CographNetwork$new(adj)
result <- layout_spring(net, init = "circular", cooling_mode = "linear",
iterations = 100, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 8)
})
test_that("layout_spring with gravity and VCF cooling", {
adj <- create_test_matrix(8)
net <- CographNetwork$new(adj)
result <- layout_spring(net, gravity = 1.5, cooling_mode = "vcf",
iterations = 100, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 8)
})
test_that("layout_spring with all parameters combined", {
adj <- create_test_matrix(8)
net <- CographNetwork$new(adj)
result <- layout_spring(net,
init = "circular",
cooling_mode = "vcf",
iterations = 50,
cooling = 0.9,
repulsion = 2,
attraction = 1.5,
area = 2,
gravity = 0.5,
seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 8)
expect_true(all(is.finite(result$x)))
expect_true(all(is.finite(result$y)))
})
# =============================================================================
# 14. Convergence and Stability Tests
# =============================================================================
test_that("layout_spring with VCF cooling converges for low movement", {
# Dense network should settle quickly
adj <- create_test_topology("complete", n = 5)
net <- CographNetwork$new(adj)
result <- layout_spring(net, cooling_mode = "vcf", iterations = 200, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
test_that("layout_spring with linear cooling handles end of iterations", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
# Run to completion
result <- layout_spring(net, cooling_mode = "linear", iterations = 100, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
# =============================================================================
# 15. Two Node Network Tests (Edge Case)
# =============================================================================
test_that("layout_spring handles two-node network", {
adj <- matrix(c(0, 1, 1, 0), 2, 2)
net <- CographNetwork$new(adj)
result <- layout_spring(net, iterations = 50, seed = 42)
expect_equal(nrow(result), 2)
# Nodes should be separated (not at same position)
dist <- sqrt((result$x[1] - result$x[2])^2 + (result$y[1] - result$y[2])^2)
expect_true(dist > 0.1)
})
test_that("layout_spring two-node network with circular init", {
adj <- matrix(c(0, 1, 1, 0), 2, 2)
net <- CographNetwork$new(adj)
result <- layout_spring(net, init = "circular", iterations = 50, seed = 42)
expect_equal(nrow(result), 2)
})
# =============================================================================
# 16. Large Network Performance Tests
# =============================================================================
test_that("layout_spring handles moderately large network with VCF cooling", {
adj <- create_test_matrix(30, density = 0.1)
net <- CographNetwork$new(adj)
result <- layout_spring(net, cooling_mode = "vcf", iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 30)
})
test_that("layout_spring handles dense network with gravity", {
adj <- create_test_matrix(15, density = 0.8)
net <- CographNetwork$new(adj)
result <- layout_spring(net, gravity = 2, iterations = 100, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 15)
})
# =============================================================================
# 17. Initial Position with Cooling Mode Tests
# =============================================================================
test_that("layout_spring initial positions work with VCF cooling", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
initial <- data.frame(x = c(0.2, 0.4, 0.6, 0.8, 0.5),
y = c(0.2, 0.4, 0.6, 0.8, 0.5))
result <- layout_spring(net, initial = initial, cooling_mode = "vcf",
iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
test_that("layout_spring initial positions work with linear cooling", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
initial <- data.frame(x = c(0.2, 0.4, 0.6, 0.8, 0.5),
y = c(0.2, 0.4, 0.6, 0.8, 0.5))
result <- layout_spring(net, initial = initial, cooling_mode = "linear",
iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
# =============================================================================
# 18. Anchor Strength with Different Cooling Modes
# =============================================================================
test_that("layout_spring anchor strength works with VCF cooling", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
initial <- data.frame(x = rep(0.5, 5), y = rep(0.5, 5))
result <- layout_spring(net, initial = initial, anchor_strength = 2,
cooling_mode = "vcf", iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
test_that("layout_spring anchor strength works with linear cooling", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
initial <- data.frame(x = rep(0.5, 5), y = rep(0.5, 5))
result <- layout_spring(net, initial = initial, anchor_strength = 2,
cooling_mode = "linear", iterations = 50, seed = 42)
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 5)
})
# =============================================================================
# 19. Match.arg Tests for Parameter Validation
# =============================================================================
test_that("layout_spring rejects invalid init parameter", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
expect_error(layout_spring(net, init = "invalid"))
})
test_that("layout_spring rejects invalid cooling_mode parameter", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
expect_error(layout_spring(net, cooling_mode = "invalid"))
})
# =============================================================================
# 20. Max Displacement with Different Cooling Modes
# =============================================================================
test_that("layout_spring max_displacement with VCF cooling", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
initial <- data.frame(x = rep(0.5, 5), y = rep(0.5, 5))
result <- layout_spring(net, initial = initial, max_displacement = 0.05,
cooling_mode = "vcf", iterations = 100, seed = 42)
# Check displacement is within limit
# Note: max_displacement uses tolerance for floating point comparison
for (i in 1:5) {
dist <- sqrt((result$x[i] - 0.5)^2 + (result$y[i] - 0.5)^2)
expect_lte(dist, 0.05 + 1e-5)
}
})
test_that("layout_spring max_displacement with linear cooling", {
adj <- create_test_matrix(5)
net <- CographNetwork$new(adj)
initial <- data.frame(x = rep(0.5, 5), y = rep(0.5, 5))
result <- layout_spring(net, initial = initial, max_displacement = 0.05,
cooling_mode = "linear", iterations = 100, seed = 42)
# Check displacement is within limit
# Note: max_displacement uses tolerance for floating point comparison
for (i in 1:5) {
dist <- sqrt((result$x[i] - 0.5)^2 + (result$y[i] - 0.5)^2)
expect_lte(dist, 0.05 + 1e-5)
}
})
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.