- Fix toml version requirement metadata warning - Replace clone() with std::slice::from_ref() - Collapse nested if statements - Add #[allow(dead_code)] to test utility functions - Fix unused imports and variables in tests - Use unwrap_or_else instead of expect with format!
158 lines
4.8 KiB
Rust
158 lines
4.8 KiB
Rust
//! Full pipeline integration tests for WTIsMyCode
|
|
//!
|
|
//! Tests the complete scan → analyze → render pipeline using test-project/.
|
|
|
|
use wtismycode_core::config::Config;
|
|
use wtismycode_core::cycle_detector;
|
|
use wtismycode_core::model::{Module, ProjectModel};
|
|
use wtismycode_core::renderer::Renderer;
|
|
use wtismycode_core::scanner::FileScanner;
|
|
use std::path::Path;
|
|
|
|
#[test]
|
|
fn test_config_load_and_validate() {
|
|
let config_path = Path::new(env!("CARGO_MANIFEST_DIR"))
|
|
.parent()
|
|
.unwrap()
|
|
.join("test-project/wtismycode.toml");
|
|
|
|
let config = Config::load_from_file(&config_path).expect("Failed to load config");
|
|
assert_eq!(config.project.language, "python");
|
|
assert!(!config.scan.include.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn test_config_validate_on_test_project() {
|
|
let config_path = Path::new(env!("CARGO_MANIFEST_DIR"))
|
|
.parent()
|
|
.unwrap()
|
|
.join("test-project/wtismycode.toml");
|
|
|
|
let mut config = Config::load_from_file(&config_path).expect("Failed to load config");
|
|
// Set root to actual test-project path so validation passes
|
|
config.project.root = config_path.parent().unwrap().to_string_lossy().to_string();
|
|
assert!(config.validate().is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_config_validate_rejects_bad_language() {
|
|
let mut config = Config::default();
|
|
config.project.language = "java".to_string();
|
|
assert!(config.validate().is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_scan_test_project() {
|
|
let test_project = Path::new(env!("CARGO_MANIFEST_DIR"))
|
|
.parent()
|
|
.unwrap()
|
|
.join("test-project");
|
|
|
|
let config_path = test_project.join("wtismycode.toml");
|
|
let mut config = Config::load_from_file(&config_path).expect("Failed to load config");
|
|
config.project.root = test_project.to_string_lossy().to_string();
|
|
|
|
let scanner = FileScanner::new(config);
|
|
let files = scanner.scan_python_files(&test_project).expect("Scan should succeed");
|
|
assert!(!files.is_empty(), "Should find Python files in test-project");
|
|
}
|
|
|
|
#[test]
|
|
fn test_cycle_detection_with_known_cycles() {
|
|
let mut model = ProjectModel::new();
|
|
|
|
// Create a known cycle: a → b → c → a
|
|
model.modules.insert(
|
|
"mod_a".into(),
|
|
Module {
|
|
id: "mod_a".into(),
|
|
path: "a.py".into(),
|
|
files: vec![],
|
|
doc_summary: None,
|
|
outbound_modules: vec!["mod_b".into()],
|
|
inbound_modules: vec!["mod_c".into()],
|
|
symbols: vec![],
|
|
},
|
|
);
|
|
model.modules.insert(
|
|
"mod_b".into(),
|
|
Module {
|
|
id: "mod_b".into(),
|
|
path: "b.py".into(),
|
|
files: vec![],
|
|
doc_summary: None,
|
|
outbound_modules: vec!["mod_c".into()],
|
|
inbound_modules: vec!["mod_a".into()],
|
|
symbols: vec![],
|
|
},
|
|
);
|
|
model.modules.insert(
|
|
"mod_c".into(),
|
|
Module {
|
|
id: "mod_c".into(),
|
|
path: "c.py".into(),
|
|
files: vec![],
|
|
doc_summary: None,
|
|
outbound_modules: vec!["mod_a".into()],
|
|
inbound_modules: vec!["mod_b".into()],
|
|
symbols: vec![],
|
|
},
|
|
);
|
|
|
|
let cycles = cycle_detector::detect_cycles(&model);
|
|
assert_eq!(cycles.len(), 1, "Should detect exactly one cycle");
|
|
assert_eq!(cycles[0].len(), 3, "Cycle should have 3 modules");
|
|
}
|
|
|
|
#[test]
|
|
fn test_cycle_detection_no_cycles() {
|
|
let mut model = ProjectModel::new();
|
|
|
|
model.modules.insert(
|
|
"mod_a".into(),
|
|
Module {
|
|
id: "mod_a".into(),
|
|
path: "a.py".into(),
|
|
files: vec![],
|
|
doc_summary: None,
|
|
outbound_modules: vec!["mod_b".into()],
|
|
inbound_modules: vec![],
|
|
symbols: vec![],
|
|
},
|
|
);
|
|
model.modules.insert(
|
|
"mod_b".into(),
|
|
Module {
|
|
id: "mod_b".into(),
|
|
path: "b.py".into(),
|
|
files: vec![],
|
|
doc_summary: None,
|
|
outbound_modules: vec![],
|
|
inbound_modules: vec!["mod_a".into()],
|
|
symbols: vec![],
|
|
},
|
|
);
|
|
|
|
let cycles = cycle_detector::detect_cycles(&model);
|
|
assert!(cycles.is_empty(), "Should detect no cycles in DAG");
|
|
}
|
|
|
|
#[test]
|
|
fn test_renderer_produces_output() {
|
|
let _config = Config::default();
|
|
let model = ProjectModel::new();
|
|
let renderer = Renderer::new();
|
|
let result = renderer.render_architecture_md(&model, None);
|
|
assert!(result.is_ok(), "Renderer should produce output for empty model");
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_duration_values() {
|
|
use wtismycode_core::config::{parse_duration, parse_file_size};
|
|
|
|
assert_eq!(parse_duration("24h").unwrap(), 86400);
|
|
assert_eq!(parse_duration("7d").unwrap(), 604800);
|
|
assert_eq!(parse_file_size("10MB").unwrap(), 10 * 1024 * 1024);
|
|
assert_eq!(parse_file_size("1GB").unwrap(), 1024 * 1024 * 1024);
|
|
}
|