mod common;
use bubbles::saliency::{BestLeastRecentlyViewed, FirstAvailable};
use bubbles::{HashMapStorage, Runner, compile};
use common::drain_line_texts;
#[test]
fn first_available_line_group_always_picks_first() {
let src = "\
title: Bark
---
=> Line A.
=> Line B.
=> Line C.
===
";
let prog = compile(src).unwrap();
let mut runner = Runner::new(prog, HashMapStorage::new());
runner.start("Bark").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Line A."]);
runner.start("Bark").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Line A."]);
}
#[test]
fn blrv_line_group_cycles_through_variants() {
let src = "\
title: Bark
---
=> Line A.
=> Line B.
=> Line C.
===
";
let prog = compile(src).unwrap();
let mut runner = Runner::new(prog, HashMapStorage::new());
runner.set_saliency(BestLeastRecentlyViewed::new());
runner.start("Bark").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Line A."]);
runner.start("Bark").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Line B."]);
runner.start("Bark").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Line C."]);
runner.start("Bark").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Line A."]);
}
#[test]
fn blrv_node_group_cycles() {
let src = "\
title: Shop
when: true
---
Still stocked.
===
title: Shop
when: true
---
Almost empty.
===
";
let prog = compile(src).unwrap();
let mut runner = Runner::new(prog, HashMapStorage::new());
runner.set_saliency(BestLeastRecentlyViewed::new());
runner.start("Shop").unwrap();
let t1 = drain_line_texts(&mut runner);
runner.start("Shop").unwrap();
let t2 = drain_line_texts(&mut runner);
assert_ne!(t1, t2, "BLRV should alternate between node variants");
}
#[test]
fn blrv_skips_unavailable_guarded_variant() {
let src = "\
title: Bark
---
=> Line A if false. <<if false>>
=> Line B.
===
";
let prog = compile(src).unwrap();
let mut runner = Runner::new(prog, HashMapStorage::new());
runner.set_saliency(BestLeastRecentlyViewed::new());
runner.start("Bark").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Line B."]);
}
#[test]
fn custom_strategy_always_picks_last() {
use bubbles::saliency::{Candidate, SaliencyStrategy};
struct AlwaysLast;
impl SaliencyStrategy for AlwaysLast {
fn select(&mut self, candidates: &[Candidate<'_>]) -> Option<usize> {
candidates
.iter()
.enumerate()
.rev()
.find(|(_, c)| c.available)
.map(|(i, _)| i)
}
}
let src = "\
title: Lines
---
=> First.
=> Second.
=> Third.
===
";
let prog = compile(src).unwrap();
let mut runner = Runner::new(prog, HashMapStorage::new());
runner.set_saliency(AlwaysLast);
runner.start("Lines").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Third."]);
}
#[test]
fn hashmap_provider_translates_line_ids() {
use bubbles::{HashMapProvider, PassthroughProvider};
let src = "\
title: Intro
---
Greetings! #line:greeting_id
===
";
let prog = compile(src).unwrap();
let mut runner = Runner::new(prog.clone(), HashMapStorage::new());
runner.set_provider(PassthroughProvider);
runner.start("Intro").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Greetings!"]);
let mut provider = HashMapProvider::new();
provider.insert("greeting_id", "Hallo!");
let mut runner2 = Runner::new(prog, HashMapStorage::new());
runner2.set_provider(provider);
runner2.start("Intro").unwrap();
assert_eq!(drain_line_texts(&mut runner2), ["Hallo!"]);
}
#[test]
fn first_available_strategy_set_explicitly() {
let src = "\
title: T
---
=> Alpha.
=> Beta.
===
";
let prog = compile(src).unwrap();
let mut runner = Runner::new(prog, HashMapStorage::new());
runner.set_saliency(FirstAvailable);
runner.start("T").unwrap();
assert_eq!(drain_line_texts(&mut runner), ["Alpha."]);
}