@@ -4,8 +4,11 @@ import ImageAnnotator, { CSS_IS_DRAWING_CLASS } from '../ImageAnnotator';
44import PopupManager from '../../popup/PopupManager' ;
55import RegionCreationManager from '../../region/RegionCreationManager' ;
66import RegionManager from '../../region/RegionManager' ;
7+ import { BoundingBoxHighlightManager } from '../../boundingBoxHighlight' ;
78import { Annotation } from '../../@types' ;
89import { CreatorStatus , fetchAnnotationsAction , setStatusAction } from '../../store' ;
10+ import { setViewModeAction } from '../../store/options' ;
11+ import { setBoundingBoxHighlightsAction } from '../../store/boundingBoxHighlights' ;
912import { annotations as drawings } from '../../drawing/__mocks__/drawingData' ;
1013import { annotations as regions } from '../../region/__mocks__/data' ;
1114import { scrollToLocation } from '../../utils/scroll' ;
@@ -14,6 +17,7 @@ jest.mock('../../common/DeselectManager');
1417jest . mock ( '../../popup/PopupManager' ) ;
1518jest . mock ( '../../region/RegionCreationManager' ) ;
1619jest . mock ( '../../region/RegionManager' ) ;
20+ jest . mock ( '../../boundingBoxHighlight' ) ;
1721jest . mock ( '../../utils/scroll' ) ;
1822
1923describe ( 'ImageAnnotator' , ( ) => {
@@ -123,6 +127,16 @@ describe('ImageAnnotator', () => {
123127 expect ( mockManager . destroy ) . not . toHaveBeenCalled ( ) ;
124128 expect ( managers . values ( ) . next ( ) . value ) . toEqual ( mockManager ) ;
125129 } ) ;
130+
131+ test ( 'should create only BoundingBoxHighlightManager when viewMode is boundingBoxes' , ( ) => {
132+ annotator . store . dispatch ( setViewModeAction ( 'boundingBoxes' ) ) ;
133+
134+ const managers = annotator . getManagers ( getParent ( ) , getImage ( ) ) ;
135+ const managerArray = Array . from ( managers ) ;
136+
137+ expect ( managerArray ) . toHaveLength ( 1 ) ;
138+ expect ( managerArray [ 0 ] ) . toBeInstanceOf ( BoundingBoxHighlightManager ) ;
139+ } ) ;
126140 } ) ;
127141
128142 describe ( 'getReference()' , ( ) => {
@@ -227,6 +241,97 @@ describe('ImageAnnotator', () => {
227241 expect ( annotator . deselectManager ) . toBeInstanceOf ( DeselectManager ) ;
228242 expect ( annotator . deselectManager ! . render ) . toHaveBeenCalled ( ) ;
229243 } ) ;
244+
245+ test ( 'should not instantiate DeselectManager when in bounding box mode' , ( ) => {
246+ annotator . annotatedEl = getParent ( ) ;
247+ annotator . store . dispatch ( setViewModeAction ( 'boundingBoxes' ) ) ;
248+
249+ annotator . render ( ) ;
250+
251+ expect ( annotator . deselectManager ) . toBeNull ( ) ;
252+ } ) ;
253+
254+ test ( 'should destroy existing DeselectManager when switching to bounding box mode' , ( ) => {
255+ annotator . annotatedEl = getParent ( ) ;
256+
257+ annotator . render ( ) ;
258+ expect ( annotator . deselectManager ) . toBeInstanceOf ( DeselectManager ) ;
259+
260+ const destroySpy = annotator . deselectManager ! . destroy as jest . Mock ;
261+
262+ annotator . store . dispatch ( setViewModeAction ( 'boundingBoxes' ) ) ;
263+ annotator . render ( ) ;
264+
265+ expect ( destroySpy ) . toHaveBeenCalled ( ) ;
266+ expect ( annotator . deselectManager ) . toBeNull ( ) ;
267+ } ) ;
268+
269+ test ( 'should clear all managers when view mode changes' , ( ) => {
270+ annotator . annotatedEl = getParent ( ) ;
271+
272+ const destroySpy = jest . fn ( ) ;
273+ const existingSpy = jest . fn ( ) . mockReturnValue ( true ) ;
274+ const mgr = { destroy : destroySpy , exists : existingSpy , render : jest . fn ( ) , style : jest . fn ( ) } ;
275+ annotator . managers = new Set ( [ mgr ] ) ;
276+
277+ // First render keeps managers because exists() returns true
278+ annotator . render ( ) ;
279+
280+ expect ( annotator . managers . size ) . toBe ( 1 ) ;
281+
282+ annotator . store . dispatch ( setViewModeAction ( 'boundingBoxes' ) ) ;
283+ annotator . render ( ) ;
284+
285+ expect ( destroySpy ) . toHaveBeenCalled ( ) ;
286+ } ) ;
287+ } ) ;
288+
289+ describe ( 'scrollToBoundingBoxHighlight()' , ( ) => {
290+ const boundingBoxes = [
291+ { id : 'box-1' , x : 10 , y : 20 , width : 30 , height : 40 , pageNumber : 1 } ,
292+ { id : 'box-2' , x : 50 , y : 60 , width : 70 , height : 80 , pageNumber : 1 } ,
293+ ] ;
294+
295+ beforeEach ( ( ) => {
296+ annotator . annotatedEl = getParent ( ) ;
297+ annotator . store . dispatch ( setBoundingBoxHighlightsAction ( boundingBoxes ) ) ;
298+ } ) ;
299+
300+ test ( 'should call scrollToLocation with center offsets and smooth scrolling' , ( ) => {
301+ jest . spyOn ( annotator , 'getReference' ) . mockImplementation ( getImage ) ;
302+
303+ annotator . scrollToBoundingBoxHighlight ( 'box-1' ) ;
304+
305+ expect ( scrollToLocation ) . toHaveBeenCalledWith ( getParent ( ) , getImage ( ) , {
306+ offsets : { x : 25 , y : 40 } ,
307+ smooth : true ,
308+ } ) ;
309+ } ) ;
310+
311+ test ( 'should do nothing if highlightId is null' , ( ) => {
312+ annotator . scrollToBoundingBoxHighlight ( null ) ;
313+ expect ( scrollToLocation ) . not . toHaveBeenCalled ( ) ;
314+ } ) ;
315+
316+ test ( 'should do nothing if annotatedEl is not defined' , ( ) => {
317+ annotator . annotatedEl = undefined ;
318+ annotator . scrollToBoundingBoxHighlight ( 'box-1' ) ;
319+ expect ( scrollToLocation ) . not . toHaveBeenCalled ( ) ;
320+ } ) ;
321+
322+ test ( 'should do nothing if highlight is not found in the store' , ( ) => {
323+ jest . spyOn ( annotator , 'getReference' ) . mockImplementation ( getImage ) ;
324+
325+ annotator . scrollToBoundingBoxHighlight ( 'nonexistent' ) ;
326+ expect ( scrollToLocation ) . not . toHaveBeenCalled ( ) ;
327+ } ) ;
328+
329+ test ( 'should do nothing if reference element is not defined' , ( ) => {
330+ jest . spyOn ( annotator , 'getReference' ) . mockReturnValue ( undefined ) ;
331+
332+ annotator . scrollToBoundingBoxHighlight ( 'box-1' ) ;
333+ expect ( scrollToLocation ) . not . toHaveBeenCalled ( ) ;
334+ } ) ;
230335 } ) ;
231336
232337 describe ( 'scrollToAnnotation()' , ( ) => {
0 commit comments