mod env;
mod report;
mod types;
pub use report::{TestReport, TestResult};
pub use types::{CiEnvironment, CiProvider};
#[cfg(test)]
mod tests {
use super::super::{CiEnvironment, CiProvider, TestReport, TestResult};
use std::path::PathBuf;
#[test]
fn test_ci_environment_detect() {
let ci = CiEnvironment::detect();
assert!(!ci.provider_name().is_empty());
assert!(!ci.artifacts_dir.as_os_str().is_empty());
}
#[test]
fn test_ci_provider_name() {
let ci = CiEnvironment {
provider: CiProvider::GitHubActions,
is_ci: true,
branch: None,
commit: None,
pr_number: None,
build_number: None,
artifacts_dir: PathBuf::from("artifacts"),
};
assert_eq!(ci.provider_name(), "GitHub Actions");
}
#[test]
fn test_report_new() {
let report = TestReport::new();
assert_eq!(report.total(), 0);
assert_eq!(report.passed(), 0);
assert_eq!(report.failed(), 0);
}
#[test]
fn test_report_add_passed() {
let mut report = TestReport::new();
report.add_passed("test1");
report.add_passed("test2");
assert_eq!(report.total(), 2);
assert_eq!(report.passed(), 2);
assert_eq!(report.failed(), 0);
assert!(report.all_passed());
}
#[test]
fn test_report_add_failed() {
let mut report = TestReport::new();
report.add_passed("test1");
report.add_failed("test2", "Something went wrong");
assert_eq!(report.total(), 2);
assert_eq!(report.passed(), 1);
assert_eq!(report.failed(), 1);
assert!(!report.all_passed());
}
#[test]
fn test_report_summary() {
let mut report = TestReport::new();
report.add_passed("test1");
report.add_failed("test2", "Error message");
let summary = report.summary();
assert!(summary.contains("1 passed"));
assert!(summary.contains("1 failed"));
assert!(summary.contains("test2"));
}
#[test]
fn test_report_markdown() {
let mut report = TestReport::new();
report.add_passed("test1");
report.add_metadata("version", "0.5.0");
let markdown = report.to_markdown();
assert!(markdown.contains("# Visual Regression Test Results"));
assert!(markdown.contains("✅ Passed"));
assert!(markdown.contains("version"));
}
#[test]
fn test_ci_provider_equality() {
assert_eq!(CiProvider::GitHubActions, CiProvider::GitHubActions);
assert_ne!(CiProvider::GitHubActions, CiProvider::GitLabCi);
}
#[test]
fn test_ci_provider_clone() {
let provider = CiProvider::CircleCi;
let cloned = provider.clone();
assert_eq!(provider, cloned);
}
#[test]
fn test_ci_provider_all_variants() {
let variants = [
CiProvider::GitHubActions,
CiProvider::GitLabCi,
CiProvider::CircleCi,
CiProvider::TravisCi,
CiProvider::Jenkins,
CiProvider::AzurePipelines,
CiProvider::Generic,
CiProvider::Local,
];
assert_eq!(variants.len(), 8);
}
#[test]
fn test_ci_environment_default() {
let ci = CiEnvironment::default();
assert!(!ci.provider_name().is_empty());
}
#[test]
fn test_ci_environment_is_ci() {
let ci = CiEnvironment {
provider: CiProvider::Local,
is_ci: false,
branch: None,
commit: None,
pr_number: None,
build_number: None,
artifacts_dir: PathBuf::from("artifacts"),
};
assert!(!ci.is_ci());
}
#[test]
fn test_ci_environment_provider_names() {
let test_cases = [
(CiProvider::GitHubActions, "GitHub Actions"),
(CiProvider::GitLabCi, "GitLab CI"),
(CiProvider::CircleCi, "CircleCI"),
(CiProvider::TravisCi, "Travis CI"),
(CiProvider::Jenkins, "Jenkins"),
(CiProvider::AzurePipelines, "Azure Pipelines"),
(CiProvider::Generic, "CI"),
(CiProvider::Local, "Local"),
];
for (provider, expected_name) in test_cases {
let ci = CiEnvironment {
provider,
is_ci: false,
branch: None,
commit: None,
pr_number: None,
build_number: None,
artifacts_dir: PathBuf::from("test"),
};
assert_eq!(ci.provider_name(), expected_name);
}
}
#[test]
fn test_ci_environment_clone() {
let ci = CiEnvironment {
provider: CiProvider::GitHubActions,
is_ci: true,
branch: Some("main".to_string()),
commit: Some("abc123".to_string()),
pr_number: Some("42".to_string()),
build_number: Some("100".to_string()),
artifacts_dir: PathBuf::from("artifacts"),
};
let cloned = ci.clone();
assert_eq!(cloned.provider, CiProvider::GitHubActions);
assert_eq!(cloned.branch, Some("main".to_string()));
}
#[test]
fn test_test_result_passed() {
let result = TestResult {
name: "my_test".to_string(),
passed: true,
message: None,
diff_path: None,
duration_ms: 100,
};
assert!(result.passed);
assert_eq!(result.name, "my_test");
}
#[test]
fn test_test_result_failed() {
let result = TestResult {
name: "failing_test".to_string(),
passed: false,
message: Some("Assertion failed".to_string()),
diff_path: Some(PathBuf::from("test.diff")),
duration_ms: 50,
};
assert!(!result.passed);
assert!(result.message.is_some());
assert!(result.diff_path.is_some());
}
#[test]
fn test_test_result_clone() {
let result = TestResult {
name: "test".to_string(),
passed: true,
message: None,
diff_path: None,
duration_ms: 10,
};
let cloned = result.clone();
assert_eq!(cloned.name, "test");
}
#[test]
fn test_report_default() {
let report = TestReport::default();
assert!(report.all_passed()); assert_eq!(report.total(), 0);
}
#[test]
fn test_report_add_metadata() {
let mut report = TestReport::new();
report.add_metadata("key1", "value1");
report.add_metadata("key2", "value2");
let markdown = report.to_markdown();
assert!(markdown.contains("key1"));
assert!(markdown.contains("value1"));
}
#[test]
fn test_report_add_passed_with_duration() {
let mut report = TestReport::new();
report.add_passed_with_duration("fast_test", 10);
report.add_passed_with_duration("slow_test", 1000);
assert_eq!(report.passed(), 2);
}
#[test]
fn test_report_add_failed_with_diff() {
let mut report = TestReport::new();
report.add_failed_with_diff("visual_test", "Size mismatch", "diff.png");
assert_eq!(report.failed(), 1);
let failures: Vec<_> = report.failures().collect();
assert_eq!(failures.len(), 1);
assert!(failures[0].diff_path.is_some());
}
#[test]
fn test_report_failures_iterator() {
let mut report = TestReport::new();
report.add_passed("pass1");
report.add_failed("fail1", "error1");
report.add_passed("pass2");
report.add_failed("fail2", "error2");
let failures: Vec<_> = report.failures().collect();
assert_eq!(failures.len(), 2);
}
#[test]
fn test_report_duration() {
let report = TestReport::new();
std::thread::sleep(std::time::Duration::from_millis(1));
assert!(report.duration() >= std::time::Duration::from_millis(1));
}
#[test]
fn test_report_summary_all_passed() {
let mut report = TestReport::new();
report.add_passed("test1");
report.add_passed("test2");
let summary = report.summary();
assert!(summary.contains("2 passed"));
assert!(summary.contains("0 failed"));
}
#[test]
fn test_report_summary_with_failures() {
let mut report = TestReport::new();
report.add_failed("broken_test", "Something broke");
let summary = report.summary();
assert!(summary.contains("Failed tests"));
assert!(summary.contains("broken_test"));
assert!(summary.contains("Something broke"));
}
#[test]
fn test_report_markdown_failed() {
let mut report = TestReport::new();
report.add_failed("test1", "Error message");
let markdown = report.to_markdown();
assert!(markdown.contains("❌ Failed"));
assert!(markdown.contains("## Failed Tests"));
assert!(markdown.contains("test1"));
}
#[test]
fn test_report_markdown_with_diff() {
let mut report = TestReport::new();
report.add_failed_with_diff("visual_test", "Mismatch", "path/to/diff.png");
let markdown = report.to_markdown();
assert!(markdown.contains("Diff:"));
assert!(markdown.contains("diff.png"));
}
}