use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
use noesis_runtime::binding::ObservableCollection;
use noesis_runtime::collection_view::CollectionViewSource;
#[test]
fn collection_view_current_item_navigation() {
if let (Ok(name), Ok(key)) = (
std::env::var("NOESIS_LICENSE_NAME"),
std::env::var("NOESIS_LICENSE_KEY"),
) {
noesis_runtime::set_license(&name, &key);
}
noesis_runtime::init();
{
let mut list = ObservableCollection::new();
list.push_string("alpha");
list.push_string("beta");
list.push_string("gamma");
let mut cvs = CollectionViewSource::new();
assert!(
cvs.set_source(&list),
"set_source on a CollectionViewSource"
);
let view = cvs
.view()
.expect("GetView returns a CollectionView once Source is set");
assert_eq!(view.count(), 3, "view sees all 3 source records");
let counter = Arc::new(AtomicU32::new(0));
let counter_cb = Arc::clone(&counter);
let _sub = view
.subscribe_current_changed(move || {
counter_cb.fetch_add(1, Ordering::SeqCst);
})
.expect("subscribe to CurrentChanged");
assert!(view.move_current_to_first(), "first is a valid record");
assert_eq!(view.current_position(), 0);
assert_eq!(
view.current_item().and_then(|i| i.as_string()).as_deref(),
Some("alpha"),
"current item is alpha"
);
assert!(view.move_current_to_next());
assert_eq!(view.current_position(), 1);
assert_eq!(
view.current_item().and_then(|i| i.as_string()).as_deref(),
Some("beta"),
);
assert!(view.move_current_to_last());
assert_eq!(view.current_position(), 2);
assert_eq!(
view.current_item().and_then(|i| i.as_string()).as_deref(),
Some("gamma"),
);
let _ = view.move_current_to_next();
assert!(view.is_current_after_last(), "cursor is after the last");
assert!(
view.current_item().is_none(),
"no current item past the end"
);
assert_eq!(view.current_position(), 3, "after-last position is count");
assert!(view.move_current_to_position(1));
assert_eq!(view.current_position(), 1);
assert_eq!(
view.current_item().and_then(|i| i.as_string()).as_deref(),
Some("beta"),
);
let _ = view.move_current_to_previous();
assert_eq!(view.current_position(), 0);
let _ = view.move_current_to_previous();
assert!(view.is_current_before_first(), "cursor is before the first");
assert!(
view.current_item().is_none(),
"no current item before the start"
);
assert_eq!(view.current_position(), -1, "before-first position is -1");
assert!(view.move_current_to_first());
let item = view.current_item().expect("current item");
let src0 = list.get(0).expect("source[0]");
assert_eq!(
item.raw(),
src0.as_ptr(),
"current item is the same boxed object as source[0]"
);
view.refresh();
assert!(
counter.load(Ordering::SeqCst) > 0,
"CurrentChanged fired at least once during navigation"
);
}
{
let mut list = ObservableCollection::new();
list.push_bool(true);
list.push_i32(42);
list.push_f64(3.5);
let mut cvs = CollectionViewSource::new();
assert!(cvs.set_source(&list), "set_source on a typed collection");
let view = cvs.view().expect("GetView once Source is set");
assert_eq!(view.count(), 3);
assert!(view.move_current_to_first());
let item = view.current_item().expect("bool current item");
assert_eq!(item.as_bool(), Some(true), "bool item round-trips");
assert_eq!(item.as_i32(), None, "bool item is not an i32");
assert_eq!(item.as_string(), None, "bool item is not a string");
assert!(view.move_current_to_next());
let item = view.current_item().expect("i32 current item");
assert_eq!(item.as_i32(), Some(42), "i32 item round-trips");
assert_eq!(item.as_string(), None, "i32 item is not a string");
assert!(view.move_current_to_next());
let item = view.current_item().expect("f64 current item");
assert_eq!(item.as_f64(), Some(3.5), "f64 item round-trips");
assert_eq!(item.as_bool(), None, "f64 item is not a bool");
}
noesis_runtime::shutdown();
}