diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index 575e9499d3..1b05993bd5 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -54,10 +54,151 @@ impl SettingsFile { #[cfg(test)] mod tests { use super::*; - use crate::{watched_json::watch_settings_file, EditorSettings, Settings, SoftWrap}; + use crate::{ + watch_files, watched_json::watch_settings_file, EditorSettings, Settings, SoftWrap, + }; use fs::FakeFs; + use gpui::{actions, Action}; use theme::ThemeRegistry; + #[gpui::test] + async fn test_base_keymap(cx: &mut gpui::TestAppContext) { + let executor = cx.background(); + let fs = FakeFs::new(executor.clone()); + let font_cache = cx.font_cache(); + + actions!(test, [A, B]); + // From the Atom keymap + actions!(workspace, [ActivatePreviousPane]); + // From the JetBrains keymap + actions!(pane, [ActivatePrevItem]); + + fs.save( + "/settings.json".as_ref(), + &r#" + { + "base_keymap": "Atom" + } + "# + .into(), + Default::default(), + ) + .await + .unwrap(); + + fs.save( + "/keymap.json".as_ref(), + &r#" + [ + { + "bindings": { + "backspace": "test::A" + } + } + ] + "# + .into(), + Default::default(), + ) + .await + .unwrap(); + + let settings_file = + WatchedJsonFile::new(fs.clone(), &executor, "/settings.json".as_ref()).await; + let keymaps_file = + WatchedJsonFile::new(fs.clone(), &executor, "/keymap.json".as_ref()).await; + + let default_settings = cx.read(Settings::test); + + cx.update(|cx| { + cx.add_global_action(|_: &A, _cx| { + }); + cx.add_global_action(|_: &B, _cx| { + }); + cx.add_global_action(|_: &ActivatePreviousPane, _cx| { + }); + cx.add_global_action(|_: &ActivatePrevItem, _cx| { + }); + watch_files( + default_settings, + settings_file, + ThemeRegistry::new((), font_cache), + keymaps_file, + cx, + ) + }); + + cx.foreground().run_until_parked(); + + // Test loading the keymap base at all + cx.update(|cx| { + assert_keybindings_for(cx, vec![("backspace", &A), ("k", &ActivatePreviousPane)], line!()); + }); + + // Test modifying the users keymap, while retaining the base keymap + fs.save( + "/keymap.json".as_ref(), + &r#" + [ + { + "bindings": { + "backspace": "test::B" + } + } + ] + "# + .into(), + Default::default(), + ) + .await + .unwrap(); + + cx.foreground().run_until_parked(); + + cx.update(|cx| { + assert_keybindings_for(cx, vec![("backspace", &B), ("k", &ActivatePreviousPane)], line!()); + }); + + // Test modifying the base, while retaining the users keymap + fs.save( + "/settings.json".as_ref(), + &r#" + { + "base_keymap": "JetBrains" + } + "# + .into(), + Default::default(), + ) + .await + .unwrap(); + + cx.foreground().run_until_parked(); + + cx.update(|cx| { + assert_keybindings_for(cx, vec![("backspace", &B), ("[", &ActivatePrevItem)], line!()); + }); + } + + fn assert_keybindings_for<'a>( + cx: &mut MutableAppContext, + actions: Vec<(&'static str, &'a dyn Action)>, + line: u32, + ) { + + for (key, action) in actions { + // assert that... + assert!(cx.available_actions(0, 0).any(|(_, bound_action, b)| { + // action names match... + bound_action.name() == action.name() + && bound_action.namespace() == action.namespace() + // and key strokes contain the given key + && b.iter() + .any(|binding| binding.keystrokes().iter().any(|k| k.key == key)) + }), "On {} Failed to find {} with keybinding {}", line, action.name(), key); + } + } + #[gpui::test] async fn test_watch_settings_files(cx: &mut gpui::TestAppContext) { let executor = cx.background();