@@ -249,10 +249,239 @@ const tests = [
249249 } ,
250250] ;
251251
252+ const nameFieldContinuationTests = [
253+ {
254+ query : 'to:John Smi' ,
255+ expected : {
256+ autocomplete : null ,
257+ ranges : [ { key : 'to' , value : 'John' , start : 3 , length : 4 } ] ,
258+ } ,
259+ description : 'Basic partial name - parser should return null autocomplete for continuation text' ,
260+ } ,
261+ {
262+ query : 'from:Jane Do' ,
263+ expected : {
264+ autocomplete : null ,
265+ ranges : [ { key : 'from' , value : 'Jane' , start : 5 , length : 4 } ] ,
266+ } ,
267+ description : 'From field partial name - parser should return null autocomplete for continuation text' ,
268+ } ,
269+ {
270+ query : 'assignee:Bob Mar' ,
271+ expected : {
272+ autocomplete : null ,
273+ ranges : [ { key : 'assignee' , value : 'Bob' , start : 9 , length : 3 } ] ,
274+ } ,
275+ description : 'Assignee field partial name - parser should return null autocomplete for continuation text' ,
276+ } ,
277+ {
278+ query : 'payer:Alice Wind' ,
279+ expected : {
280+ autocomplete : null ,
281+ ranges : [ { key : 'payer' , value : 'Alice' , start : 6 , length : 5 } ] ,
282+ } ,
283+ description : 'Payer field partial name - parser should return null autocomplete for continuation text' ,
284+ } ,
285+ {
286+ query : 'exporter:Charlie Bro' ,
287+ expected : {
288+ autocomplete : null ,
289+ ranges : [ { key : 'exporter' , value : 'Charlie' , start : 9 , length : 7 } ] ,
290+ } ,
291+ description : 'Exporter field partial name - parser should return null autocomplete for continuation text' ,
292+ } ,
293+ {
294+ query : 'to:John Smith Doe' ,
295+ expected : {
296+ autocomplete : null ,
297+ ranges : [ { key : 'to' , value : 'John' , start : 3 , length : 4 } ] ,
298+ } ,
299+ description : 'Multiple word continuation - parser should only parse first token, rest is free text' ,
300+ } ,
301+ {
302+ query : 'from:Mary Jane Wat' ,
303+ expected : {
304+ autocomplete : null ,
305+ ranges : [ { key : 'from' , value : 'Mary' , start : 5 , length : 4 } ] ,
306+ } ,
307+ description : 'Multiple word continuation with partial last name - parser should only parse first token' ,
308+ } ,
309+ {
310+ query : 'to:John Smi' ,
311+ expected : {
312+ autocomplete : null ,
313+ ranges : [ { key : 'to' , value : 'John' , start : 3 , length : 4 } ] ,
314+ } ,
315+ description : 'Multiple spaces before continuation text' ,
316+ } ,
317+ {
318+ query : 'to:John\tSmi' ,
319+ expected : {
320+ autocomplete : null ,
321+ ranges : [ { key : 'to' , value : 'John' , start : 3 , length : 4 } ] ,
322+ } ,
323+ description : 'Tab character before continuation text' ,
324+ } ,
325+ {
326+ query : 'category:Travel Exp' ,
327+ expected : {
328+ autocomplete : null ,
329+ ranges : [ { key : 'category' , value : 'Travel' , start : 9 , length : 6 } ] ,
330+ } ,
331+ description : 'Non-name field with space - parser treats space as separator, continuation logic applies in UI' ,
332+ } ,
333+ {
334+ query : 'tag:Office Sup' ,
335+ expected : {
336+ autocomplete : null ,
337+ ranges : [ { key : 'tag' , value : 'Office' , start : 4 , length : 6 } ] ,
338+ } ,
339+ description : 'Tag field with space - parser treats space as separator, continuation logic applies in UI' ,
340+ } ,
341+ {
342+ query : 'type:expense to:John Smi amount>100' ,
343+ expected : {
344+ autocomplete : null ,
345+ ranges : [
346+ { key : 'type' , value : 'expense' , start : 5 , length : 7 } ,
347+ { key : 'to' , value : 'John' , start : 16 , length : 4 } ,
348+ ] ,
349+ } ,
350+ description : 'Complex query with name field continuation should return null autocomplete' ,
351+ } ,
352+ {
353+ query : 'from:Jane Do category:Travel' ,
354+ expected : {
355+ autocomplete : {
356+ key : 'category' ,
357+ value : 'Travel' ,
358+ start : 22 ,
359+ length : 6 ,
360+ } ,
361+ ranges : [
362+ { key : 'from' , value : 'Jane' , start : 5 , length : 4 } ,
363+ { key : 'category' , value : 'Travel' , start : 22 , length : 6 } ,
364+ ] ,
365+ } ,
366+ description : 'Mixed query with name continuation and other field should autocomplete the other field' ,
367+ } ,
368+ {
369+ query : 'to:John' ,
370+ expected : {
371+ autocomplete : {
372+ key : 'to' ,
373+ value : 'John' ,
374+ start : 3 ,
375+ length : 4 ,
376+ } ,
377+ ranges : [ { key : 'to' , value : 'John' , start : 3 , length : 4 } ] ,
378+ } ,
379+ description : 'Complete single name should still provide autocomplete' ,
380+ } ,
381+ {
382+ query : 'to:"John Smith"' ,
383+ expected : {
384+ autocomplete : {
385+ key : 'to' ,
386+ value : 'John Smith' ,
387+ start : 3 ,
388+ length : 12 ,
389+ } ,
390+ ranges : [ { key : 'to' , value : 'John Smith' , start : 3 , length : 12 } ] ,
391+ } ,
392+ description : 'Quoted complete name should provide autocomplete' ,
393+ } ,
394+ {
395+ query : "to:John O'Con" ,
396+ expected : {
397+ autocomplete : null ,
398+ ranges : [ { key : 'to' , value : 'John' , start : 3 , length : 4 } ] ,
399+ } ,
400+ description : 'Name continuation with apostrophe should return null autocomplete' ,
401+ } ,
402+ {
403+ query : 'to:John-Paul Smi' ,
404+ expected : {
405+ autocomplete : null ,
406+ ranges : [ { key : 'to' , value : 'John-Paul' , start : 3 , length : 9 } ] ,
407+ } ,
408+ description : 'Hyphenated first name with continuation should return null autocomplete' ,
409+ } ,
410+ {
411+ query : 'to:John Smi' ,
412+ expected : {
413+ autocomplete : null ,
414+ ranges : [ { key : 'to' , value : 'John' , start : 3 , length : 4 } ] ,
415+ } ,
416+ description : 'Original issue scenario - to:John Smi should return null autocomplete for continuation detection' ,
417+ } ,
418+ {
419+ query : 'to:FirstName PartialLastName' ,
420+ expected : {
421+ autocomplete : null ,
422+ ranges : [ { key : 'to' , value : 'FirstName' , start : 3 , length : 9 } ] ,
423+ } ,
424+ description : 'Test case scenario - to:FirstName PartialLastName should return null autocomplete' ,
425+ } ,
426+ {
427+ query : 'from:Alice Bob' ,
428+ expected : {
429+ autocomplete : null ,
430+ ranges : [ { key : 'from' , value : 'Alice' , start : 5 , length : 5 } ] ,
431+ } ,
432+ description : 'From field with two names should return null autocomplete for continuation' ,
433+ } ,
434+ {
435+ query : 'assignee:Manager Partial' ,
436+ expected : {
437+ autocomplete : null ,
438+ ranges : [ { key : 'assignee' , value : 'Manager' , start : 9 , length : 7 } ] ,
439+ } ,
440+ description : 'Assignee field with partial second name should return null autocomplete' ,
441+ } ,
442+ {
443+ query : 'to:John,Jane' ,
444+ expected : {
445+ autocomplete : {
446+ key : 'to' ,
447+ value : 'Jane' ,
448+ start : 8 ,
449+ length : 4 ,
450+ } ,
451+ ranges : [
452+ { key : 'to' , value : 'John' , start : 3 , length : 4 } ,
453+ { key : 'to' , value : 'Jane' , start : 8 , length : 4 } ,
454+ ] ,
455+ } ,
456+ description : 'Comma-separated names should provide autocomplete for last value' ,
457+ } ,
458+ {
459+ query : 'to:"John Smith"' ,
460+ expected : {
461+ autocomplete : {
462+ key : 'to' ,
463+ value : 'John Smith' ,
464+ start : 3 ,
465+ length : 12 ,
466+ } ,
467+ ranges : [ { key : 'to' , value : 'John Smith' , start : 3 , length : 12 } ] ,
468+ } ,
469+ description : 'Quoted full name should provide autocomplete normally' ,
470+ } ,
471+ ] ;
472+
252473describe ( 'autocomplete parser' , ( ) => {
253474 test . each ( tests ) ( `parsing: $query` , ( { query, expected} ) => {
254475 const result = parse ( query ) as SearchQueryJSON ;
255476
256477 expect ( result ) . toEqual ( expected ) ;
257478 } ) ;
258479} ) ;
480+
481+ describe ( 'autocomplete parser - name field continuation detection' , ( ) => {
482+ test . each ( nameFieldContinuationTests ) ( `$description: $query` , ( { query, expected} ) => {
483+ const result = parse ( query ) as SearchQueryJSON ;
484+
485+ expect ( result ) . toEqual ( expected ) ;
486+ } ) ;
487+ } ) ;
0 commit comments