64 lines
2.0 KiB
Dart
64 lines
2.0 KiB
Dart
|
|
// Tests for search ranking + aggregation (F8).
|
||
|
|
|
||
|
|
import 'package:flutter_test/flutter_test.dart';
|
||
|
|
|
||
|
|
import 'package:badnote/editor/search/search_ranking.dart';
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
group('scoreText', () {
|
||
|
|
test('0 for empty query or no match', () {
|
||
|
|
expect(scoreText('hello world', ''), 0);
|
||
|
|
expect(scoreText('hello world', 'zzz'), 0);
|
||
|
|
expect(scoreText('', 'x'), 0);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('more occurrences score higher', () {
|
||
|
|
final one = scoreText('cat dog', 'cat');
|
||
|
|
final three = scoreText('cat cat cat', 'cat');
|
||
|
|
expect(three, greaterThan(one));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('earlier first match breaks ties (same count)', () {
|
||
|
|
final early = scoreText('needle then padding padding', 'needle');
|
||
|
|
final late = scoreText('padding padding then needle', 'needle');
|
||
|
|
expect(early, greaterThan(late));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a match at position 0 gives earliness 1 (score = count + 1)', () {
|
||
|
|
expect(scoreText('cat', 'cat'), closeTo(2.0, 1e-9)); // 1 occ + 1.0
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
group('rankHits', () {
|
||
|
|
test('drops non-matches and orders best-first', () {
|
||
|
|
final hits = rankHits({
|
||
|
|
'p1': 'one mention of fox',
|
||
|
|
'p2': 'fox fox fox everywhere', // 3 occ → highest
|
||
|
|
'p3': 'nothing relevant here',
|
||
|
|
}, 'fox');
|
||
|
|
expect(hits.map((h) => h.ref), ['p2', 'p1']);
|
||
|
|
expect(hits.first.score, greaterThan(hits.last.score));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('each hit carries a display snippet of the original text', () {
|
||
|
|
final hits = rankHits({'p1': 'The quick brown fox jumps'}, 'fox');
|
||
|
|
expect(hits, hasLength(1));
|
||
|
|
expect(hits.first.snippet.match, 'fox');
|
||
|
|
expect(hits.first.ref, 'p1');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('equal scores keep input order (explicit tiebreak)', () {
|
||
|
|
final hits = rankHits({
|
||
|
|
'a': 'match',
|
||
|
|
'b': 'match',
|
||
|
|
}, 'match');
|
||
|
|
expect(hits.map((h) => h.ref), ['a', 'b']);
|
||
|
|
expect(hits[0].score, hits[1].score);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('empty query → no hits', () {
|
||
|
|
expect(rankHits({'a': 'anything'}, ''), isEmpty);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|