#include "scroller_streams.h" #include "db/database_manager.h" #include #include #include #include namespace { using radiantwave::db::AudioFileRecord; using radiantwave::db::ProclamationRecord; using radiantwave::scroller::ProclamationStream; using radiantwave::scroller::StreamColor; using radiantwave::scroller::buildStreams; using radiantwave::scroller::kDefaultRepeatCount; using radiantwave::scroller::kSelectedRepeatCount; const std::string kDefaultId = "default"; std::vector palette() { StreamColor c; c.r = 10; c.g = 20; c.b = 30; return {c}; } } // namespace TEST(ScrollerStreamsTest, InterleavesSelectedWithDefault) { ProclamationRecord p1; p1.id = "one"; p1.title = "One"; p1.content = "hello world"; p1.selected = true; p1.solfeggio_frequency_id = 2; ProclamationRecord p2; p2.id = "two"; p2.title = "Two"; p2.content = "foo bar baz"; p2.selected = true; p2.solfeggio_frequency_id = 5; ProclamationRecord def; def.id = kDefaultId; def.title = "Default"; def.content = "default text"; def.selected = true; def.solfeggio_frequency_id = 5; std::unordered_map> palettes; palettes[2] = palette(); std::unordered_map audio; AudioFileRecord af; af.id = 1; af.filename = "396Hz.wav"; af.solfeggio_frequency_id = 2; audio[2] = af; auto streams = buildStreams({p1, p2, def}, palettes, palette(), audio, kDefaultId); // The first user-selected proclamation plays first, followed by the // default, then the next selected, then the default again. ASSERT_EQ(streams.size(), 4u); EXPECT_EQ(streams[0].name, "One"); ASSERT_EQ(streams[0].words.size(), 2u); EXPECT_EQ(streams[0].words[0], "hello"); EXPECT_EQ(streams[0].words[1], "world"); EXPECT_EQ(streams[0].repeat, kSelectedRepeatCount); EXPECT_EQ(streams[0].solfeggio_frequency_id, 2); EXPECT_EQ(streams[0].audioFilename, "396Hz.wav"); EXPECT_EQ(streams[0].palette.size(), 1u); EXPECT_EQ(streams[1].name, "Default"); EXPECT_EQ(streams[1].repeat, kDefaultRepeatCount); EXPECT_EQ(streams[1].solfeggio_frequency_id, 5); EXPECT_EQ(streams[1].audioFilename, "OriginalAudio.wav"); // no audio for freq 5 EXPECT_EQ(streams[1].palette.size(), 1u); // falls back to 528 palette EXPECT_EQ(streams[2].name, "Two"); EXPECT_EQ(streams[2].repeat, kSelectedRepeatCount); EXPECT_EQ(streams[2].palette.size(), 1u); // falls back to 528 palette EXPECT_EQ(streams[3].name, "Default"); EXPECT_EQ(streams[3].repeat, kDefaultRepeatCount); EXPECT_EQ(streams[3].audioFilename, "OriginalAudio.wav"); } TEST(ScrollerStreamsTest, DefaultOnlyWhenNothingSelected) { ProclamationRecord p1; p1.id = "one"; p1.title = "One"; p1.content = "x"; p1.selected = false; ProclamationRecord def; def.id = kDefaultId; def.title = "Default"; def.content = "y"; def.selected = true; auto streams = buildStreams({p1, def}, {}, palette(), {}, kDefaultId); ASSERT_EQ(streams.size(), 1u); EXPECT_EQ(streams[0].name, "Default"); EXPECT_EQ(streams[0].repeat, kDefaultRepeatCount); } TEST(ScrollerStreamsTest, MissingDefaultStillStreamsSelected) { ProclamationRecord p1; p1.id = "one"; p1.title = "One"; p1.content = "x"; p1.selected = true; auto streams = buildStreams({p1}, {}, palette(), {}, kDefaultId); ASSERT_EQ(streams.size(), 1u); EXPECT_EQ(streams[0].name, "One"); EXPECT_EQ(streams[0].repeat, kSelectedRepeatCount); } TEST(ScrollerStreamsTest, SplitsGluedSentencePunctuation) { ProclamationRecord p1; p1.id = "one"; p1.title = "One"; p1.content = "state?Create NOW?KING field’s fine (Acts 17:27)I example.com"; p1.selected = true; auto streams = buildStreams({p1}, {}, palette(), {}, kDefaultId); ASSERT_EQ(streams.size(), 1u); const auto& words = streams[0].words; // "?" glued to an uppercase word splits after the punctuation, keeping the // sentence separator attached to the preceding word. EXPECT_EQ(words[0], "state?"); EXPECT_EQ(words[1], "Create"); EXPECT_EQ(words[2], "NOW?"); EXPECT_EQ(words[3], "KING"); // Curly apostrophes are not sentence punctuation and stay inside the word. EXPECT_EQ(words[4], "field’s"); EXPECT_EQ(words[5], "fine"); // Closing paren followed by an uppercase letter splits so the verse // reference and the next word are separate tokens. EXPECT_EQ(words[6], "(Acts"); EXPECT_EQ(words[7], "17:27)"); EXPECT_EQ(words[8], "I"); // A lowercase continuation after a dot is not a new sentence, so this // stays intact. EXPECT_EQ(words[9], "example.com"); }