@@ -334,7 +334,8 @@ describe('Confluence plain search ranking', () => {
334334
335335describe ( 'Jira plain search ranking' , ( ) => {
336336 const search = '/ex/jira/cloud/rest/api/3/search/jql'
337- type Issue = string | { key : string ; summary : string }
337+ /** `outsideMatch`: the issue lacks a query term, so a `text ~` all-terms clause drops it. */
338+ type Issue = string | { key : string ; summary : string ; outsideMatch ?: boolean }
338339 /**
339340 * Answers the all-terms query with `exact`, the all-terms summary query with `titled`, and the
340341 * half-the-terms summary query with `half`, or their failures.
@@ -344,7 +345,8 @@ describe('Jira plain search ranking', () => {
344345 titled : Issue [ ] | ( ( ) => never ) ,
345346 half : Issue [ ] | ( ( ) => never ) = [ ]
346347 ) {
347- const toRow = ( row : Issue ) => ( typeof row === 'string' ? { key : row , summary : row } : row )
348+ const toRow = ( row : Issue ) : Exclude < Issue , string > =>
349+ typeof row === 'string' ? { key : row , summary : row } : row
348350 const issues = ( rows : Issue [ ] ) =>
349351 rows . map ( toRow ) . map ( ( { key, summary } ) => ( { key, fields : { summary } } ) )
350352 const json = vi . fn (
@@ -354,7 +356,9 @@ describe('Jira plain search ranking', () => {
354356 const jql = options ?. body ?. jql ?? ''
355357 if ( jql . includes ( 'summary ~' ) ) {
356358 const rows = jql . includes ( ' OR ' ) ? half : titled
357- const picked = typeof rows === 'function' ? rows ( ) : rows
359+ const picked = ( typeof rows === 'function' ? rows ( ) : rows )
360+ . map ( toRow )
361+ . filter ( ( row ) => ! ( row . outsideMatch && jql . includes ( 'text ~' ) ) )
358362 return { issues : issues ( picked ) . slice ( 0 , options ?. body ?. maxResults ) }
359363 }
360364 return { issues : issues ( exact . ids ) , ...( exact . more ? { nextPageToken : 'page-2' } : { } ) }
@@ -502,4 +506,17 @@ describe('Jira plain search ranking', () => {
502506 const page = await searchAtlassian ( api , 'jira' , query )
503507 expect ( page . documents . map ( ( document ) => document . id ) ) . toEqual ( [ 'ALL-1' , 'HALF-1' , 'NEW-3' ] )
504508 } )
509+
510+ it ( 'keeps half-the-terms summaries to issues that match every term somewhere' , async ( ) => {
511+ const api = jira (
512+ overflowing ,
513+ [ ] ,
514+ [
515+ { key : 'OUTSIDE-1' , summary : 'Merged results dashboard' , outsideMatch : true } ,
516+ { key : 'INSIDE-1' , summary : 'Merged results broke the dashboard' } ,
517+ ]
518+ )
519+ const page = await searchAtlassian ( api , 'jira' , query )
520+ expect ( page . documents . map ( ( document ) => document . id ) ) . toEqual ( [ 'INSIDE-1' , 'NEW-3' , 'NEW-2' ] )
521+ } )
505522} )
0 commit comments