use super::super::*;
use crate::test_utils::test_helpers::test_app;
use proptest::prelude::*;
#[test]
fn test_scroll_to_match_with_margin_when_below_viewport() {
let mut app = test_app(r#"{"name": "test"}"#);
app.results_scroll.viewport_height = 20;
app.results_scroll.max_offset = 100;
app.results_scroll.offset = 0;
app.search.open();
app.search.search_textarea_mut().insert_str("test");
let content = (0..120)
.map(|i| if i == 50 { "test\n" } else { "line\n" })
.collect::<String>();
app.search.update_matches(&content);
while app.search.current_match().map(|m| m.line) != Some(50) {
app.search.next_match();
}
scroll::scroll_to_match(&mut app);
assert_eq!(app.results_scroll.offset, 36);
}
#[test]
fn test_scroll_to_match_with_margin_when_above_viewport() {
let mut app = test_app(r#"{"name": "test"}"#);
app.results_scroll.viewport_height = 20;
app.results_scroll.max_offset = 100;
app.results_scroll.offset = 50;
app.search.open();
app.search.search_textarea_mut().insert_str("test");
let content = (0..120)
.map(|i| if i == 10 { "test\n" } else { "line\n" })
.collect::<String>();
app.search.update_matches(&content);
scroll::scroll_to_match(&mut app);
assert_eq!(app.results_scroll.offset, 5);
}
#[test]
fn test_scroll_to_match_no_scroll_if_visible_with_margin() {
let mut app = test_app(r#"{"name": "test"}"#);
app.results_scroll.viewport_height = 20;
app.results_scroll.max_offset = 100;
app.results_scroll.offset = 10;
app.search.open();
app.search.search_textarea_mut().insert_str("test");
let content = (0..120)
.map(|i| if i == 20 { "test\n" } else { "line\n" })
.collect::<String>();
app.search.update_matches(&content);
scroll::scroll_to_match(&mut app);
assert_eq!(app.results_scroll.offset, 10);
}
#[test]
fn test_scroll_to_match_clamps_to_max() {
let mut app = test_app(r#"{"name": "test"}"#);
app.results_scroll.viewport_height = 20;
app.results_scroll.max_offset = 50;
app.results_scroll.offset = 0;
app.search.open();
app.search.search_textarea_mut().insert_str("test");
let content = (0..120)
.map(|i| if i == 100 { "test\n" } else { "line\n" })
.collect::<String>();
app.search.update_matches(&content);
while app.search.current_match().map(|m| m.line) != Some(100) {
app.search.next_match();
}
scroll::scroll_to_match(&mut app);
assert_eq!(app.results_scroll.offset, 50);
}
#[test]
fn test_scroll_to_match_horizontal() {
let mut app = test_app(r#"{"name": "test"}"#);
app.results_scroll.viewport_height = 20;
app.results_scroll.max_offset = 100;
app.results_scroll.max_h_offset = 200;
app.results_scroll.offset = 0;
app.results_scroll.h_offset = 0;
app.search.open();
app.search.search_textarea_mut().insert_str("test");
let content = format!("{}test\n", " ".repeat(150));
app.search.update_matches(&content);
scroll::scroll_to_match(&mut app);
assert_eq!(app.results_scroll.h_offset, 140);
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop_auto_scroll_positions_match_in_viewport(
viewport_height in 5u16..50,
max_offset in 10u16..200,
initial_offset in 0u16..100,
target_line_factor in 0.0f64..1.0,
) {
let mut app = test_app(r#"{"name": "test"}"#);
app.results_scroll.viewport_height = viewport_height;
app.results_scroll.max_offset = max_offset;
app.results_scroll.offset = initial_offset.min(max_offset);
let content_height = max_offset as u32 + viewport_height as u32;
let target_line = ((target_line_factor * content_height as f64) as u32).min(content_height.saturating_sub(1));
app.search.open();
app.search.search_textarea_mut().insert_str("test");
let content: String = (0..content_height)
.map(|i| if i == target_line { "test\n" } else { "line\n" })
.collect();
app.search.update_matches(&content);
prop_assert_eq!(app.search.matches().len(), 1, "Should have exactly one match");
prop_assert_eq!(app.search.current_match().map(|m| m.line), Some(target_line), "Match should be at target line");
scroll::scroll_to_match(&mut app);
let result_offset = app.results_scroll.offset;
let visible_start = result_offset as u32;
let visible_end = visible_start + viewport_height as u32;
prop_assert!(
target_line >= visible_start && target_line < visible_end,
"Target line {} should be within visible range [{}, {}), offset={}, viewport_height={}, max_offset={}",
target_line, visible_start, visible_end, result_offset, viewport_height, max_offset
);
prop_assert!(
result_offset <= max_offset,
"Scroll offset {} should not exceed max_offset {}",
result_offset, max_offset
);
}
}