use pretty_assertions::assert_eq;
use super::{
bundled_current_display, latest_section, parse_request, section_for_version, ChangelogGroup,
ChangelogRequest, ChangelogRequestError, ChangelogSection, ChangelogSource, BUNDLED_CHANGELOG,
};
const SAMPLE: &str = r#"# Changelog
## [1.25.1](https://example.test/compare/v1.25.0...v1.25.1) (2026-07-31)
### Bug Fixes
* **tui:** suppress false notice ([#675](https://example.test/issues/675)) ([5a354f0](https://example.test/commit/5a354f0))
* **tui:** validate attachments ([#677](https://example.test/issues/677))
## [1.25.0](https://example.test/compare/v1.24.1...v1.25.0) (2026-07-31)
### Features
* **hooks:** add typed lifecycle hooks ([#668](https://example.test/issues/668))
### Dependencies
* The following workspace dependencies were updated
* dependencies
* rho-sdk bumped from 1.13.1 to 1.14.0
## [1.24.0] - 2026-07-30
### Features
- plain dash item without links
"#;
#[test]
fn section_for_version_returns_only_the_requested_release() {
assert_eq!(
section_for_version(SAMPLE, "1.25.1"),
Some(ChangelogSection {
version: "1.25.1".into(),
date: Some("2026-07-31".into()),
groups: vec![ChangelogGroup {
title: "Bug Fixes".into(),
items: vec![
"tui: suppress false notice (#675) (5a354f0)".into(),
"tui: validate attachments (#677)".into(),
],
}],
})
);
}
#[test]
fn section_for_version_skips_dependency_groups() {
let section = section_for_version(SAMPLE, "1.25.0").expect("section exists");
assert_eq!(
section,
ChangelogSection {
version: "1.25.0".into(),
date: Some("2026-07-31".into()),
groups: vec![ChangelogGroup {
title: "Features".into(),
items: vec!["hooks: add typed lifecycle hooks (#668)".into()],
}],
}
);
}
#[test]
fn latest_section_uses_document_order() {
let section = latest_section(SAMPLE).expect("section exists");
assert_eq!(section.version, "1.25.1");
}
#[test]
fn classic_heading_and_dash_bullets_parse() {
assert_eq!(
section_for_version(SAMPLE, "v1.24.0"),
Some(ChangelogSection {
version: "1.24.0".into(),
date: Some("2026-07-30".into()),
groups: vec![ChangelogGroup {
title: "Features".into(),
items: vec!["plain dash item without links".into()],
}],
})
);
}
#[test]
fn missing_or_unreleased_versions_return_none() {
assert_eq!(section_for_version(SAMPLE, "9.9.9"), None);
assert_eq!(
section_for_version(
"## [Unreleased]\n\n### Features\n\n* pending\n",
"Unreleased"
),
None
);
}
#[test]
fn parse_request_accepts_current_and_latest_only() {
assert_eq!(parse_request(""), Ok(ChangelogRequest::Current));
assert_eq!(parse_request(" "), Ok(ChangelogRequest::Current));
assert_eq!(parse_request("latest"), Ok(ChangelogRequest::Latest));
assert_eq!(parse_request("LATEST"), Ok(ChangelogRequest::Latest));
assert_eq!(parse_request("all"), Err(ChangelogRequestError::Usage));
assert_eq!(
parse_request("latest please"),
Err(ChangelogRequestError::Usage)
);
}
#[test]
fn bundled_changelog_contains_this_package_version() {
let display = bundled_current_display(env!("CARGO_PKG_VERSION"))
.expect("bundled changelog should include this package version");
assert_eq!(display.source, ChangelogSource::Bundled);
assert_eq!(display.section.version, env!("CARGO_PKG_VERSION"));
assert!(
!display.section.groups.is_empty(),
"bundled section should retain at least one non-dependency group"
);
assert!(
latest_section(BUNDLED_CHANGELOG).is_some(),
"bundled changelog should parse at least one section"
);
}