use cantara_songlib::exporter::slides::{chapters_from_songs, slides_from_songs};
use cantara_songlib::exporter::text::{text_from_song, text_from_songs, TextFormat, TextSettings};
use cantara_songlib::importer::import_song_from_file;
use cantara_songlib::slides::{LinkedEntity, SlideSettings};
use cantara_songlib::song::Song;
const GRACE: &str = "tests/data/Amazing Grace.song.yml";
const CCLI: &str = "tests/data/Weiß ich den Weg auch nicht.ccli";
const CLASSIC: &str = "tests/data/O What A Savior That He Died For Me.song";
fn songs() -> Vec<Song> {
[GRACE, CCLI]
.iter()
.map(|path| import_song_from_file(path).expect("import"))
.collect()
}
#[test]
fn test_plain_text_carries_no_markup() {
for path in [GRACE, CCLI, CLASSIC] {
let song = import_song_from_file(path).unwrap();
let text = text_from_song(&song, &TextSettings::default()).unwrap();
assert!(text.starts_with(&song.title), "{}: no title:\n{}", path, text);
for artefact in ["--", "\\set", "\\unset", "##t", "_ ", "w:", "X:1"] {
assert!(
!text.contains(artefact),
"{}: '{}' leaked into the text:\n{}",
path,
artefact,
text
);
}
}
}
#[test]
fn test_singing_order_including_repeats() {
let song = import_song_from_file(CLASSIC).unwrap();
let text = text_from_song(&song, &TextSettings::default()).unwrap();
assert_eq!(text.matches("Verily, verily, I say unto you;").count(), 4);
assert_eq!(text.matches("Oh, what a Saviour that He died for me!").count(), 1);
}
#[test]
fn test_markdown_and_telegram_differ_only_in_the_heading() {
let song = import_song_from_file(GRACE).unwrap();
let markdown =
text_from_song(&song, &TextSettings::with_format(TextFormat::Markdown)).unwrap();
let telegram =
text_from_song(&song, &TextSettings::with_format(TextFormat::Telegram)).unwrap();
assert!(markdown.starts_with("# Amazing Grace"));
assert!(telegram.starts_with("**Amazing Grace**"));
let body = |text: &str| {
text.lines()
.skip_while(|line| !line.starts_with("Amazing grace"))
.collect::<Vec<_>>()
.join("\n")
};
assert_eq!(body(&markdown), body(&telegram));
}
#[test]
fn test_custom_template_sees_the_parts() {
let song = import_song_from_file("tests/data/Sei nicht stolz auf das, was du bist.song.yml")
.unwrap();
let settings = TextSettings::with_format(TextFormat::Custom(
"{{#each parts}}{{position}}:{{id}}{{#unless last}},{{/unless}}{{/each}}".to_string(),
));
let text = text_from_song(&song, &settings).unwrap();
assert_eq!(
text,
"1:verse.1,2:refrain.1,3:verse.2,4:refrain.1,5:verse.3,6:refrain.1"
);
}
#[test]
fn test_first_and_last_flags() {
let song = import_song_from_file(GRACE).unwrap();
let settings = TextSettings::with_format(TextFormat::Custom(
"{{#each parts}}{{#if first}}[{{/if}}{{number}}{{#if last}}]{{else}}-{{/if}}{{/each}}"
.to_string(),
));
assert_eq!(text_from_song(&song, &settings).unwrap(), "[1-2-3]");
}
#[test]
fn test_several_songs_into_one_document() {
let text =
text_from_songs(&songs(), &TextSettings::with_format(TextFormat::Markdown)).unwrap();
let headings: Vec<&str> = text.lines().filter(|line| line.starts_with("# ")).collect();
assert_eq!(
headings,
["# Amazing Grace", "# Weiß ich den Weg auch nicht (Pax Dei)"]
);
}
#[test]
fn test_song_separator() {
let settings = TextSettings {
song_separator: Some("· · ·".to_string()),
..TextSettings::default()
};
let text = text_from_songs(&songs(), &settings).unwrap();
assert_eq!(text.matches("· · ·").count(), 1);
assert!(!text.starts_with("· · ·"));
assert!(!text.trim_end().ends_with("· · ·"));
}
#[test]
fn test_chapters_keep_their_songs() {
let songs = songs();
let chapters = chapters_from_songs(&songs, &SlideSettings::default());
assert_eq!(chapters.len(), 2);
for (chapter, song) in chapters.iter().zip(songs.iter()) {
assert!(!chapter.slides.is_empty());
match &chapter.linked_entity {
LinkedEntity::Song(linked) => assert_eq!(linked, song),
other => panic!("expected a song link, got {:?}", other),
}
}
}
#[test]
fn test_flat_slides_match_the_chapters() {
let songs = songs();
let settings = SlideSettings::default();
let flat = slides_from_songs(&songs, &settings);
let from_chapters: Vec<_> = chapters_from_songs(&songs, &settings)
.into_iter()
.flat_map(|chapter| chapter.slides)
.collect();
assert_eq!(flat, from_chapters);
}
#[test]
fn test_chapters_round_trip_through_json() {
let chapters = chapters_from_songs(&songs(), &SlideSettings::default());
let json = serde_json::to_string(&chapters).expect("serialise");
let restored: Vec<cantara_songlib::slides::PresentationChapter> =
serde_json::from_str(&json).expect("deserialise");
assert_eq!(restored, chapters);
}
#[test]
fn test_no_songs_gives_no_chapters() {
assert!(chapters_from_songs(&[], &SlideSettings::default()).is_empty());
assert!(slides_from_songs(&[], &SlideSettings::default()).is_empty());
assert_eq!(text_from_songs(&[], &TextSettings::default()).unwrap(), "");
}