@@ -317,17 +317,44 @@ describe("useTimelineEditCallbacks — flat tween keyframe lanes", () => {
317317 } ) ;
318318
319319 it ( "deletes all keyframes through the clicked non-selected element's identity" , async ( ) => {
320- const { circle, selection } = arrangeClickedCircle ( ) ;
320+ const circle : TimelineElement = {
321+ ...element ,
322+ id : "circle" ,
323+ key : "scenes/main.html#circle" ,
324+ domId : "circle" ,
325+ sourceFile : "scenes/main.html" ,
326+ } ;
327+ const circleSelection = { id : "circle" , selector : "#circle" , sourceFile : "scenes/main.html" } ;
328+ const scaleAnimation : GsapAnimation = {
329+ ...otherKeyframedAnimation ,
330+ id : "circle-to-0-scale" ,
331+ properties : { } ,
332+ propertyGroup : "scale" ,
333+ keyframes : {
334+ format : "percentage" ,
335+ keyframes : [
336+ { percentage : 0 , properties : { scale : 1 } } ,
337+ { percentage : 100 , properties : { scale : 2 } } ,
338+ ] ,
339+ } ,
340+ } ;
341+ usePlayerStore . setState ( {
342+ elements : [ element , circle ] ,
343+ gsapAnimations : new Map ( [
344+ [ "scenes/main.html#circle" , [ otherKeyframedAnimation , scaleAnimation ] ] ,
345+ ] ) ,
346+ } ) ;
347+ mocks . actions . buildDomSelectionForTimelineElement . mockResolvedValue ( circleSelection ) ;
321348 const view = renderCallbacks ( ) ;
322349
323350 await act ( async ( ) => {
324- view . callbacks . onDeleteAllKeyframes ?.( circle ) ;
351+ view . callbacks . onDeleteAllKeyframes ?.( circle , scaleAnimation . id ) ;
325352 await Promise . resolve ( ) ;
326353 } ) ;
327354
328355 expect ( mocks . actions . handleGsapRemoveAllKeyframes ) . toHaveBeenCalledWith (
329- otherKeyframedAnimation . id ,
330- selection ,
356+ scaleAnimation . id ,
357+ circleSelection ,
331358 ) ;
332359 view . unmount ( ) ;
333360 } ) ;
@@ -360,6 +387,19 @@ describe("useTimelineEditCallbacks — flat tween keyframe lanes", () => {
360387 view . unmount ( ) ;
361388 } ) ;
362389
390+ it ( "does not delete a different lane when an explicit animation identity is stale" , async ( ) => {
391+ const { circle } = arrangeClickedCircle ( ) ;
392+ const view = renderCallbacks ( ) ;
393+
394+ await act ( async ( ) => {
395+ view . callbacks . onDeleteAllKeyframes ?.( circle , "missing-animation-id" ) ;
396+ await Promise . resolve ( ) ;
397+ } ) ;
398+
399+ expect ( mocks . actions . handleGsapRemoveAllKeyframes ) . not . toHaveBeenCalled ( ) ;
400+ view . unmount ( ) ;
401+ } ) ;
402+
363403 it ( "aborts every mutation when the clicked element resolves no selection" , async ( ) => {
364404 const { circle } = arrangeClickedCircle ( ) ;
365405 mocks . actions . buildDomSelectionForTimelineElement . mockResolvedValue ( null ) ;
@@ -391,6 +431,40 @@ describe("useTimelineEditCallbacks — flat tween keyframe lanes", () => {
391431 view . unmount ( ) ;
392432 } ) ;
393433
434+ it ( "does not delete a different keyframe when its explicit animation identity is stale" , ( ) => {
435+ const view = renderCallbacks ( ) ;
436+
437+ act ( ( ) => {
438+ view . callbacks . onDeleteKeyframe ?.( "box" , {
439+ percentage : 100 ,
440+ propertyGroup : "position" ,
441+ tweenPercentage : 100 ,
442+ animationId : "missing-animation-id" ,
443+ } ) ;
444+ } ) ;
445+
446+ expect ( mocks . actions . handleGsapDeleteAnimation ) . not . toHaveBeenCalled ( ) ;
447+ expect ( mocks . actions . handleGsapRemoveKeyframe ) . not . toHaveBeenCalled ( ) ;
448+ view . unmount ( ) ;
449+ } ) ;
450+
451+ it ( "does not move a different keyframe when its explicit animation identity is stale" , async ( ) => {
452+ const view = renderCallbacks ( ) ;
453+
454+ await act ( async ( ) => {
455+ view . callbacks . onMoveKeyframeToPlayhead ?.( element , {
456+ percentage : 100 ,
457+ propertyGroup : "position" ,
458+ tweenPercentage : 100 ,
459+ animationId : "missing-animation-id" ,
460+ } ) ;
461+ await Promise . resolve ( ) ;
462+ } ) ;
463+
464+ expect ( mocks . actions . handleGsapMoveKeyframeToPlayhead ) . not . toHaveBeenCalled ( ) ;
465+ view . unmount ( ) ;
466+ } ) ;
467+
394468 it ( "moves a keyframe to the playhead through the clicked non-selected element's identity" , async ( ) => {
395469 const { circle, selection } = arrangeClickedCircle ( ) ;
396470 const view = renderCallbacks ( ) ;
0 commit comments