diff --git a/src/components/timeline/TrackThread.js b/src/components/timeline/TrackThread.js index b1b00d91c1..eb3fde310f 100644 --- a/src/components/timeline/TrackThread.js +++ b/src/components/timeline/TrackThread.js @@ -148,7 +148,13 @@ class TimelineTrackThreadImpl extends PureComponent { } else { selectLeafCallNode(threadsKey, sampleIndex); } - focusCallTree(); + + if (sampleIndex !== null) { + // If the user clicked outside of the activity graph (sampleIndex === null), + // then we don't need to focus the call tree. This action also selects + // the call tree panel, which we don't want either in this case. + focusCallTree(); + } } if ( typeof threadsKey === 'number' && diff --git a/src/test/components/ThreadActivityGraph.test.js b/src/test/components/ThreadActivityGraph.test.js index 3d984ad97e..86656bbe77 100644 --- a/src/test/components/ThreadActivityGraph.test.js +++ b/src/test/components/ThreadActivityGraph.test.js @@ -15,10 +15,12 @@ import { Provider } from 'react-redux'; import { render } from 'firefox-profiler/test/fixtures/testing-library'; import { selectedThreadSelectors } from '../../selectors/per-thread'; -import { getTimelineType } from '../../selectors/url-state'; +import { getTimelineType, getSelectedTab } from '../../selectors/url-state'; +import { getLastVisibleThreadTabSlug } from '../../selectors/app'; import { ensureExists } from '../../utils/flow'; import { TimelineTrackThread } from '../../components/timeline/TrackThread'; import { commitRange } from '../../actions/profile-view'; +import { changeSelectedTab } from '../../actions/app'; import { autoMockCanvasContext, @@ -261,6 +263,29 @@ describe('ThreadActivityGraph', function () { expect(getCallNodePath()).toEqual([]); }); + it('when clicking a stack, this selects the call tree panel', function () { + const { dispatch, getState, clickActivityGraph } = setup(); + + dispatch(changeSelectedTab('marker-chart')); + + // The full call node at this sample is: + // A -> B -> C -> F -> G + clickActivityGraph(1, 0.2); + expect(getSelectedTab(getState())).toBe('calltree'); + expect(getLastVisibleThreadTabSlug(getState())).toBe('calltree'); + }); + + it(`when clicking outside of the graph, this doesn't select the call tree panel`, function () { + const { dispatch, getState, clickActivityGraph } = setup(); + + dispatch(changeSelectedTab('marker-chart')); + + // There's no sample at this location. + clickActivityGraph(0, 1); + expect(getSelectedTab(getState())).toBe('marker-chart'); + expect(getLastVisibleThreadTabSlug(getState())).toBe('marker-chart'); + }); + it('will redraw even when there are no samples in range', function () { const { dispatch } = setup(); flushDrawLog(); diff --git a/src/test/components/TrackThread.test.js b/src/test/components/TrackThread.test.js index bf4e798923..156c449407 100644 --- a/src/test/components/TrackThread.test.js +++ b/src/test/components/TrackThread.test.js @@ -16,12 +16,9 @@ import { changeInvertCallstack, changeSelectedCallNode, } from '../../actions/profile-view'; -import { changeSelectedTab } from '../../actions/app'; import { TimelineTrackThread } from '../../components/timeline/TrackThread'; import { getPreviewSelection } from '../../selectors/profile'; import { selectedThreadSelectors } from '../../selectors/per-thread'; -import { getSelectedTab } from '../../selectors/url-state'; -import { getLastVisibleThreadTabSlug } from '../../selectors/app'; import { ensureExists } from '../../utils/flow'; import { @@ -191,19 +188,6 @@ describe('timeline/TrackThread', function () { expect(getCallNodePath()).toEqual(['j', 'k', 'l']); }); - it('when clicking a stack, this selects the call tree panel', function () { - const { dispatch, getState, stackGraphCanvas, getFillRectCenterByIndex } = - setup(getSamplesProfile()); - - dispatch(changeSelectedTab('marker-chart')); - - const log = flushDrawLog(); - - fireFullClick(stackGraphCanvas(), getFillRectCenterByIndex(log, 0)); - expect(getSelectedTab(getState())).toBe('calltree'); - expect(getLastVisibleThreadTabSlug(getState())).toBe('calltree'); - }); - it('can click a stack in the stack graph in inverted call trees', function () { const { dispatch,