use colorgrad::{Color, Gradient, GradientBuilder, LinearGradient};
use chromacat::pattern::{
PatternConfig, PatternEngine, PatternParams, CommonParams,
CheckerboardParams, DiagonalParams, DiamondParams, HorizontalParams,
PerlinParams, PlasmaParams, RippleParams, SpiralParams, WaveParams,
};
fn create_test_gradient() -> Box<dyn Gradient + Send + Sync> {
let gradient = GradientBuilder::new()
.colors(&[
Color::new(1.0, 0.0, 0.0, 1.0),
Color::new(0.0, 0.0, 1.0, 1.0),
])
.build::<LinearGradient>()
.unwrap();
Box::new(gradient)
}
fn create_test_config() -> PatternConfig {
PatternConfig {
common: CommonParams {
frequency: 1.0,
amplitude: 1.0,
speed: 1.0,
correct_aspect: true,
aspect_ratio: 0.5,
theme_name: Some("test".to_string()),
},
params: PatternParams::Horizontal(HorizontalParams::default()),
}
}
#[test]
fn test_pattern_value_ranges() {
let patterns = vec![
PatternParams::Horizontal(HorizontalParams::default()),
PatternParams::Diagonal(DiagonalParams::default()),
PatternParams::Plasma(PlasmaParams::default()),
PatternParams::Ripple(RippleParams::default()),
PatternParams::Wave(WaveParams::default()),
PatternParams::Spiral(SpiralParams::default()),
PatternParams::Checkerboard(CheckerboardParams::default()),
PatternParams::Diamond(DiamondParams::default()),
PatternParams::Perlin(PerlinParams::default()),
];
for pattern in patterns {
let mut config = create_test_config();
config.params = pattern.clone();
let engine = PatternEngine::new(create_test_gradient(), config, 100, 100);
for x in [0, 49, 99] {
for y in [0, 49, 99] {
let value = engine.get_value_at(x, y).unwrap();
assert!(
(0.0..=1.0).contains(&value),
"Pattern {:?} value out of range: {} at ({}, {})",
pattern,
value,
x,
y
);
}
}
}
}
#[test]
fn test_pattern_animation() {
let animated_patterns = vec![
PatternParams::Wave(WaveParams::default()),
PatternParams::Ripple(RippleParams::default()),
PatternParams::Spiral(SpiralParams::default()),
PatternParams::Plasma(PlasmaParams::default()),
];
for pattern in animated_patterns {
eprintln!("\nDEBUG: Testing animation for pattern: {:?}", pattern);
let mut config = create_test_config();
config.params = pattern.clone();
config.common.speed = 2.0; let mut engine = PatternEngine::new(create_test_gradient(), config, 100, 100);
let initial = engine.get_value_at(50, 50).unwrap();
eprintln!("DEBUG: Initial value at (50,50): {}", initial);
eprintln!("DEBUG: Current time: {}", engine.time());
engine.update(2.0); eprintln!("DEBUG: Updated time to: {}", engine.time());
let after_update = engine.get_value_at(50, 50).unwrap();
eprintln!("DEBUG: Value after update at (50,50): {}", after_update);
assert_ne!(
initial, after_update,
"Pattern {:?} should animate over time",
pattern
);
}
}
#[test]
fn test_pattern_determinism() {
let static_patterns = vec![
PatternParams::Horizontal(HorizontalParams::default()),
PatternParams::Diagonal(DiagonalParams::default()),
PatternParams::Checkerboard(CheckerboardParams::default()),
PatternParams::Diamond(DiamondParams::default()),
PatternParams::Perlin(PerlinParams::default()),
];
for pattern in static_patterns {
let mut config = PatternConfig::new(pattern.clone());
config.common.theme_name = Some("test".to_string());
let engine = PatternEngine::new(create_test_gradient(), config, 100, 100);
let first = engine.get_value_at(50, 50).unwrap();
let second = engine.get_value_at(50, 50).unwrap();
assert_eq!(
first, second,
"Pattern {:?} should produce consistent values for same coordinates",
pattern
);
}
}