@@ -13,7 +13,7 @@ import {
1313} from './message-component-manager' ;
1414import { log } from '../utilities/log' ;
1515import { resolveMessageProperties } from './gist-properties-manager' ;
16- import { positionTooltip } from './tooltip-position-manager' ;
16+ import { positionTooltip , ensureTargetInView } from './tooltip-position-manager' ;
1717import type { GistMessage } from '../types' ;
1818
1919vi . mock ( '../utilities/log' , ( ) => ( { log : vi . fn ( ) } ) ) ;
@@ -65,6 +65,7 @@ vi.mock('../utilities/message-utils', () => ({
6565} ) ) ;
6666vi . mock ( './tooltip-position-manager' , ( ) => ( {
6767 positionTooltip : vi . fn ( ) ,
68+ ensureTargetInView : vi . fn ( ( ) => Promise . resolve ( true ) ) ,
6869} ) ) ;
6970
7071describe ( 'message-component-manager' , ( ) => {
@@ -192,7 +193,7 @@ describe('message-component-manager', () => {
192193 expect ( iframe ?. onload ) . toBeTypeOf ( 'function' ) ;
193194 } ) ;
194195
195- it ( 'cleans up existing position listeners before re-creating the tooltip' , ( ) => {
196+ it ( 'cleans up existing position listeners before re-creating the tooltip' , async ( ) => {
196197 const mockCleanup = vi . fn ( ) ;
197198 vi . mocked ( positionTooltip ) . mockReturnValue ( { cleanup : mockCleanup , reposition : vi . fn ( ) } ) ;
198199
@@ -222,7 +223,7 @@ describe('message-component-manager', () => {
222223 } ;
223224
224225 loadTooltipComponent ( 'https://view.example.com/index.html' , message , baseOptions ) ;
225- showTooltipComponent ( message ) ;
226+ await showTooltipComponent ( message ) ;
226227
227228 expect ( mockCleanup ) . not . toHaveBeenCalled ( ) ;
228229
@@ -249,7 +250,7 @@ describe('message-component-manager', () => {
249250 return wrapper ;
250251 }
251252
252- it ( 'adds gist-visible class to the tooltip container and returns true when positioned' , ( ) => {
253+ it ( 'adds gist-visible class to the tooltip container and returns true when positioned' , async ( ) => {
253254 vi . mocked ( positionTooltip ) . mockReturnValue ( { cleanup : vi . fn ( ) , reposition : vi . fn ( ) } ) ;
254255 setupTooltipWrapper ( 'inst-1' ) ;
255256 const message : GistMessage = {
@@ -258,14 +259,14 @@ describe('message-component-manager', () => {
258259 properties : { gist : { elementId : '#target-el' } } ,
259260 } ;
260261
261- const result = showTooltipComponent ( message ) ;
262+ const result = await showTooltipComponent ( message ) ;
262263
263264 expect ( result ) . toBe ( true ) ;
264265 const container = document . querySelector ( '.gist-tooltip-container' ) ;
265266 expect ( container ?. classList . contains ( 'gist-visible' ) ) . toBe ( true ) ;
266267 } ) ;
267268
268- it ( 'calls positionTooltip with the wrapper, selector, and position' , ( ) => {
269+ it ( 'calls positionTooltip with the wrapper, selector, and position' , async ( ) => {
269270 setupTooltipWrapper ( 'inst-1' ) ;
270271 vi . mocked ( resolveMessageProperties ) . mockReturnValue ( {
271272 isEmbedded : false ,
@@ -292,13 +293,13 @@ describe('message-component-manager', () => {
292293 properties : { gist : { elementId : '#target-el' , tooltipPosition : 'top' } } ,
293294 } ;
294295
295- showTooltipComponent ( message ) ;
296+ await showTooltipComponent ( message ) ;
296297
297298 const tooltipElement = document . querySelector ( '.gist-tooltip-outer' ) ;
298299 expect ( positionTooltip ) . toHaveBeenCalledWith ( tooltipElement , '#target-el' , 'top' ) ;
299300 } ) ;
300301
301- it ( 'defaults tooltip position to bottom when not specified' , ( ) => {
302+ it ( 'defaults tooltip position to bottom when not specified' , async ( ) => {
302303 setupTooltipWrapper ( 'inst-1' ) ;
303304 vi . mocked ( resolveMessageProperties ) . mockReturnValue ( {
304305 isEmbedded : false ,
@@ -325,12 +326,12 @@ describe('message-component-manager', () => {
325326 properties : { gist : { elementId : '#target-el' } } ,
326327 } ;
327328
328- showTooltipComponent ( message ) ;
329+ await showTooltipComponent ( message ) ;
329330
330331 expect ( positionTooltip ) . toHaveBeenCalledWith ( expect . any ( HTMLElement ) , '#target-el' , 'bottom' ) ;
331332 } ) ;
332333
333- it ( 'returns false when positionTooltip returns null (target not found)' , ( ) => {
334+ it ( 'returns false when positionTooltip returns null (target not found)' , async ( ) => {
334335 setupTooltipWrapper ( 'inst-1' ) ;
335336 vi . mocked ( positionTooltip ) . mockReturnValue ( null ) ;
336337
@@ -340,14 +341,14 @@ describe('message-component-manager', () => {
340341 properties : { gist : { elementId : '#target-el' } } ,
341342 } ;
342343
343- const result = showTooltipComponent ( message ) ;
344+ const result = await showTooltipComponent ( message ) ;
344345
345346 expect ( result ) . toBe ( false ) ;
346347 const container = document . querySelector ( '.gist-tooltip-container' ) ;
347348 expect ( container ?. classList . contains ( 'gist-visible' ) ) . toBe ( false ) ;
348349 } ) ;
349350
350- it ( 'returns false and cleans up when tooltip container element is missing' , ( ) => {
351+ it ( 'returns false and cleans up when tooltip container element is missing' , async ( ) => {
351352 const mockCleanup = vi . fn ( ) ;
352353 vi . mocked ( positionTooltip ) . mockReturnValue ( { cleanup : mockCleanup , reposition : vi . fn ( ) } ) ;
353354
@@ -364,14 +365,14 @@ describe('message-component-manager', () => {
364365 properties : { gist : { elementId : '#target-el' } } ,
365366 } ;
366367
367- const result = showTooltipComponent ( message ) ;
368+ const result = await showTooltipComponent ( message ) ;
368369
369370 expect ( result ) . toBe ( false ) ;
370371 expect ( mockCleanup ) . toHaveBeenCalled ( ) ;
371372 expect ( log ) . toHaveBeenCalledWith ( 'Tooltip container not found for instance inst-1' ) ;
372373 } ) ;
373374
374- it ( 'returns false and cleans up when tooltip is hidden via display:none (no viewport fit)' , ( ) => {
375+ it ( 'returns false and cleans up when tooltip is hidden via display:none (no viewport fit)' , async ( ) => {
375376 setupTooltipWrapper ( 'inst-1' ) ;
376377 const mockCleanup = vi . fn ( ) ;
377378
@@ -386,36 +387,36 @@ describe('message-component-manager', () => {
386387 properties : { gist : { elementId : '#target-el' } } ,
387388 } ;
388389
389- const result = showTooltipComponent ( message ) ;
390+ const result = await showTooltipComponent ( message ) ;
390391
391392 expect ( result ) . toBe ( false ) ;
392393 expect ( mockCleanup ) . toHaveBeenCalled ( ) ;
393394 const container = document . querySelector ( '.gist-tooltip-container' ) ;
394395 expect ( container ?. classList . contains ( 'gist-visible' ) ) . toBe ( false ) ;
395396 } ) ;
396397
397- it ( 'logs and returns false when wrapper is not found' , ( ) => {
398+ it ( 'logs and returns false when wrapper is not found' , async ( ) => {
398399 const message : GistMessage = {
399400 messageId : 'msg-1' ,
400401 instanceId : 'inst-1' ,
401402 properties : { gist : { elementId : '#target-el' } } ,
402403 } ;
403404
404- const result = showTooltipComponent ( message ) ;
405+ const result = await showTooltipComponent ( message ) ;
405406
406407 expect ( result ) . toBe ( false ) ;
407408 expect ( log ) . toHaveBeenCalledWith ( 'Tooltip wrapper not found for instance inst-1' ) ;
408409 expect ( positionTooltip ) . not . toHaveBeenCalled ( ) ;
409410 } ) ;
410411
411- it ( 'logs and returns false when no target selector is provided' , ( ) => {
412+ it ( 'logs and returns false when no target selector is provided' , async ( ) => {
412413 setupTooltipWrapper ( 'inst-1' ) ;
413414 const message : GistMessage = {
414415 messageId : 'msg-1' ,
415416 instanceId : 'inst-1' ,
416417 } ;
417418
418- const result = showTooltipComponent ( message ) ;
419+ const result = await showTooltipComponent ( message ) ;
419420
420421 expect ( result ) . toBe ( false ) ;
421422 expect ( log ) . toHaveBeenCalledWith ( 'No target selector for tooltip inst-1' ) ;
@@ -424,6 +425,39 @@ describe('message-component-manager', () => {
424425 const container = document . querySelector ( '.gist-tooltip-container' ) ;
425426 expect ( container ?. classList . contains ( 'gist-visible' ) ) . toBe ( false ) ;
426427 } ) ;
428+
429+ it ( 'returns false without calling positionTooltip when ensureTargetInView returns false' , async ( ) => {
430+ vi . mocked ( ensureTargetInView ) . mockResolvedValue ( false ) ;
431+ setupTooltipWrapper ( 'inst-1' ) ;
432+ const message : GistMessage = {
433+ messageId : 'msg-1' ,
434+ instanceId : 'inst-1' ,
435+ properties : { gist : { elementId : '#target-el' } } ,
436+ } ;
437+
438+ const result = await showTooltipComponent ( message ) ;
439+
440+ expect ( result ) . toBe ( false ) ;
441+ expect ( ensureTargetInView ) . toHaveBeenCalled ( ) ;
442+ expect ( positionTooltip ) . not . toHaveBeenCalled ( ) ;
443+ } ) ;
444+
445+ it ( 'proceeds to positionTooltip when ensureTargetInView returns true' , async ( ) => {
446+ vi . mocked ( ensureTargetInView ) . mockResolvedValue ( true ) ;
447+ vi . mocked ( positionTooltip ) . mockReturnValue ( { cleanup : vi . fn ( ) , reposition : vi . fn ( ) } ) ;
448+ setupTooltipWrapper ( 'inst-1' ) ;
449+ const message : GistMessage = {
450+ messageId : 'msg-1' ,
451+ instanceId : 'inst-1' ,
452+ properties : { gist : { elementId : '#target-el' } } ,
453+ } ;
454+
455+ const result = await showTooltipComponent ( message ) ;
456+
457+ expect ( result ) . toBe ( true ) ;
458+ expect ( ensureTargetInView ) . toHaveBeenCalled ( ) ;
459+ expect ( positionTooltip ) . toHaveBeenCalled ( ) ;
460+ } ) ;
427461 } ) ;
428462
429463 describe ( 'hideTooltipComponent' , ( ) => {
@@ -437,7 +471,7 @@ describe('message-component-manager', () => {
437471 expect ( document . getElementById ( 'gist-tooltip-inst-1' ) ) . toBeNull ( ) ;
438472 } ) ;
439473
440- it ( 'calls the position cleanup function when one exists' , ( ) => {
474+ it ( 'calls the position cleanup function when one exists' , async ( ) => {
441475 const wrapper = document . createElement ( 'div' ) ;
442476 wrapper . id = 'gist-tooltip-inst-1' ;
443477 const tooltip = document . createElement ( 'div' ) ;
@@ -479,7 +513,7 @@ describe('message-component-manager', () => {
479513 properties : { gist : { elementId : '#target-el' } } ,
480514 } ;
481515
482- showTooltipComponent ( message ) ;
516+ await showTooltipComponent ( message ) ;
483517 hideTooltipComponent ( message ) ;
484518
485519 expect ( mockCleanup ) . toHaveBeenCalled ( ) ;
@@ -510,7 +544,7 @@ describe('message-component-manager', () => {
510544 return wrapper ;
511545 }
512546
513- it ( 'calls cleanup on all tracked tooltip handles' , ( ) => {
547+ it ( 'calls cleanup on all tracked tooltip handles' , async ( ) => {
514548 const cleanup1 = vi . fn ( ) ;
515549 const cleanup2 = vi . fn ( ) ;
516550 vi . mocked ( positionTooltip )
@@ -520,12 +554,12 @@ describe('message-component-manager', () => {
520554 setupTooltipWrapper ( 'inst-1' ) ;
521555 setupTooltipWrapper ( 'inst-2' ) ;
522556
523- showTooltipComponent ( {
557+ await showTooltipComponent ( {
524558 messageId : 'msg-1' ,
525559 instanceId : 'inst-1' ,
526560 properties : { gist : { elementId : '#target-1' } } ,
527561 } ) ;
528- showTooltipComponent ( {
562+ await showTooltipComponent ( {
529563 messageId : 'msg-2' ,
530564 instanceId : 'inst-2' ,
531565 properties : { gist : { elementId : '#target-2' } } ,
@@ -564,12 +598,12 @@ describe('message-component-manager', () => {
564598 expect ( ( ) => clearAllTooltipHandles ( ) ) . not . toThrow ( ) ;
565599 } ) ;
566600
567- it ( 'clears the map so subsequent hideTooltipComponent does not double-cleanup' , ( ) => {
601+ it ( 'clears the map so subsequent hideTooltipComponent does not double-cleanup' , async ( ) => {
568602 const mockCleanup = vi . fn ( ) ;
569603 vi . mocked ( positionTooltip ) . mockReturnValue ( { cleanup : mockCleanup , reposition : vi . fn ( ) } ) ;
570604
571605 setupTooltipWrapper ( 'inst-1' ) ;
572- showTooltipComponent ( {
606+ await showTooltipComponent ( {
573607 messageId : 'msg-1' ,
574608 instanceId : 'inst-1' ,
575609 properties : { gist : { elementId : '#target-1' } } ,
0 commit comments