@@ -191,6 +191,65 @@ describe('Check addHighlights and clearHighlights.', function () {
191191 assert . throws ( ( ) => scribe . addHighlights ( [ { page : 0 } ] ) ) ;
192192 } ) . timeout ( 10000 ) ;
193193
194+ it ( 'addHighlights with multi-line range highlights all lines including the last' , async ( ) => {
195+ await scribe . importFiles ( [ `${ ASSETS_PATH_KARMA } /testocr.abbyy.xml` ] ) ;
196+ const lineCount = scribe . data . ocr . active [ 0 ] . lines . length ;
197+ assert . isAbove ( lineCount , 3 , 'Document should have more than 3 lines' ) ;
198+
199+ const result = scribe . addHighlights ( [ { page : 0 , startLine : 0 , endLine : lineCount - 1 } ] ) ;
200+ assert . strictEqual ( result . totalLinesHighlighted , lineCount ) ;
201+
202+ // Verify the last line specifically has all words annotated
203+ const lastLine = scribe . data . ocr . active [ 0 ] . lines [ lineCount - 1 ] ;
204+ const annots = scribe . data . annotations . pages [ 0 ] ;
205+ let lastLineAnnotCount = 0 ;
206+ for ( const word of lastLine . words ) {
207+ if ( annots . some ( ( a ) => a . bbox === word . bbox ) ) lastLineAnnotCount ++ ;
208+ }
209+ assert . strictEqual ( lastLineAnnotCount , lastLine . words . length , 'All words on the last line should be annotated' ) ;
210+ scribe . clearHighlights ( ) ;
211+ } ) . timeout ( 10000 ) ;
212+
213+ after ( async ( ) => {
214+ await scribe . terminate ( ) ;
215+ } ) ;
216+ } ) . timeout ( 120000 ) ;
217+
218+ describe ( 'Check MCP highlight flow preserves data file.' , function ( ) {
219+ this . timeout ( 30000 ) ;
220+
221+ it ( 'Multi-line highlights should work when ensureFileLoaded is called without dataFile on already-loaded document' , async ( ) => {
222+ const { ensureFileLoaded, resetState } = await import ( '../../mcp/index.js' ) ;
223+ resetState ( ) ;
224+
225+ const imgPath = `${ ASSETS_PATH_KARMA } /testocr.png` ;
226+ const dataPath = `${ ASSETS_PATH_KARMA } /testocr.abbyy.xml` ;
227+
228+ await ensureFileLoaded ( imgPath , dataPath ) ;
229+ const lineCount = scribe . data . ocr . active [ 0 ] . lines . length ;
230+ assert . strictEqual ( lineCount , 8 ) ;
231+
232+ await ensureFileLoaded ( imgPath , undefined ) ;
233+ const lineCountAfter = scribe . data . ocr . active [ 0 ] ?. lines ?. length ?? 0 ;
234+
235+ assert . strictEqual ( lineCountAfter , 8 ) ;
236+
237+ // Verify multi-line highlights work for the full range including the last line
238+ const result = scribe . addHighlights ( [ { page : 0 , startLine : 0 , endLine : lineCount - 1 } ] ) ;
239+ assert . strictEqual ( result . totalLinesHighlighted , lineCount ) ;
240+
241+ const lastLine = scribe . data . ocr . active [ 0 ] . lines [ lineCount - 1 ] ;
242+ const annots = scribe . data . annotations . pages [ 0 ] ;
243+ let lastLineAnnotCount = 0 ;
244+ for ( const word of lastLine . words ) {
245+ if ( annots . some ( ( a ) => a . bbox === word . bbox ) ) lastLineAnnotCount ++ ;
246+ }
247+ assert . strictEqual ( lastLineAnnotCount , 7 ) ;
248+
249+ scribe . clearHighlights ( ) ;
250+ resetState ( ) ;
251+ } ) . timeout ( 20000 ) ;
252+
194253 after ( async ( ) => {
195254 await scribe . terminate ( ) ;
196255 } ) ;
0 commit comments