Test prompting when saving while there's a conflict
This commit is contained in:
parent
ac2168f1bd
commit
048bbc9da0
5 changed files with 86 additions and 2 deletions
|
@ -343,6 +343,23 @@ impl TestAppContext {
|
||||||
pub fn did_prompt_for_new_path(&self) -> bool {
|
pub fn did_prompt_for_new_path(&self) -> bool {
|
||||||
self.1.as_ref().did_prompt_for_new_path()
|
self.1.as_ref().did_prompt_for_new_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn simulate_prompt_answer(&self, window_id: usize, answer: usize) {
|
||||||
|
let mut state = self.0.borrow_mut();
|
||||||
|
let (_, window) = state
|
||||||
|
.presenters_and_platform_windows
|
||||||
|
.get_mut(&window_id)
|
||||||
|
.unwrap();
|
||||||
|
let test_window = window
|
||||||
|
.as_any_mut()
|
||||||
|
.downcast_mut::<platform::test::Window>()
|
||||||
|
.unwrap();
|
||||||
|
let callback = test_window
|
||||||
|
.last_prompt
|
||||||
|
.take()
|
||||||
|
.expect("prompt was not called");
|
||||||
|
(callback)(answer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpdateModel for TestAppContext {
|
impl UpdateModel for TestAppContext {
|
||||||
|
|
|
@ -27,6 +27,7 @@ use objc::{
|
||||||
use pathfinder_geometry::vector::vec2f;
|
use pathfinder_geometry::vector::vec2f;
|
||||||
use smol::Timer;
|
use smol::Timer;
|
||||||
use std::{
|
use std::{
|
||||||
|
any::Any,
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
ffi::c_void,
|
ffi::c_void,
|
||||||
|
@ -263,6 +264,10 @@ impl Drop for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl platform::Window for Window {
|
impl platform::Window for Window {
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, callback: Box<dyn FnMut(Event)>) {
|
fn on_event(&mut self, callback: Box<dyn FnMut(Event)>) {
|
||||||
self.0.as_ref().borrow_mut().event_callback = Some(callback);
|
self.0.as_ref().borrow_mut().event_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ pub trait Dispatcher: Send + Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Window: WindowContext {
|
pub trait Window: WindowContext {
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||||
fn on_event(&mut self, callback: Box<dyn FnMut(Event)>);
|
fn on_event(&mut self, callback: Box<dyn FnMut(Event)>);
|
||||||
fn on_resize(&mut self, callback: Box<dyn FnMut(&mut dyn WindowContext)>);
|
fn on_resize(&mut self, callback: Box<dyn FnMut(&mut dyn WindowContext)>);
|
||||||
fn on_close(&mut self, callback: Box<dyn FnOnce()>);
|
fn on_close(&mut self, callback: Box<dyn FnOnce()>);
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub struct Window {
|
||||||
event_handlers: Vec<Box<dyn FnMut(super::Event)>>,
|
event_handlers: Vec<Box<dyn FnMut(super::Event)>>,
|
||||||
resize_handlers: Vec<Box<dyn FnMut(&mut dyn super::WindowContext)>>,
|
resize_handlers: Vec<Box<dyn FnMut(&mut dyn super::WindowContext)>>,
|
||||||
close_handlers: Vec<Box<dyn FnOnce()>>,
|
close_handlers: Vec<Box<dyn FnOnce()>>,
|
||||||
|
pub(crate) last_prompt: RefCell<Option<Box<dyn FnOnce(usize)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Platform {
|
impl Platform {
|
||||||
|
@ -123,6 +124,7 @@ impl Window {
|
||||||
close_handlers: Vec::new(),
|
close_handlers: Vec::new(),
|
||||||
scale_factor: 1.0,
|
scale_factor: 1.0,
|
||||||
current_scene: None,
|
current_scene: None,
|
||||||
|
last_prompt: RefCell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,6 +154,10 @@ impl super::WindowContext for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Window for Window {
|
impl super::Window for Window {
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, callback: Box<dyn FnMut(crate::Event)>) {
|
fn on_event(&mut self, callback: Box<dyn FnMut(crate::Event)>) {
|
||||||
self.event_handlers.push(callback);
|
self.event_handlers.push(callback);
|
||||||
}
|
}
|
||||||
|
@ -164,7 +170,9 @@ impl super::Window for Window {
|
||||||
self.close_handlers.push(callback);
|
self.close_handlers.push(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt(&self, _: crate::PromptLevel, _: &str, _: &[&str], _: Box<dyn FnOnce(usize)>) {}
|
fn prompt(&self, _: crate::PromptLevel, _: &str, _: &[&str], f: Box<dyn FnOnce(usize)>) {
|
||||||
|
self.last_prompt.replace(Some(f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn platform() -> Platform {
|
pub(crate) fn platform() -> Platform {
|
||||||
|
|
|
@ -761,7 +761,7 @@ mod tests {
|
||||||
use crate::{editor::BufferView, settings, test::temp_tree};
|
use crate::{editor::BufferView, settings, test::temp_tree};
|
||||||
use gpui::App;
|
use gpui::App;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::collections::HashSet;
|
use std::{collections::HashSet, fs};
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1101,6 +1101,59 @@ mod tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_save_conflicting_item() {
|
||||||
|
App::test_async((), |mut app| async move {
|
||||||
|
let dir = temp_tree(json!({
|
||||||
|
"a.txt": "",
|
||||||
|
}));
|
||||||
|
|
||||||
|
let settings = settings::channel(&app.font_cache()).unwrap().1;
|
||||||
|
let (window_id, workspace) = app.add_window(|ctx| {
|
||||||
|
let mut workspace = Workspace::new(0, settings, ctx);
|
||||||
|
workspace.add_worktree(dir.path(), ctx);
|
||||||
|
workspace
|
||||||
|
});
|
||||||
|
let tree = app.read(|ctx| {
|
||||||
|
let mut trees = workspace.read(ctx).worktrees().iter();
|
||||||
|
trees.next().unwrap().clone()
|
||||||
|
});
|
||||||
|
tree.flush_fs_events(&app).await;
|
||||||
|
|
||||||
|
// Open a file within an existing worktree.
|
||||||
|
app.update(|ctx| {
|
||||||
|
workspace.update(ctx, |view, ctx| {
|
||||||
|
view.open_paths(&[dir.path().join("a.txt")], ctx)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
let editor = app.read(|ctx| {
|
||||||
|
let pane = workspace.read(ctx).active_pane().read(ctx);
|
||||||
|
let item = pane.active_item().unwrap();
|
||||||
|
item.to_any().downcast::<BufferView>().unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
app.update(|ctx| {
|
||||||
|
editor.update(ctx, |editor, ctx| editor.insert(&"x".to_string(), ctx))
|
||||||
|
});
|
||||||
|
fs::write(dir.path().join("a.txt"), "changed").unwrap();
|
||||||
|
tree.flush_fs_events(&app).await;
|
||||||
|
app.read(|ctx| {
|
||||||
|
assert!(editor.is_dirty(ctx));
|
||||||
|
assert!(editor.has_conflict(ctx));
|
||||||
|
});
|
||||||
|
|
||||||
|
app.update(|ctx| workspace.update(ctx, |w, ctx| w.save_active_item(&(), ctx)));
|
||||||
|
app.simulate_prompt_answer(window_id, 0);
|
||||||
|
tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
|
||||||
|
.await;
|
||||||
|
app.read(|ctx| {
|
||||||
|
assert!(!editor.is_dirty(ctx));
|
||||||
|
assert!(!editor.has_conflict(ctx));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pane_actions() {
|
fn test_pane_actions() {
|
||||||
App::test_async((), |mut app| async move {
|
App::test_async((), |mut app| async move {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue