Files
galaxy/crates/editor/src/search_tests.rs
T

247 lines
7.8 KiB
Rust

use galaxyui_core::{App, ModelHandle};
use super::Searcher;
use crate::content::buffer::{
AutoScrollBehavior, Buffer, BufferEditAction, BufferSelectAction, EditOrigin,
};
use crate::content::find::{Match, SearchResults};
use crate::content::selection_model::BufferSelectionModel;
use crate::content::text::IndentBehavior;
#[test]
fn test_literal_search() {
App::test((), |mut app| async move {
let (content, selection) = buffer(&mut app, "abc def abc def");
let search = searcher(&mut app, content, selection);
search
.update(&mut app, |search, ctx| {
search.set_query("abc", ctx);
search.search_finished(ctx)
})
.await;
search.read(&app, |search, _| {
assert_eq!(search.match_count(), 2);
assert_eq!(
search.results,
Some(SearchResults {
matches: vec![
Match {
start: 1.into(),
end: 4.into()
},
Match {
start: 9.into(),
end: 12.into()
}
]
})
)
})
});
}
#[test]
fn test_navigate_search_results() {
App::test((), |mut app| async move {
let (content, selection) = buffer(&mut app, "abc def abc def");
let search = searcher(&mut app, content, selection);
search
.update(&mut app, |search, ctx| {
search.set_auto_select(true);
search.set_query("abc", ctx);
search.search_finished(ctx)
})
.await;
search.update(&mut app, |search, ctx| {
assert_eq!(search.match_count(), 2);
// With auto-selection, the first match should be selected (cursor is at start)
assert_eq!(search.selected_match(), Some(0));
// Move to the next result.
search.select_next_result(ctx);
assert_eq!(search.selected_match(), Some(1));
// Keep moving until we wrap around.
search.select_next_result(ctx);
assert_eq!(search.selected_match(), Some(0));
// Now do the same in the other direction.
search.select_previous_result(ctx);
assert_eq!(search.selected_match(), Some(1));
search.select_previous_result(ctx);
assert_eq!(search.selected_match(), Some(0));
// Starting from no selection, select the last result.
search.selected_result = None;
search.select_previous_result(ctx);
assert_eq!(search.selected_match(), Some(1));
})
});
}
#[test]
fn test_edit_results_valid() {
App::test((), |mut app| async move {
let (content, content_selection) = buffer(&mut app, "a git command");
let search = searcher(&mut app, content.clone(), content_selection.clone());
search
.update(&mut app, |search, ctx| {
search.set_auto_select(true);
search.set_regex(true, ctx);
search.set_query(r"g\w+t", ctx);
search.search_finished(ctx)
})
.await;
search.update(&mut app, |search, ctx| {
search.select_next_result(ctx);
assert_eq!(search.selected_match(), Some(0));
});
// Insert some text before the match.
content.update(&mut app, |buffer, ctx| {
buffer.update_selection(
content_selection.clone(),
BufferSelectAction::AddCursorAt {
offset: 2.into(),
clear_selections: true,
},
AutoScrollBehavior::Selection,
ctx,
);
buffer.update_content(
BufferEditAction::Insert {
text: "sdf",
style: Default::default(),
override_text_style: None,
},
EditOrigin::UserTyped,
content_selection.clone(),
ctx,
);
assert_eq!(buffer.debug(), "<text>asdf git command");
});
search
.update(&mut app, |search, ctx| search.search_finished(ctx))
.await;
// When the search finishes, we should have the same result.
assert_eq!(
search.read(&app, |search, _| search.selected_match()),
Some(0)
);
// Insert a new match before the selected one, which should move it back.
content.update(&mut app, |buffer, ctx| {
buffer.update_content(
BufferEditAction::Insert {
text: "got",
style: Default::default(),
override_text_style: None,
},
EditOrigin::UserTyped,
content_selection.clone(),
ctx,
);
assert_eq!(buffer.debug(), "<text>asdfgot git command");
});
search
.update(&mut app, |search, ctx| search.search_finished(ctx))
.await;
assert_eq!(
search.read(&app, |search, _| search.selected_match()),
Some(1)
);
})
}
#[test]
fn test_edit_results_invalid() {
App::test((), |mut app| async move {
let (content, content_selection) = buffer(&mut app, "a git command for git");
let search = searcher(&mut app, content.clone(), content_selection.clone());
search
.update(&mut app, |search, ctx| {
search.set_auto_select(true);
search.set_regex(true, ctx);
search.set_query(r"g\w+t", ctx);
search.search_finished(ctx)
})
.await;
search.update(&mut app, |search, ctx| {
// Move to the second match
search.select_next_result(ctx);
assert_eq!(search.selected_match(), Some(1));
});
// Invalidate the match
content.update(&mut app, |buffer, ctx| {
buffer.update_selection(
content_selection.clone(),
BufferSelectAction::AddCursorAt {
offset: 6.into(),
clear_selections: true,
},
AutoScrollBehavior::Selection,
ctx,
);
buffer.update_content(
BufferEditAction::Backspace,
EditOrigin::UserTyped,
content_selection.clone(),
ctx,
);
assert_eq!(buffer.debug(), "<text>a gi command for git");
});
search
.update(&mut app, |search, ctx| search.search_finished(ctx))
.await;
// When the search finishes, auto-selection should pick the remaining match.
search.read(&app, |search, _| {
assert_eq!(search.selected_match(), Some(0));
assert_eq!(search.match_count(), 1);
});
})
}
/// Create a new buffer model with the given Markdown.
fn buffer(
app: &mut App,
markdown: &str,
) -> (ModelHandle<Buffer>, ModelHandle<BufferSelectionModel>) {
let buffer = app.add_model(|_| Buffer::new(Box::new(|_, _| IndentBehavior::Ignore)));
let selection = app.add_model(|_| BufferSelectionModel::new(buffer.clone()));
buffer.update(app, |buffer, ctx| {
*buffer = Buffer::from_markdown(
markdown,
None,
Box::new(|_, _| IndentBehavior::Ignore),
selection.clone(),
ctx,
);
});
(buffer, selection)
}
fn searcher(
app: &mut App,
buffer: ModelHandle<Buffer>,
selection: ModelHandle<BufferSelectionModel>,
) -> ModelHandle<Searcher> {
app.add_model(|ctx| Searcher::new(buffer, selection, ctx))
}