use super::*;
type DisplayOptionCheck = fn(&DashboardState) -> bool;
#[test]
fn options_popup_toggles_and_cycles_display_settings() {
let cases: [(&str, Option<usize>, DisplayOptionCheck); 4] = [
("show avatars", None, |state| {
!state.display_options().show_avatars
}),
("image preview quality", Some(3), |state| {
state.display_options().image_preview_quality == ImagePreviewQualityPreset::High
}),
("attachment viewer quality", Some(4), |state| {
state.display_options().attachment_viewer_quality
== ImagePreviewQualityPreset::Efficient
}),
("media playback", Some(7), |state| {
state.display_options().media_playback
}),
];
for (label, rows, expected) in cases {
let mut state = state_with_messages(1);
state.open_options_popup();
match rows {
None => {
handle_key(&mut state, key(KeyCode::Down));
}
Some(rows) => {
handle_key(&mut state, key(KeyCode::Enter));
for _ in 0..rows {
handle_key(&mut state, key(KeyCode::Down));
}
}
}
handle_key(&mut state, key(KeyCode::Enter));
assert!(
state.is_active_modal_popup(crate::tui::state::ActiveModalPopupKind::Options),
"{label}"
);
assert!(expected(&state), "{label}");
assert_eq!(
state.take_options_save_request(),
Some(AppOptions {
display: state.display_options(),
composer: state.composer_options(),
credentials: Default::default(),
notifications: state.notification_options(),
voice: state.voice_options(),
presence: Default::default(),
}),
"{label}"
);
}
}
#[test]
fn options_popup_h_l_adjust_microphone_sensitivity_by_one_or_ten_db() {
let mut state = state_with_messages(1);
handle_key(&mut state, char_key(' '));
handle_key(&mut state, char_key('o'));
handle_key(&mut state, char_key('v'));
for _ in 0..8 {
handle_key(&mut state, key(KeyCode::Down));
}
handle_key(&mut state, char_key('h'));
assert_eq!(
state.voice_options().microphone_sensitivity,
MicrophoneSensitivityDb::new(-31)
);
handle_key(&mut state, char_key('H'));
assert_eq!(
state.voice_options().microphone_sensitivity,
MicrophoneSensitivityDb::new(-41)
);
handle_key(&mut state, char_key('l'));
assert_eq!(
state.voice_options().microphone_sensitivity,
MicrophoneSensitivityDb::new(-40)
);
handle_key(&mut state, char_key('L'));
assert_eq!(
state.voice_options().microphone_sensitivity,
MicrophoneSensitivityDb::new(-30)
);
handle_key(&mut state, key(KeyCode::Down));
handle_key(&mut state, char_key('H'));
assert_eq!(
state.voice_options().microphone_volume,
VoiceVolumePercent::new(90)
);
handle_key(&mut state, char_key('l'));
assert_eq!(
state.voice_options().microphone_volume,
VoiceVolumePercent::new(91)
);
assert_eq!(
state.take_options_save_request(),
Some(AppOptions {
display: state.display_options(),
composer: state.composer_options(),
credentials: Default::default(),
notifications: state.notification_options(),
voice: state.voice_options(),
presence: Default::default(),
})
);
}
#[test]
fn options_popup_uses_configured_close_popup_key() {
let mut state = state_with_keymap(KeymapOptions {
leader: None,
groups: std::collections::BTreeMap::new(),
mappings: [("ClosePopup".to_owned(), KeymapBinding::one("x"))]
.into_iter()
.collect(),
..Default::default()
});
state.open_options_popup();
handle_key(&mut state, char_key('q'));
assert!(state.is_active_modal_popup(crate::tui::state::ActiveModalPopupKind::Options));
handle_key(&mut state, key(KeyCode::Esc));
assert!(!state.is_active_modal_popup(crate::tui::state::ActiveModalPopupKind::Options));
state.open_options_popup();
handle_key(&mut state, char_key('x'));
assert!(!state.is_active_modal_popup(crate::tui::state::ActiveModalPopupKind::Options));
let mut state = state_with_keymap(KeymapOptions {
leader: None,
groups: std::collections::BTreeMap::new(),
mappings: [("ClosePopup".to_owned(), KeymapBinding::one("pagedown"))]
.into_iter()
.collect(),
..Default::default()
});
state.open_options_popup();
handle_key(&mut state, key(KeyCode::PageDown));
assert!(!state.is_active_modal_popup(crate::tui::state::ActiveModalPopupKind::Options));
}
#[test]
fn search_popup_still_accepts_printable_default_close_key_as_text() {
let mut state = state_with_messages(1);
state.focus_pane(FocusPane::Messages);
handle_key(&mut state, char_key('/'));
handle_key(&mut state, char_key('q'));
assert!(state.is_active_modal_popup(crate::tui::state::ActiveModalPopupKind::Search));
let view = state
.search_popup_view()
.expect("search popup remains open");
assert_eq!(view.fields[0].value, "q");
}
#[test]
fn options_popup_selection_aliases_move_selection() {
let mut state = state_with_messages(1);
state.open_options_popup();
handle_key(&mut state, ctrl_key('n'));
assert_eq!(state.selected_option_index(), Some(1));
handle_key(&mut state, ctrl_key('p'));
assert_eq!(state.selected_option_index(), Some(0));
handle_key(&mut state, char_key('j'));
assert_eq!(state.selected_option_index(), Some(1));
handle_key(&mut state, char_key('k'));
assert_eq!(state.selected_option_index(), Some(0));
handle_key(&mut state, key(KeyCode::Down));
assert_eq!(state.selected_option_index(), Some(1));
handle_key(&mut state, key(KeyCode::Up));
assert_eq!(state.selected_option_index(), Some(0));
handle_key(&mut state, ctrl_key('d'));
assert_eq!(state.selected_option_index(), Some(7));
handle_key(&mut state, ctrl_key('u'));
assert_eq!(state.selected_option_index(), Some(0));
}
#[test]
fn options_popup_toggles_composer_emoji_links() {
let mut state = state_with_messages(1);
handle_key(&mut state, char_key(' '));
handle_key(&mut state, char_key('o'));
handle_key(&mut state, char_key('c'));
handle_key(&mut state, key(KeyCode::Enter));
assert!(state.composer_options().emojis_as_links);
assert_eq!(
state.take_options_save_request(),
Some(AppOptions {
display: state.display_options(),
composer: state.composer_options(),
credentials: Default::default(),
notifications: state.notification_options(),
voice: state.voice_options(),
presence: Default::default(),
})
);
}
#[test]
fn voice_options_enable_push_to_talk_and_apply_shortcut_without_restart() {
let mut state = state_with_messages(1);
handle_key(&mut state, char_key(' '));
handle_key(&mut state, char_key('o'));
handle_key(&mut state, char_key('v'));
for _ in 0..5 {
handle_key(&mut state, key(KeyCode::Down));
}
handle_key(&mut state, key(KeyCode::Enter));
assert!(state.voice_options().push_to_talk);
handle_key(&mut state, key(KeyCode::Down));
handle_key(&mut state, key(KeyCode::Enter));
assert!(state.is_capturing_push_to_talk_shortcut());
assert_eq!(
state.display_option_items()[6].value.as_deref(),
Some("Press shortcut (Esc cancels)")
);
handle_key(
&mut state,
KeyEvent::new(KeyCode::F(9), KeyModifiers::CONTROL | KeyModifiers::SHIFT),
);
assert!(!state.is_capturing_push_to_talk_shortcut());
assert_eq!(
state.voice_options().push_to_talk_shortcut,
"Control+Shift+F9"
);
assert!(state.take_options_save_request().is_some());
}
#[test]
fn push_to_talk_shortcut_capture_keeps_the_previous_key_on_cancel_or_invalid_input() {
let mut state = state_with_messages(1);
handle_key(&mut state, char_key(' '));
handle_key(&mut state, char_key('o'));
handle_key(&mut state, char_key('v'));
for _ in 0..6 {
handle_key(&mut state, key(KeyCode::Down));
}
handle_key(&mut state, key(KeyCode::Enter));
handle_key(&mut state, key(KeyCode::Null));
assert!(state.is_capturing_push_to_talk_shortcut());
assert_eq!(state.voice_options().push_to_talk_shortcut, "F8");
handle_key(&mut state, key(KeyCode::Esc));
assert!(!state.is_capturing_push_to_talk_shortcut());
assert_eq!(state.voice_options().push_to_talk_shortcut, "F8");
assert!(state.is_active_modal_popup(crate::tui::state::ActiveModalPopupKind::Options));
}