@@ -25,6 +25,8 @@ import {
2525 changeSelectedCallNode ,
2626 changeCallTreeSummaryStrategy ,
2727} from '../../actions/profile-view' ;
28+ import * as AppActions from '../../actions/app' ;
29+ import * as UrlStateSelectors from '../../selectors/url-state' ;
2830import { selectedThreadSelectors } from '../../selectors/per-thread' ;
2931
3032describe ( '"focus-subtree" transform' , function ( ) {
@@ -819,6 +821,70 @@ describe('"focus-category" transform', function () {
819821 expect ( selectedCallNodePath ) . toEqual ( [ A , A ] ) ;
820822 } ) ;
821823 } ) ;
824+
825+ describe ( 'browser back button behavior' , function ( ) {
826+ // This test ensures that when using browser back button after applying
827+ // a focus-category transform, re-applying the transform doesn't fail.
828+ // The bug occurred because expanded paths from the transformed tree
829+ // weren't being reset when the URL state changed via browser navigation.
830+ const { threadIndex, categoryIndex, funcNamesDict, getState, dispatch } =
831+ setup ( `
832+ A[cat:Other] A[cat:Other]
833+ B[cat:Other] B[cat:Other]
834+ C[cat:Graphics] C[cat:Graphics]
835+ D[cat:Graphics] D[cat:Graphics]
836+ E[cat:Graphics] F[cat:Graphics]
837+ ` ) ;
838+
839+ it ( 'can re-apply transform after browser back without error' , function ( ) {
840+ const { C, D, E } = funcNamesDict ;
841+
842+ // Apply focus-category transform.
843+ dispatch (
844+ addTransformToStack ( threadIndex , {
845+ type : 'focus-category' ,
846+ category : categoryIndex ,
847+ } )
848+ ) ;
849+
850+ // Select a deep node in the transformed tree, which expands paths.
851+ // In the transformed tree, C becomes a root since A and B are filtered out.
852+ dispatch ( changeSelectedCallNode ( threadIndex , [ C , D , E ] ) ) ;
853+
854+ expect (
855+ selectedThreadSelectors . getSelectedCallNodePath ( getState ( ) )
856+ ) . toEqual ( [ C , D , E ] ) ;
857+
858+ // Capture the current URL state with transforms.
859+ const urlStateWithTransforms = UrlStateSelectors . getUrlState ( getState ( ) ) ;
860+
861+ // Simulate browser back button by creating a URL state without transforms.
862+ const urlStateWithoutTransforms = {
863+ ...urlStateWithTransforms ,
864+ profileSpecific : {
865+ ...urlStateWithTransforms . profileSpecific ,
866+ transforms : { } ,
867+ } ,
868+ } ;
869+
870+ // Apply the URL state change (simulating browser back).
871+ dispatch ( AppActions . updateUrlState ( urlStateWithoutTransforms ) ) ;
872+
873+ // Re-apply the same transform. This should not throw an error.
874+ expect ( ( ) => {
875+ dispatch (
876+ addTransformToStack ( threadIndex , {
877+ type : 'focus-category' ,
878+ category : categoryIndex ,
879+ } )
880+ ) ;
881+ } ) . not . toThrow ( ) ;
882+
883+ expect (
884+ selectedThreadSelectors . getSelectedCallNodePath ( getState ( ) )
885+ ) . toEqual ( [ ] ) ;
886+ } ) ;
887+ } ) ;
822888} ) ;
823889
824890describe ( '"collapse-resource" transform' , function ( ) {
0 commit comments