#[cfg(all(feature = "static_export", feature = "plotly"))]
mod plotly_render_tests {
use optionstratlib::visualization::{Graph, GraphConfig, GraphData, OutputType, Series2D};
use rust_decimal::Decimal;
use std::path::PathBuf;
use std::str::FromStr;
use tempfile::tempdir;
struct TestGraph {
data: GraphData,
config: GraphConfig,
}
impl TestGraph {
fn new(data: GraphData, config: GraphConfig) -> Self {
Self { data, config }
}
}
impl Graph for TestGraph {
fn graph_data(&self) -> GraphData {
self.data.clone()
}
fn graph_config(&self) -> GraphConfig {
self.config.clone()
}
}
fn create_sample_series() -> Series2D {
Series2D {
x: vec![
Decimal::from_str("1.0").unwrap(),
Decimal::from_str("2.0").unwrap(),
Decimal::from_str("3.0").unwrap(),
],
y: vec![
Decimal::from_str("4.0").unwrap(),
Decimal::from_str("5.0").unwrap(),
Decimal::from_str("6.0").unwrap(),
],
name: "Test Series".to_string(),
mode: optionstratlib::visualization::TraceMode::Lines,
line_color: Some("#FF0000".to_string()),
line_width: Some(2.0),
}
}
fn create_sample_config() -> GraphConfig {
GraphConfig {
title: "Test Graph".to_string(),
width: 800,
height: 600,
x_label: Some("X Axis".to_string()),
y_label: Some("Y Axis".to_string()),
z_label: Some("Z Axis".to_string()),
line_style: optionstratlib::visualization::LineStyle::Solid,
color_scheme: optionstratlib::visualization::ColorScheme::Viridis,
legend: Some(vec!["Series 1".to_string()]),
show_legend: true,
}
}
#[cfg(test)]
mod tests {
use super::*;
use tracing::info;
#[test]
fn test_to_plot_with_minimal_config() {
let series = create_sample_series();
let minimal_config = GraphConfig {
title: "Minimal Config".to_string(),
width: 400,
height: 300,
x_label: None, y_label: None, z_label: None, line_style: optionstratlib::visualization::LineStyle::Solid,
color_scheme: optionstratlib::visualization::ColorScheme::Viridis,
legend: None, show_legend: false,
};
let graph = TestGraph::new(GraphData::Series(series), minimal_config);
let plot = graph.to_plot();
assert_eq!(plot.data().len(), 1);
let layout = plot.layout();
assert!(layout.to_json().contains("\"width\":400"));
assert!(layout.to_json().contains("\"height\":300"));
}
#[test]
fn test_to_plot_with_all_axis_labels() {
let series = create_sample_series();
let config = GraphConfig {
title: "All Axis Labels".to_string(),
width: 600,
height: 400,
x_label: Some("X Axis Label".to_string()),
y_label: Some("Y Axis Label".to_string()),
z_label: Some("Z Axis Label".to_string()),
line_style: optionstratlib::visualization::LineStyle::Solid,
color_scheme: optionstratlib::visualization::ColorScheme::Viridis,
legend: Some(vec!["Series 1".to_string()]),
show_legend: true,
};
let graph = TestGraph::new(GraphData::Series(series), config);
let plot = graph.to_plot();
assert_eq!(plot.data().len(), 1);
let layout_json = plot.layout().to_json();
assert!(layout_json.contains("\"title\":{\"text\":\"X Axis Label\""));
assert!(layout_json.contains("\"title\":{\"text\":\"Y Axis Label\""));
assert!(layout_json.contains("\"title\":{\"text\":\"Z Axis Label\""));
}
#[test]
fn test_render_error_handling() {
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let invalid_path = std::path::PathBuf::from("/nonexistent/directory/file.png");
let png_result = graph.render(OutputType::Png(&invalid_path));
assert!(png_result.is_err());
let svg_result = graph.render(OutputType::Svg(&invalid_path));
assert!(svg_result.is_err());
let html_result = graph.render(OutputType::Html(&invalid_path));
assert!(html_result.is_err());
}
#[test]
fn test_render_png() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test_render.png");
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let result = graph.render(OutputType::Png(&file_path));
if let Err(e) = &result {
info!("PNG render error: {e}");
}
assert!(result.is_ok(), "Render to PNG should succeed");
}
#[test]
fn test_render_svg() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test_render.svg");
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let result = graph.render(OutputType::Svg(&file_path));
if let Err(e) = &result {
info!("SVG render error: {e}");
}
assert!(result.is_ok(), "Render to SVG should succeed");
}
#[test]
fn test_render_html() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test_render.html");
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let result = graph.render(OutputType::Html(&file_path));
assert!(result.is_ok(), "Render to HTML should succeed");
}
#[test]
fn test_render_browser() {
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let result = graph.render(OutputType::Browser);
assert!(result.is_ok(), "Render to Browser should succeed");
}
#[test]
fn test_write_png() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test_write.png");
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let result = graph.write_png(&file_path);
if let Err(e) = &result {
info!("PNG export error: {e}");
}
assert!(result.is_ok(), "Write to PNG should succeed");
}
#[test]
fn test_write_svg() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test_write.svg");
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let result = graph.write_svg(&file_path);
if let Err(e) = &result {
info!("SVG export error: {e}");
}
assert!(result.is_ok(), "Write to SVG should succeed");
}
#[test]
fn test_write_html() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test_write.html");
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let result = graph.write_html(&file_path);
assert!(result.is_ok(), "Write to HTML should succeed");
}
#[test]
fn test_to_interactive_html() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test_interactive.html");
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let result = graph.to_interactive_html(&file_path);
assert!(result.is_ok(), "Interactive HTML should succeed");
}
#[test]
fn test_file_operation_error_handling() {
let invalid_path = PathBuf::from("/nonexistent/directory/test.png");
let series = create_sample_series();
let config = create_sample_config();
let graph = TestGraph::new(GraphData::Series(series), config);
let png_result = graph.write_png(&invalid_path);
assert!(png_result.is_err(), "Write to invalid PNG path should fail");
let svg_result = graph.write_svg(&invalid_path);
assert!(svg_result.is_err(), "Write to invalid SVG path should fail");
let html_result = graph.write_html(&invalid_path);
assert!(
html_result.is_err(),
"Write to invalid HTML path should fail"
);
let interactive_result = graph.to_interactive_html(&invalid_path);
assert!(
interactive_result.is_err(),
"Interactive HTML to invalid path should fail"
);
}
}
}