Add a unit test for editor edit events

Antonio Scandurra created

Change summary

crates/editor/src/editor.rs | 110 ++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+), 1 deletion(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -5657,7 +5657,7 @@ fn compute_scroll_position(
     scroll_position
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum Event {
     Activate,
     BufferEdited,
@@ -6140,6 +6140,114 @@ mod tests {
     use util::test::sample_text;
     use workspace::FollowableItem;
 
+    #[gpui::test]
+    fn test_edit_events(cx: &mut MutableAppContext) {
+        populate_settings(cx);
+        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
+
+        let events = Rc::new(RefCell::new(Vec::new()));
+        let (_, editor1) = cx.add_window(Default::default(), {
+            let events = events.clone();
+            |cx| {
+                cx.subscribe(&cx.handle(), move |_, _, event, _| {
+                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
+                        events.borrow_mut().push(("editor1", *event));
+                    }
+                })
+                .detach();
+                Editor::for_buffer(buffer.clone(), None, cx)
+            }
+        });
+        let (_, editor2) = cx.add_window(Default::default(), {
+            let events = events.clone();
+            |cx| {
+                cx.subscribe(&cx.handle(), move |_, _, event, _| {
+                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
+                        events.borrow_mut().push(("editor2", *event));
+                    }
+                })
+                .detach();
+                Editor::for_buffer(buffer.clone(), None, cx)
+            }
+        });
+        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
+
+        // Mutating editor 1 will emit an `Edited` event only for that editor.
+        editor1.update(cx, |editor, cx| editor.insert("X", cx));
+        assert_eq!(
+            mem::take(&mut *events.borrow_mut()),
+            [
+                ("editor1", Event::Edited),
+                ("editor1", Event::BufferEdited),
+                ("editor2", Event::BufferEdited),
+                ("editor1", Event::Dirtied),
+                ("editor2", Event::Dirtied)
+            ]
+        );
+
+        // Mutating editor 2 will emit an `Edited` event only for that editor.
+        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
+        assert_eq!(
+            mem::take(&mut *events.borrow_mut()),
+            [
+                ("editor2", Event::Edited),
+                ("editor1", Event::BufferEdited),
+                ("editor2", Event::BufferEdited),
+            ]
+        );
+
+        // Undoing on editor 1 will emit an `Edited` event only for that editor.
+        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
+        assert_eq!(
+            mem::take(&mut *events.borrow_mut()),
+            [
+                ("editor1", Event::Edited),
+                ("editor1", Event::BufferEdited),
+                ("editor2", Event::BufferEdited),
+            ]
+        );
+
+        // Redoing on editor 1 will emit an `Edited` event only for that editor.
+        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
+        assert_eq!(
+            mem::take(&mut *events.borrow_mut()),
+            [
+                ("editor1", Event::Edited),
+                ("editor1", Event::BufferEdited),
+                ("editor2", Event::BufferEdited),
+            ]
+        );
+
+        // Undoing on editor 2 will emit an `Edited` event only for that editor.
+        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
+        assert_eq!(
+            mem::take(&mut *events.borrow_mut()),
+            [
+                ("editor2", Event::Edited),
+                ("editor1", Event::BufferEdited),
+                ("editor2", Event::BufferEdited),
+            ]
+        );
+
+        // Redoing on editor 2 will emit an `Edited` event only for that editor.
+        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
+        assert_eq!(
+            mem::take(&mut *events.borrow_mut()),
+            [
+                ("editor2", Event::Edited),
+                ("editor1", Event::BufferEdited),
+                ("editor2", Event::BufferEdited),
+            ]
+        );
+
+        // No event is emitted when the mutation is a no-op.
+        editor2.update(cx, |editor, cx| {
+            editor.select_ranges([0..0], None, cx);
+            editor.backspace(&Backspace, cx);
+        });
+        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
+    }
+
     #[gpui::test]
     fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
         populate_settings(cx);