// Tests for pure search-snippet extraction (F8). import 'package:flutter_test/flutter_test.dart'; import 'package:badnote/editor/search/search_snippet.dart'; void main() { test('returns null for empty query, empty source, or no match', () { expect(snippetFor('hello world', ''), isNull); expect(snippetFor('', 'x'), isNull); expect(snippetFor('hello world', 'zzz'), isNull); }); test('case-insensitive match, offset preserved within the snippet', () { final s = snippetFor('The Quick Brown Fox', 'quick', window: 80)!; expect(s.match.toLowerCase(), 'quick'); expect(s.text.substring(s.matchStart, s.matchStart + s.matchLength), 'Quick'); }); test('short source is returned whole, no truncation', () { final s = snippetFor('alpha beta gamma', 'beta', window: 80)!; expect(s.text, 'alpha beta gamma'); expect(s.truncatedStart, isFalse); expect(s.truncatedEnd, isFalse); expect(s.matchStart, 'alpha '.length); }); test('long source is windowed and truncated on both sides', () { final source = '${'a' * 200} needle ${'b' * 200}'; final s = snippetFor(source, 'needle', window: 40)!; expect(s.truncatedStart, isTrue); expect(s.truncatedEnd, isTrue); expect(s.match, 'needle'); // Window is ~40 + match; nowhere near the full 400+ source. expect(s.text.length, lessThan(80)); }); test('match near the start has no leading truncation', () { final source = 'needle ${'b' * 200}'; final s = snippetFor(source, 'needle', window: 40)!; expect(s.truncatedStart, isFalse); expect(s.matchStart, 0); expect(s.truncatedEnd, isTrue); }); test('match near the end has no trailing truncation', () { final source = '${'a' * 200} needle'; final s = snippetFor(source, 'needle', window: 40)!; expect(s.truncatedEnd, isFalse); expect(s.truncatedStart, isTrue); }); test('the full match is included even when longer than the window', () { final long = 'x' * 100; final s = snippetFor('pre $long post', long, window: 10)!; expect(s.match, long); expect(s.matchLength, 100); }); test('finds the FIRST occurrence', () { final s = snippetFor('cat dog cat', 'cat', window: 80)!; expect(s.matchStart, 0); }); }