use std::path::Path;
use unbundle::MediaFile;
fn sample_with_chapters_path() -> &'static str {
"tests/fixtures/sample_with_chapters.mkv"
}
fn sample_video_path() -> &'static str {
"tests/fixtures/sample_video.mp4"
}
#[test]
fn chapters_present_in_file_with_chapters() {
let path = sample_with_chapters_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let unbundler = MediaFile::open(path).expect("Failed to open");
let metadata = unbundler.metadata();
let chapters = metadata
.chapters
.as_ref()
.expect("Expected chapters in fixture");
assert_eq!(chapters.len(), 3, "Expected 3 chapters");
}
#[test]
fn chapter_titles_match() {
let path = sample_with_chapters_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let unbundler = MediaFile::open(path).expect("Failed to open");
let chapters = unbundler
.metadata()
.chapters
.as_ref()
.expect("Expected chapters")
.clone();
assert_eq!(chapters[0].title.as_deref(), Some("Introduction"));
assert_eq!(chapters[1].title.as_deref(), Some("Main Content"));
assert_eq!(chapters[2].title.as_deref(), Some("Conclusion"));
}
#[test]
fn chapter_timestamps_are_ordered() {
let path = sample_with_chapters_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let unbundler = MediaFile::open(path).expect("Failed to open");
let chapters = unbundler
.metadata()
.chapters
.as_ref()
.expect("Expected chapters")
.clone();
for window in chapters.windows(2) {
assert!(
window[0].end <= window[1].start || window[0].end == window[1].start,
"Chapters should be ordered: {:?} should end before {:?} starts",
window[0],
window[1]
);
}
}
#[test]
fn chapter_indices_are_sequential() {
let path = sample_with_chapters_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let unbundler = MediaFile::open(path).expect("Failed to open");
let chapters = unbundler
.metadata()
.chapters
.as_ref()
.expect("Expected chapters")
.clone();
for (i, chapter) in chapters.iter().enumerate() {
assert_eq!(chapter.index, i, "Chapter index should be sequential");
}
}
#[test]
fn no_chapters_in_file_without() {
let path = sample_video_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let unbundler = MediaFile::open(path).expect("Failed to open");
assert!(
unbundler.metadata().chapters.is_none(),
"sample_video.mp4 should have no chapters"
);
}
#[test]
fn chapter_start_end_durations() {
let path = sample_with_chapters_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let unbundler = MediaFile::open(path).expect("Failed to open");
let chapters = unbundler
.metadata()
.chapters
.as_ref()
.expect("Expected chapters")
.clone();
let first = &chapters[0];
assert!(
first.start.as_secs_f64() < 0.1,
"First chapter should start near 0"
);
assert!(
(first.end.as_secs_f64() - 2.0).abs() < 0.1,
"First chapter should end near 2s, got {:?}",
first.end,
);
}