use vortex_session::VortexSession;
use crate::Edition;
use crate::EditionDeclaration;
use crate::EditionId;
use crate::EditionInclusion;
use crate::EditionSession;
use crate::EditionSessionExt;
use crate::EnabledEditions;
const FIRST: EditionId = EditionId::new("test", 2026, 1, 0);
const SECOND: EditionId = EditionId::new("test", 2026, 7, 0);
static DECLARATIONS: &[EditionDeclaration] = &[
EditionDeclaration {
edition: Edition {
id: FIRST,
min_vortex_version: None,
},
added: &[&"test.alpha", &"test.beta"],
},
EditionDeclaration {
edition: Edition {
id: SECOND,
min_vortex_version: None,
},
added: &[&"test.gamma"],
},
];
fn session() -> EditionSession {
let editions = EditionSession::empty();
for declaration in DECLARATIONS {
editions
.declare(declaration)
.unwrap_or_else(|e| panic!("declaring test editions: {e}"));
}
editions
}
#[test]
fn editions_pass_the_test_harness() -> Result<(), crate::EditionError> {
crate::test_harness::validate_edition(&session(), &FIRST)?;
crate::test_harness::validate_edition(&session(), &SECOND)?;
let undeclared = EditionId::new("test", 2027, 1, 0);
assert!(crate::test_harness::validate_edition(&session(), &undeclared).is_err());
Ok(())
}
#[test]
fn membership_is_transitive() {
let editions = session();
let first = editions.encodings_in(&FIRST);
let ids: Vec<&str> = first.iter().map(|i| i.encoding_id.as_str()).collect();
assert_eq!(ids, ["test.alpha", "test.beta"]);
let second = editions.encodings_in(&SECOND);
let ids: Vec<&str> = second.iter().map(|i| i.encoding_id.as_str()).collect();
assert_eq!(ids, ["test.alpha", "test.beta", "test.gamma"]);
assert!(
second
.iter()
.filter(|i| i.encoding_id.as_str() != "test.gamma")
.all(|i| i.since == FIRST)
);
let added: Vec<&str> = second
.iter()
.filter(|i| i.since == SECOND)
.map(|i| i.encoding_id.as_str())
.collect();
assert_eq!(added, ["test.gamma"]);
assert!(first.iter().all(|i| i.since == FIRST));
let third = EditionId::new("test", 2026, 10, 0);
assert_eq!(editions.encodings_in(&third).len(), 3);
let other = EditionId::new("other", 2026, 10, 0);
assert!(editions.encodings_in(&other).is_empty());
}
#[test]
fn drafts_and_current() {
let editions = session();
assert!(editions.find(&FIRST).is_some_and(|e| e.is_draft()));
assert!(editions.current("test").is_none());
let editions = EditionSession::empty();
editions
.declare_edition(Edition {
id: FIRST,
min_vortex_version: Some("0.60.0"),
})
.unwrap();
editions
.declare_edition(Edition {
id: SECOND,
min_vortex_version: None,
})
.unwrap();
assert!(editions.validate().is_ok());
assert_eq!(editions.current("test").map(|e| e.id), Some(FIRST));
}
#[test]
fn session_exposes_edition_registry() {
let session = VortexSession::empty().with::<EditionSession>();
assert!(session.editions().find(&FIRST).is_none());
for declaration in DECLARATIONS {
session.editions().declare(declaration).unwrap();
}
assert!(session.editions().find(&FIRST).is_some());
}
#[test]
fn registered_and_enabled_editions_are_separate() -> Result<(), crate::EditionError> {
let session = VortexSession::empty().with::<EditionSession>();
for declaration in DECLARATIONS {
session.register_edition(declaration)?;
}
assert!(session.enabled_encoding_ids().is_empty());
session.enable_edition(FIRST)?;
assert_eq!(session.enabled_editions().editions(), [FIRST]);
assert_eq!(
session
.enabled_encoding_ids()
.iter()
.map(|id| id.as_str())
.collect::<Vec<_>>(),
["test.alpha", "test.beta"]
);
session.enable_edition(SECOND)?;
assert_eq!(session.enabled_editions().editions(), [SECOND]);
assert_eq!(session.enabled_encoding_ids().len(), 3);
session.enable_edition(FIRST)?;
assert_eq!(session.enabled_editions().editions(), [FIRST]);
let enabled = session.enabled_encoding_ids();
assert_eq!(enabled.len(), 2);
assert!(enabled.iter().all(|id| id.as_str() != "test.gamma"));
Ok(())
}
#[test]
fn enabling_requires_registration() {
let session = VortexSession::empty().with::<EnabledEditions>();
assert!(session.enable_edition(FIRST).is_err());
assert!(session.enabled_editions().editions().is_empty());
}
#[test]
fn enabled_editions_are_independent_across_families() -> Result<(), crate::EditionError> {
const OTHER: EditionId = EditionId::new("other", 2026, 4, 0);
static OTHER_DECLARATION: EditionDeclaration = EditionDeclaration {
edition: Edition {
id: OTHER,
min_vortex_version: None,
},
added: &[&"other.delta"],
};
let session = VortexSession::empty().with::<EditionSession>();
session.register_edition(&DECLARATIONS[0])?;
session.register_edition(&OTHER_DECLARATION)?;
session.enable_edition(FIRST)?;
session.enable_edition(OTHER)?;
let mut enabled = session.enabled_editions().editions();
enabled.sort_unstable();
assert_eq!(enabled, [OTHER, FIRST]);
assert_eq!(session.enabled_encoding_ids().len(), 3);
Ok(())
}
#[test]
fn duplicate_declarations_error() {
let editions = session();
assert!(
editions
.declare_edition(Edition {
id: FIRST,
min_vortex_version: None,
})
.is_err()
);
assert!(
editions
.declare_inclusion(EditionInclusion::new("test.alpha", FIRST))
.is_err()
);
}
#[test]
fn validate_rejects_inconsistent_declarations() -> Result<(), crate::EditionError> {
let editions = EditionSession::empty();
editions.declare_inclusion(EditionInclusion::new("test.alpha", FIRST))?;
assert!(editions.validate().is_err());
let editions = EditionSession::empty();
editions.declare_edition(Edition {
id: FIRST,
min_vortex_version: Some("0.70.0"),
})?;
editions.declare_inclusion(EditionInclusion {
required_vortex_release: Some("0.80.0"),
..EditionInclusion::new("test.alpha", FIRST)
})?;
assert!(editions.validate().is_err());
let editions = EditionSession::empty();
editions.declare_edition(Edition {
id: FIRST,
min_vortex_version: None,
})?;
editions.declare_edition(Edition {
id: SECOND,
min_vortex_version: Some("0.70.0"),
})?;
assert!(editions.validate().is_err());
let editions = EditionSession::empty();
editions.declare_edition(Edition {
id: EditionId::new("Test", 2026, 13, 0),
min_vortex_version: None,
})?;
assert!(editions.validate().is_err());
let editions = EditionSession::empty();
editions.declare_edition(Edition {
id: FIRST,
min_vortex_version: None,
})?;
editions.declare_inclusion(EditionInclusion::new("Test.ALPHA", FIRST))?;
assert!(editions.validate().is_err());
Ok(())
}
#[test]
fn edition_ids_order_within_family_only() {
assert!(FIRST.is_at_or_before(&SECOND));
assert!(!SECOND.is_at_or_before(&FIRST));
let other = EditionId::new("other", 2026, 3, 0);
assert!(!FIRST.is_at_or_before(&other));
assert!(!other.is_at_or_before(&FIRST));
}
#[test]
fn edition_id_display() {
assert_eq!(FIRST.to_string(), "test2026.01.0");
}