Skip to content

Commit 5023933

Browse files
committed
chore: add test cases
1 parent e909406 commit 5023933

2 files changed

Lines changed: 468 additions & 0 deletions

File tree

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
import CONST from '@src/CONST';
2+
3+
// Mock the SearchAutocompleteList continuation detection logic
4+
function mockContinuationDetection(autocompleteQueryValue: string, autocomplete: any, ranges: any[]) {
5+
let autocompleteKey = autocomplete?.key;
6+
let autocompleteValue = autocomplete?.value ?? '';
7+
8+
// If autocomplete is null but we have ranges, check if user is continuing to type after any name field
9+
if (!autocomplete && ranges.length > 0) {
10+
const lastRange = ranges.at(ranges.length - 1);
11+
// Only apply continuation logic for name fields (to, from, assignee, payer, exporter)
12+
const nameFields = [
13+
CONST.SEARCH.SYNTAX_FILTER_KEYS.TO,
14+
CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM,
15+
CONST.SEARCH.SYNTAX_FILTER_KEYS.ASSIGNEE,
16+
CONST.SEARCH.SYNTAX_FILTER_KEYS.PAYER,
17+
CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTER,
18+
] as const;
19+
20+
if (lastRange && nameFields.includes(lastRange.key as any)) {
21+
const afterLastRange = autocompleteQueryValue.substring(lastRange.start + lastRange.length);
22+
const continuationMatch = afterLastRange.match(/^\s+(\w+)/);
23+
24+
if (continuationMatch) {
25+
autocompleteKey = lastRange.key;
26+
autocompleteValue = `${lastRange.value} ${continuationMatch[1]}`;
27+
}
28+
}
29+
}
30+
31+
return { autocompleteKey, autocompleteValue };
32+
}
33+
34+
// Mock the SearchRouter field key extraction and replacement logic
35+
function mockFieldKeyReplacement(textInputValue: string, item: any) {
36+
const fieldKey = item.mapKey?.includes(':') ? item.mapKey.split(':').at(0) : null;
37+
const keyIndex = fieldKey ? textInputValue.toLowerCase().lastIndexOf(`${fieldKey}:`) : -1;
38+
39+
const trimmedUserSearchQuery = keyIndex !== -1 && fieldKey
40+
? textInputValue.substring(0, keyIndex + fieldKey.length + 1)
41+
: textInputValue; // Simplified for testing
42+
43+
return `${trimmedUserSearchQuery}${item.searchQuery}`;
44+
}
45+
46+
describe('SearchAutocompleteList - Continuation Detection Logic', () => {
47+
const continuationTests = [
48+
{
49+
description: 'Basic partial name matching - to:John Smi',
50+
autocompleteQueryValue: 'to:John Smi',
51+
autocomplete: null,
52+
ranges: [{key: 'to', value: 'John', start: 3, length: 4}],
53+
expected: {
54+
autocompleteKey: 'to',
55+
autocompleteValue: 'John Smi',
56+
},
57+
},
58+
{
59+
description: 'From field partial name - from:Jane Do',
60+
autocompleteQueryValue: 'from:Jane Do',
61+
autocomplete: null,
62+
ranges: [{key: 'from', value: 'Jane', start: 5, length: 4}],
63+
expected: {
64+
autocompleteKey: 'from',
65+
autocompleteValue: 'Jane Do',
66+
},
67+
},
68+
{
69+
description: 'Multiple word continuation - to:FirstName PartialLastName',
70+
autocompleteQueryValue: 'to:FirstName PartialLastName',
71+
autocomplete: null,
72+
ranges: [{key: 'to', value: 'FirstName', start: 3, length: 9}],
73+
expected: {
74+
autocompleteKey: 'to',
75+
autocompleteValue: 'FirstName PartialLastName',
76+
},
77+
},
78+
{
79+
description: 'Assignee field - assignee:Manager Partial',
80+
autocompleteQueryValue: 'assignee:Manager Partial',
81+
autocomplete: null,
82+
ranges: [{key: 'assignee', value: 'Manager', start: 9, length: 7}],
83+
expected: {
84+
autocompleteKey: 'assignee',
85+
autocompleteValue: 'Manager Partial',
86+
},
87+
},
88+
{
89+
description: 'Payer field - payer:Alice Wonder',
90+
autocompleteQueryValue: 'payer:Alice Wonder',
91+
autocomplete: null,
92+
ranges: [{key: 'payer', value: 'Alice', start: 6, length: 5}],
93+
expected: {
94+
autocompleteKey: 'payer',
95+
autocompleteValue: 'Alice Wonder',
96+
},
97+
},
98+
{
99+
description: 'Exporter field - exporter:Charlie Brown',
100+
autocompleteQueryValue: 'exporter:Charlie Brown',
101+
autocomplete: null,
102+
ranges: [{key: 'exporter', value: 'Charlie', start: 9, length: 7}],
103+
expected: {
104+
autocompleteKey: 'exporter',
105+
autocompleteValue: 'Charlie Brown',
106+
},
107+
},
108+
{
109+
description: 'Non-name field should not trigger continuation - category:Travel Exp',
110+
autocompleteQueryValue: 'category:Travel Exp',
111+
autocomplete: null,
112+
ranges: [{key: 'category', value: 'Travel', start: 9, length: 6}],
113+
expected: {
114+
autocompleteKey: undefined,
115+
autocompleteValue: '',
116+
},
117+
},
118+
{
119+
description: 'Tag field should not trigger continuation - tag:Office Sup',
120+
autocompleteQueryValue: 'tag:Office Sup',
121+
autocomplete: null,
122+
ranges: [{key: 'tag', value: 'Office', start: 4, length: 6}],
123+
expected: {
124+
autocompleteKey: undefined,
125+
autocompleteValue: '',
126+
},
127+
},
128+
{
129+
description: 'Complex query with name continuation - type:expense to:John Smi amount>100',
130+
autocompleteQueryValue: 'type:expense to:John Smi amount>100',
131+
autocomplete: null,
132+
ranges: [
133+
{key: 'type', value: 'expense', start: 5, length: 7},
134+
{key: 'to', value: 'John', start: 16, length: 4},
135+
],
136+
expected: {
137+
autocompleteKey: 'to',
138+
autocompleteValue: 'John Smi',
139+
},
140+
},
141+
{
142+
description: 'No continuation when autocomplete exists - to:John',
143+
autocompleteQueryValue: 'to:John',
144+
autocomplete: {key: 'to', value: 'John', start: 3, length: 4},
145+
ranges: [{key: 'to', value: 'John', start: 3, length: 4}],
146+
expected: {
147+
autocompleteKey: 'to',
148+
autocompleteValue: 'John',
149+
},
150+
},
151+
{
152+
description: 'No continuation when no ranges exist',
153+
autocompleteQueryValue: 'some free text',
154+
autocomplete: null,
155+
ranges: [],
156+
expected: {
157+
autocompleteKey: undefined,
158+
autocompleteValue: '',
159+
},
160+
},
161+
{
162+
description: 'Multiple spaces before continuation - to:John Smi',
163+
autocompleteQueryValue: 'to:John Smi',
164+
autocomplete: null,
165+
ranges: [{key: 'to', value: 'John', start: 3, length: 4}],
166+
expected: {
167+
autocompleteKey: 'to',
168+
autocompleteValue: 'John Smi',
169+
},
170+
},
171+
];
172+
173+
test.each(continuationTests)('$description', ({autocompleteQueryValue, autocomplete, ranges, expected}) => {
174+
const result = mockContinuationDetection(autocompleteQueryValue, autocomplete, ranges);
175+
expect(result).toEqual(expected);
176+
});
177+
});
178+
179+
describe('SearchRouter - Field Key Replacement Logic', () => {
180+
const replacementTests = [
181+
{
182+
description: 'Basic name field replacement - to:John Smi -> to:John Smith',
183+
textInputValue: 'to:John Smi',
184+
item: {
185+
mapKey: 'to:john_smith_id',
186+
searchQuery: 'John Smith',
187+
},
188+
expected: 'to:John Smith',
189+
},
190+
{
191+
description: 'From field replacement - from:Jane Do -> from:Jane Doe',
192+
textInputValue: 'from:Jane Do',
193+
item: {
194+
mapKey: 'from:jane_doe_id',
195+
searchQuery: 'Jane Doe',
196+
},
197+
expected: 'from:Jane Doe',
198+
},
199+
{
200+
description: 'Complex query replacement - type:expense to:FirstName Partial -> type:expense to:FirstName LastName',
201+
textInputValue: 'type:expense to:FirstName Partial',
202+
item: {
203+
mapKey: 'to:firstname_lastname_id',
204+
searchQuery: 'FirstName LastName',
205+
},
206+
expected: 'type:expense to:FirstName LastName',
207+
},
208+
{
209+
description: 'Multiple occurrences - uses last occurrence - to:John to:Jane Do -> to:John to:Jane Doe',
210+
textInputValue: 'to:John to:Jane Do',
211+
item: {
212+
mapKey: 'to:jane_doe_id',
213+
searchQuery: 'Jane Doe',
214+
},
215+
expected: 'to:John to:Jane Doe',
216+
},
217+
{
218+
description: 'No mapKey - fallback to simple replacement',
219+
textInputValue: 'to:John Smi',
220+
item: {
221+
searchQuery: 'John Smith',
222+
},
223+
expected: 'to:John SmiJohn Smith',
224+
},
225+
];
226+
227+
test.each(replacementTests)('$description', ({textInputValue, item, expected}) => {
228+
const result = mockFieldKeyReplacement(textInputValue, item);
229+
expect(result).toEqual(expected);
230+
});
231+
});

0 commit comments

Comments
 (0)