use rand::prelude::*; use rand_chacha::ChaCha12Rng; use requestty::question::Choice; use ui::events::{KeyCode, KeyEvent, TestEvents}; mod helpers; const SEED: u64 = 9828123; const SEP_RATIO: f32 = 0.3; const DEFAULT_SEP_RATIO: f32 = 0.10; fn choices(len: usize) -> impl Iterator> { let mut rng = ChaCha12Rng::seed_from_u64(SEED); (0..len).map(move |i| { let rand: f32 = rng.gen(); if rand < DEFAULT_SEP_RATIO { Choice::DefaultSeparator } else if rand < SEP_RATIO { Choice::Separator(format!("Separator {}", i)) } else { Choice::Choice(format!("Choice {}", i)) } }) } #[test] fn test_validate() { let multi_select = requestty::Question::multi_select("name") .validate(|checked, _| { let count = checked.iter().filter(|&&b| b).count(); if count > 1 { Ok(()) } else { Err(format!( "At least 2 items must be checked. {} items were checked", count )) } }) .message("multi select") .choices(choices(10)); let size = (50, 20).into(); let mut backend = helpers::SnapshotOnFlushBackend::new(size); let mut events = TestEvents::new(vec![ KeyEvent::from(KeyCode::Down), KeyCode::Char(' ').into(), KeyCode::Enter.into(), KeyCode::End.into(), KeyCode::Char(' ').into(), KeyCode::Enter.into(), ]); let ans: Vec<_> = requestty::prompt_one_with(multi_select, &mut backend, &mut events) .unwrap() .try_into_list_items() .unwrap() .into_iter() .map(|item| item.index) .collect(); assert_eq!(ans, [3, 9]); } #[test] fn test_filter() { let multi_select = requestty::Question::multi_select("name") .filter(|mut checked, _| { checked.iter_mut().for_each(|b| *b = !*b); checked }) .message("multi select") .choices(choices(10)); let size = (50, 20).into(); let mut backend = helpers::SnapshotOnFlushBackend::new(size); let mut events = TestEvents::new(vec![ KeyEvent::from(KeyCode::Down), KeyCode::Char(' ').into(), KeyCode::End.into(), KeyCode::Char(' ').into(), KeyCode::Enter.into(), ]); let ans: Vec<_> = requestty::prompt_one_with(multi_select, &mut backend, &mut events) .unwrap() .try_into_list_items() .unwrap() .into_iter() .map(|item| item.index) .collect(); assert_eq!(ans, [0, 4, 6, 7, 8]); } #[test] fn test_transform() { let multi_select = requestty::Question::multi_select("name") .transform(|items, _, b| { b.set_fg(ui::style::Color::Magenta)?; for (i, item) in items.iter().enumerate() { write!(b, "{}: {}", item.index, item.text)?; if i + 1 != items.len() { write!(b, ", ")?; } } b.set_fg(ui::style::Color::Reset) }) .message("multi select") .choices(choices(10)); let size = (50, 20).into(); let mut backend = helpers::SnapshotOnFlushBackend::new(size); let mut events = TestEvents::new(vec![ KeyEvent::from(KeyCode::Down), KeyCode::Char(' ').into(), KeyCode::End.into(), KeyCode::Char(' ').into(), KeyCode::Enter.into(), ]); let ans: Vec<_> = requestty::prompt_one_with(multi_select, &mut backend, &mut events) .unwrap() .try_into_list_items() .unwrap() .into_iter() .map(|item| item.index) .collect(); assert_eq!(ans, [3, 9]); } #[test] fn test_on_esc() { let size = (50, 20).into(); let mut backend = helpers::SnapshotOnFlushBackend::new(size); let mut events = TestEvents::new(Some(KeyCode::Esc.into())); let res = requestty::prompt_one_with( requestty::Question::multi_select("name") .message("message") .choices(choices(10)) .on_esc(requestty::OnEsc::Terminate), &mut backend, &mut events, ); assert!(matches!(res, Err(requestty::ErrorKind::Aborted))); let size = (50, 20).into(); let mut backend = helpers::SnapshotOnFlushBackend::new(size); let mut events = TestEvents::new(Some(KeyCode::Esc.into())); let res = requestty::prompt_with( Some( requestty::Question::multi_select("name") .message("message") .choices(choices(10)) .on_esc(requestty::OnEsc::SkipQuestion) .build(), ), &mut backend, &mut events, ) .unwrap(); assert!(res.is_empty()); }