use super::common::*;
use std::{io::Write, path::PathBuf};
use tempfile::NamedTempFile;
use crate::{
analyzer::release::Release,
config::Config,
forge::{request::Tag, traits::MockForge},
packages::releasable::SerializableReleasablePackage,
};
fn create_test_release(version: &str, notes: &str) -> Release {
Release {
tag: Tag {
name: format!("v{}", version),
semver: Version::parse(version).unwrap(),
sha: "abc123".to_string(),
..Default::default()
},
notes: notes.to_string(),
..Default::default()
}
}
#[tokio::test]
async fn recompile_notes_from_release_file_returns_rendered_notes() {
let mock_forge = MockForge::new();
let orchestrator = create_test_orchestrator(mock_forge);
let mut temp_file = NamedTempFile::new().unwrap();
let package = SerializableReleasablePackage {
name: "test-package".to_string(),
path: PathBuf::from("."),
release: create_test_release("1.0.0", "Existing notes"),
..Default::default()
};
let json = serde_json::to_string(&vec![package]).unwrap();
temp_file.write_all(json.as_bytes()).unwrap();
temp_file.flush().unwrap();
let result = orchestrator
.recompile_notes_from_release_file(&temp_file.path().to_string_lossy())
.await
.unwrap();
assert_eq!(result.len(), 1);
assert_eq!(result[0].name, "test-package");
assert!(!result[0].release.notes.is_empty());
}
#[tokio::test]
async fn recompile_notes_from_release_file_handles_multiple_packages() {
let mock_forge = MockForge::new();
let orchestrator = create_test_orchestrator(mock_forge);
let mut temp_file = NamedTempFile::new().unwrap();
let packages = vec![
SerializableReleasablePackage {
name: "package-one".to_string(),
path: PathBuf::from("packages/one"),
release: create_test_release("1.0.0", "Pkg1 Existing notes"),
..Default::default()
},
SerializableReleasablePackage {
name: "package-two".to_string(),
path: PathBuf::from("packages/two"),
release: create_test_release("2.0.0", "Pkg2 Existing notes"),
..Default::default()
},
];
let json = serde_json::to_string(&packages).unwrap();
temp_file.write_all(json.as_bytes()).unwrap();
temp_file.flush().unwrap();
let result = orchestrator
.recompile_notes_from_release_file(&temp_file.path().to_string_lossy())
.await
.unwrap();
assert_eq!(result.len(), 2);
assert_eq!(result[0].name, "package-one");
assert_eq!(result[1].name, "package-two");
assert!(!result[0].release.notes.is_empty());
assert!(!result[1].release.notes.is_empty());
}
#[tokio::test]
async fn recompile_notes_from_release_file_renders_with_custom_template() {
let mock_forge = MockForge::new();
let mut config = Config::default();
config.changelog.body = "Version: {{ version }}".to_string();
let orchestrator =
create_test_orchestrator_with_config(mock_forge, vec![], Some(config));
let mut temp_file = NamedTempFile::new().unwrap();
let package = SerializableReleasablePackage {
name: "test-pkg".to_string(),
path: PathBuf::from("."),
release: create_test_release("3.2.1", "Release notes"),
..Default::default()
};
let json = serde_json::to_string(&vec![package]).unwrap();
temp_file.write_all(json.as_bytes()).unwrap();
temp_file.flush().unwrap();
let result = orchestrator
.recompile_notes_from_release_file(&temp_file.path().to_string_lossy())
.await
.unwrap();
assert_eq!(result.len(), 1);
assert_eq!(result[0].release.notes, "Version: 3.2.1");
}
#[tokio::test]
async fn recompile_notes_from_release_file_fails_with_nonexistent_file() {
let mock_forge = MockForge::new();
let orchestrator = create_test_orchestrator(mock_forge);
let result = orchestrator
.recompile_notes_from_release_file("/nonexistent/path/file.json")
.await;
assert!(result.is_err());
let err = result.unwrap_err();
assert!(err.to_string().contains("does not exist"));
}
#[tokio::test]
async fn recompile_notes_from_release_file_fails_with_invalid_json() {
let mock_forge = MockForge::new();
let orchestrator = create_test_orchestrator(mock_forge);
let mut temp_file = NamedTempFile::new().unwrap();
temp_file.write_all(b"not valid json").unwrap();
temp_file.flush().unwrap();
let result = orchestrator
.recompile_notes_from_release_file(&temp_file.path().to_string_lossy())
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn recompile_notes_from_release_file_handles_empty_array() {
let mock_forge = MockForge::new();
let orchestrator = create_test_orchestrator(mock_forge);
let mut temp_file = NamedTempFile::new().unwrap();
temp_file.write_all(b"[]").unwrap();
temp_file.flush().unwrap();
let result = orchestrator
.recompile_notes_from_release_file(&temp_file.path().to_string_lossy())
.await
.unwrap();
assert_eq!(result.len(), 0);
}
#[tokio::test]
async fn recompile_notes_from_release_file_fails_with_invalid_template() {
let mock_forge = MockForge::new();
let mut config = Config::default();
config.changelog.body = "{{ unclosed_variable".to_string();
let orchestrator =
create_test_orchestrator_with_config(mock_forge, vec![], Some(config));
let mut temp_file = NamedTempFile::new().unwrap();
let package = SerializableReleasablePackage {
name: "test-pkg".to_string(),
path: PathBuf::from("."),
release: create_test_release("1.0.0", "Release notes"),
..Default::default()
};
let json = serde_json::to_string(&vec![package]).unwrap();
temp_file.write_all(json.as_bytes()).unwrap();
temp_file.flush().unwrap();
let result = orchestrator
.recompile_notes_from_release_file(&temp_file.path().to_string_lossy())
.await;
assert!(result.is_err());
}