use std::{path::Path, time::Duration};
use unbundle::{MediaFile, SubtitleFormat, UnbundleError};
fn sample_with_subtitles() -> &'static str {
"tests/fixtures/sample_with_subtitles.mkv"
}
fn sample_video_path() -> &'static str {
"tests/fixtures/sample_video.mp4"
}
#[test]
fn extract_subtitle_entries() {
let path = sample_with_subtitles();
if !Path::new(path).exists() {
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open fixture");
let entries = unbundler
.subtitle()
.extract()
.expect("Failed to extract subtitles");
assert!(!entries.is_empty(), "Expected at least one subtitle entry");
let first = &entries[0];
assert!(!first.text.is_empty(), "Subtitle text should not be empty");
assert!(first.end_time >= first.start_time, "end_time >= start_time");
}
#[test]
fn save_subtitles_srt() {
let path = sample_with_subtitles();
if !Path::new(path).exists() {
return;
}
let tmp = tempfile::NamedTempFile::new().expect("Failed to create temp file");
let output_path = tmp.path().with_extension("srt");
let mut unbundler = MediaFile::open(path).expect("Failed to open fixture");
unbundler
.subtitle()
.save(&output_path, SubtitleFormat::Srt)
.expect("Failed to save SRT");
let content = std::fs::read_to_string(&output_path).expect("Failed to read SRT");
assert!(!content.is_empty(), "SRT file should not be empty");
assert!(
content.contains("1\n") || content.contains("1\r\n"),
"SRT should start with cue 1"
);
assert!(
content.contains("-->"),
"SRT should contain --> timestamp separator"
);
let _ = std::fs::remove_file(&output_path);
}
#[test]
fn save_subtitles_webvtt() {
let path = sample_with_subtitles();
if !Path::new(path).exists() {
return;
}
let tmp = tempfile::NamedTempFile::new().expect("Failed to create temp file");
let output_path = tmp.path().with_extension("vtt");
let mut unbundler = MediaFile::open(path).expect("Failed to open fixture");
unbundler
.subtitle()
.save(&output_path, SubtitleFormat::WebVtt)
.expect("Failed to save WebVTT");
let content = std::fs::read_to_string(&output_path).expect("Failed to read WebVTT");
assert!(
content.starts_with("WEBVTT"),
"WebVTT must have WEBVTT header"
);
assert!(
content.contains("-->"),
"WebVTT should contain --> separator"
);
let _ = std::fs::remove_file(&output_path);
}
#[test]
fn extract_subtitle_text() {
let path = sample_with_subtitles();
if !Path::new(path).exists() {
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open fixture");
let text = unbundler
.subtitle()
.extract_text(SubtitleFormat::Raw)
.expect("Failed to extract subtitle text");
assert!(!text.is_empty(), "Extracted text should not be empty");
}
#[test]
fn subtitle_format_display() {
assert_eq!(format!("{}", SubtitleFormat::Srt), "SRT");
assert_eq!(format!("{}", SubtitleFormat::WebVtt), "WebVTT");
assert_eq!(format!("{}", SubtitleFormat::Raw), "Raw");
}
#[test]
fn no_subtitle_stream_error() {
let path = sample_video_path();
if !Path::new(path).exists() {
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open fixture");
let result = unbundler.subtitle().extract();
assert!(result.is_err());
match result.unwrap_err() {
UnbundleError::NoSubtitleStream => {}
other => panic!("Expected NoSubtitleStream, got: {other}"),
}
}
#[test]
fn subtitle_metadata_present() {
let path = sample_with_subtitles();
if !Path::new(path).exists() {
return;
}
let unbundler = MediaFile::open(path).expect("Failed to open fixture");
let metadata = unbundler.metadata();
assert!(
metadata.subtitle.is_some(),
"Expected subtitle metadata for fixture with subtitles",
);
let sub = metadata.subtitle.as_ref().unwrap();
assert!(!sub.codec.is_empty(), "Subtitle codec should be non-empty");
}
#[test]
fn subtitle_tracks_listed() {
let path = sample_with_subtitles();
if !Path::new(path).exists() {
return;
}
let unbundler = MediaFile::open(path).expect("Failed to open fixture");
let metadata = unbundler.metadata();
if let Some(tracks) = &metadata.subtitle_tracks {
assert!(!tracks.is_empty(), "Expected at least one subtitle track");
}
}
#[test]
fn render_at_returns_none_when_no_bitmap_event_at_time() {
let path = sample_with_subtitles();
if !Path::new(path).exists() {
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open fixture");
let rendered = unbundler
.subtitle()
.render_at(Duration::from_secs(0))
.expect("render_at failed");
if let Some(image) = rendered {
assert!(image.width() > 0);
assert!(image.height() > 0);
}
}
#[test]
fn bitmap_event_as_image_accessor_compiles_and_returns_image() {
let path = sample_with_subtitles();
if !Path::new(path).exists() {
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open fixture");
let bitmaps = unbundler
.subtitle()
.extract_bitmaps()
.expect("extract_bitmaps failed");
if let Some(first) = bitmaps.first() {
let image = first.as_image();
assert!(image.width() > 0);
assert!(image.height() > 0);
}
}