From 9f749b6c63acdf56e303dc92139ce0a7e26d5984 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Mon, 26 Sep 2022 13:40:58 +0200 Subject: [PATCH 1/5] Squashed prior commits --- locales/en-US/app.ftl | 4 + src/components/app/MenuButtons/MetaInfo.css | 15 +++- src/components/app/MenuButtons/MetaInfo.js | 85 +++++++++++++++++++-- src/components/app/MenuButtons/index.js | 33 ++++---- src/selectors/profile.js | 11 +++ src/types/profile.js | 16 +++- 6 files changed, 142 insertions(+), 22 deletions(-) diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index 1fca268904..1f9102595f 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -413,6 +413,10 @@ MenuButtons--metaInfo--attempting-resymbolicate = Attempting to re-symbolicate p MenuButtons--metaInfo--currently-symbolicating = Currently symbolicating profile MenuButtons--metaInfo--cpu = CPU: MenuButtons--metaInfo--main-memory = Main memory: +MenuButtons--moreInfo-button = More +MenuButtons--moreInfo-title = Additional Profile Information +MenuButtons--index--show-moreInfo-button = Show More +MenuButtons--index--hide-moreInfo-button = Show Less # This string is used when we have the information about both physical and # logical CPU cores. diff --git a/src/components/app/MenuButtons/MetaInfo.css b/src/components/app/MenuButtons/MetaInfo.css index a10ec27c05..bb68ba4753 100644 --- a/src/components/app/MenuButtons/MetaInfo.css +++ b/src/components/app/MenuButtons/MetaInfo.css @@ -27,7 +27,7 @@ .metaInfoLargeContent { overflow: scroll; - height: 100px; + max-height: 100px; overflow-wrap: anywhere; } @@ -67,3 +67,16 @@ font-size: 1.2em; font-weight: 700; } + +.moreInfoButton { + width: 100%; + margin-top: 15px; +} + +.moreInfoPart { + margin-top: 15px; +} + +.moreInfoValue { + overflow-x: scroll; +} diff --git a/src/components/app/MenuButtons/MetaInfo.js b/src/components/app/MenuButtons/MetaInfo.js index 1736ebedb0..3d2d92ac82 100644 --- a/src/components/app/MenuButtons/MetaInfo.js +++ b/src/components/app/MenuButtons/MetaInfo.js @@ -10,8 +10,12 @@ import { MetaOverheadStatistics } from './MetaOverheadStatistics'; import { getProfile, getSymbolicationStatus, + hasProfileExtraInfo, + getMarkerSchemaByName, + getProfileExtraInfo, } from 'firefox-profiler/selectors/profile'; import { resymbolicateProfile } from 'firefox-profiler/actions/receive-profile'; +import { formatFromMarkerSchema } from 'firefox-profiler/profile-logic/marker-schema'; import { formatBytes, @@ -25,26 +29,40 @@ import { import { assertExhaustiveCheck } from 'firefox-profiler/utils/flow'; import explicitConnect from 'firefox-profiler/utils/connect'; -import type { Profile, SymbolicationStatus } from 'firefox-profiler/types'; +import type { + Profile, + SymbolicationStatus, + ExtraProfileInfoSection, + MarkerSchemaByName, +} from 'firefox-profiler/types'; import type { ConnectedProps } from 'firefox-profiler/utils/connect'; import './MetaInfo.css'; -type StateProps = $ReadOnly<{| +type State = {| + showsMoreInfo: boolean, +|}; + +type OwnProps = $ReadOnly<{| profile: Profile, symbolicationStatus: SymbolicationStatus, + hasProfileExtraInfo: boolean, + +profileExtraInfo: ExtraProfileInfoSection[], + +markerSchemaByName: MarkerSchemaByName, |}>; type DispatchProps = $ReadOnly<{| resymbolicateProfile: typeof resymbolicateProfile, |}>; -type Props = ConnectedProps<{||}, StateProps, DispatchProps>; +type Props = ConnectedProps<{||}, OwnProps, DispatchProps>; /** * This component formats the profile's meta information into a dropdown panel. */ -class MetaInfoPanelImpl extends React.PureComponent { +class MetaInfoPanelImpl extends React.PureComponent { + state = { showsMoreInfo: false }; + /** * This method provides information about the symbolication status, and a button * to re-trigger symbolication. @@ -120,6 +138,40 @@ class MetaInfoPanelImpl extends React.PureComponent { } } + _handleMoreInfoButtonClick = () => { + this.setState((state) => ({ showsMoreInfo: !state.showsMoreInfo })); + }; + + _renderMoreInfoSection(section: ExtraProfileInfoSection) { + return ( +
+

+ {section.label} +

+
+ {section.entries.map(({ label, format, value }) => { + return ( +
+ {label} +
+ {formatFromMarkerSchema('moreInfo', format, value)} +
+
+ ); + })} +
+
+ ); + } + + _renderMoreInfo() { + return ( +
+ {this.props.profileExtraInfo.map(this._renderMoreInfoSection)} +
+ ); + } + render() { const { meta, profilerOverhead } = this.props.profile; const { configuration } = meta; @@ -403,6 +455,26 @@ class MetaInfoPanelImpl extends React.PureComponent { {profilerOverhead ? ( ) : null} + {this.props.hasProfileExtraInfo ? ( +
+ +
+ ) : null} + {this.props.hasProfileExtraInfo && this.state.showsMoreInfo + ? this._renderMoreInfo() + : null} ); } @@ -440,10 +512,13 @@ function _formatDate(timestamp: number): string { return timestampDate; } -export const MetaInfoPanel = explicitConnect<{||}, StateProps, DispatchProps>({ +export const MetaInfoPanel = explicitConnect<{||}, OwnProps, DispatchProps>({ mapStateToProps: (state) => ({ profile: getProfile(state), symbolicationStatus: getSymbolicationStatus(state), + hasProfileExtraInfo: hasProfileExtraInfo(state), + profileExtraInfo: getProfileExtraInfo(state), + markerSchemaByName: getMarkerSchemaByName(state), }), mapDispatchToProps: { resymbolicateProfile, diff --git a/src/components/app/MenuButtons/index.js b/src/components/app/MenuButtons/index.js index b3bb5c445b..619e452201 100644 --- a/src/components/app/MenuButtons/index.js +++ b/src/components/app/MenuButtons/index.js @@ -91,7 +91,9 @@ type State = $ReadOnly<{| |}>; class MenuButtonsImpl extends React.PureComponent { - state = { metaInfoPanelState: 'initial' }; + state = { + metaInfoPanelState: 'initial', + }; componentDidMount() { // Clear out the newly published notice from the URL. @@ -228,7 +230,6 @@ class MenuButtonsImpl extends React.PureComponent { // we still have to pass jwtToken / profileToken, and we don't have // these values anymore when we're in this state. return ; - default: throw assertExhaustiveCheck(metaInfoPanelState); } @@ -236,19 +237,21 @@ class MenuButtonsImpl extends React.PureComponent { _renderMetaInfoButton() { return ( - - wrapper. - label="" - onPanelClose={this._resetMetaInfoState} - panelClassName="metaInfoPanel" - panelContent={this._renderMetaInfoPanel()} - /> - + <> + + wrapper. + label="" + onPanelClose={this._resetMetaInfoState} + panelClassName="metaInfoPanel" + panelContent={this._renderMetaInfoPanel()} + /> + + ); } diff --git a/src/selectors/profile.js b/src/selectors/profile.js index 3f756e549b..a125fd3a47 100644 --- a/src/selectors/profile.js +++ b/src/selectors/profile.js @@ -74,6 +74,7 @@ import type { MarkerSchemaByName, SampleUnits, IndexIntoSamplesTable, + ExtraProfileInfoSection, } from 'firefox-profiler/types'; export const getProfileView: Selector = (state) => @@ -924,3 +925,13 @@ export const getProfileUsesMultipleStackTypes: Selector = (state) => { } return profile.meta.usesOnlyOneStackType !== true; }; + +export const getProfileExtraInfo: Selector = ( + state +) => { + return getProfile(state).meta.extra || []; +}; + +export const hasProfileExtraInfo: Selector = (state) => { + return getProfileExtraInfo(state).length > 0; +}; diff --git a/src/types/profile.js b/src/types/profile.js index 44ad29cbbd..b16997c785 100644 --- a/src/types/profile.js +++ b/src/types/profile.js @@ -6,7 +6,7 @@ import type { Milliseconds, Address, Microseconds, Bytes } from './units'; import type { UniqueStringArray } from '../utils/unique-string-array'; -import type { MarkerPayload, MarkerSchema } from './markers'; +import type { MarkerPayload, MarkerSchema, MarkerFormatType } from './markers'; import type { MarkerPhase, ProfilingLog } from './gecko-profile'; export type IndexIntoStackTable = number; @@ -734,6 +734,17 @@ export type SampleUnits = {| +threadCPUDelta: ThreadCPUDeltaUnit, |}; +export type ExtraProfileInfoSection = {| + // section label + label: string, + entries: Array<{| + label: string, + format: MarkerFormatType, + // any value valid for the formatter + value: any, + |}>, +|}; + /** * Meta information associated for the entire profile. */ @@ -874,6 +885,9 @@ export type ProfileMeta = {| doesNotUseFrameImplementation?: boolean, // Hide the "Look up the function name on Searchfox" menu entry? sourceCodeIsNotOnSearchfox?: boolean, + // Extra information about the profile, not shown in the "Profile Info" panel, + // but in the more info panel + extra?: ExtraProfileInfoSection[], |}; /** From 983e8af5eff272fc4989173d4f1826a12de8cdd8 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Mon, 26 Sep 2022 15:17:20 +0200 Subject: [PATCH 2/5] Improve and add tests --- locales/en-US/app.ftl | 2 - src/components/app/MenuButtons/MetaInfo.css | 4 + src/components/app/MenuButtons/MetaInfo.js | 59 ++- src/components/app/MenuButtons/index.js | 33 +- src/selectors/profile.js | 11 +- src/test/components/MenuButtons.test.js | 1 + src/test/components/MetaInfo.test.js | 61 +++ .../__snapshots__/MetaInfo.test.js.snap | 393 ++++++++++++++++++ .../fixtures/profiles/processed-profile.js | 35 ++ 9 files changed, 537 insertions(+), 62 deletions(-) create mode 100644 src/test/components/MetaInfo.test.js create mode 100644 src/test/components/__snapshots__/MetaInfo.test.js.snap diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index 1f9102595f..9a807f2989 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -413,8 +413,6 @@ MenuButtons--metaInfo--attempting-resymbolicate = Attempting to re-symbolicate p MenuButtons--metaInfo--currently-symbolicating = Currently symbolicating profile MenuButtons--metaInfo--cpu = CPU: MenuButtons--metaInfo--main-memory = Main memory: -MenuButtons--moreInfo-button = More -MenuButtons--moreInfo-title = Additional Profile Information MenuButtons--index--show-moreInfo-button = Show More MenuButtons--index--hide-moreInfo-button = Show Less diff --git a/src/components/app/MenuButtons/MetaInfo.css b/src/components/app/MenuButtons/MetaInfo.css index bb68ba4753..00dc91e054 100644 --- a/src/components/app/MenuButtons/MetaInfo.css +++ b/src/components/app/MenuButtons/MetaInfo.css @@ -68,6 +68,10 @@ font-weight: 700; } +.moreInfoSummary::marker { + content: ''; +} + .moreInfoButton { width: 100%; margin-top: 15px; diff --git a/src/components/app/MenuButtons/MetaInfo.js b/src/components/app/MenuButtons/MetaInfo.js index 3d2d92ac82..3a69a4caa2 100644 --- a/src/components/app/MenuButtons/MetaInfo.js +++ b/src/components/app/MenuButtons/MetaInfo.js @@ -10,8 +10,6 @@ import { MetaOverheadStatistics } from './MetaOverheadStatistics'; import { getProfile, getSymbolicationStatus, - hasProfileExtraInfo, - getMarkerSchemaByName, getProfileExtraInfo, } from 'firefox-profiler/selectors/profile'; import { resymbolicateProfile } from 'firefox-profiler/actions/receive-profile'; @@ -33,22 +31,19 @@ import type { Profile, SymbolicationStatus, ExtraProfileInfoSection, - MarkerSchemaByName, } from 'firefox-profiler/types'; import type { ConnectedProps } from 'firefox-profiler/utils/connect'; import './MetaInfo.css'; -type State = {| +type StateProps = {| showsMoreInfo: boolean, |}; type OwnProps = $ReadOnly<{| profile: Profile, symbolicationStatus: SymbolicationStatus, - hasProfileExtraInfo: boolean, - +profileExtraInfo: ExtraProfileInfoSection[], - +markerSchemaByName: MarkerSchemaByName, + profileExtraInfo: ExtraProfileInfoSection[], |}>; type DispatchProps = $ReadOnly<{| @@ -60,7 +55,7 @@ type Props = ConnectedProps<{||}, OwnProps, DispatchProps>; /** * This component formats the profile's meta information into a dropdown panel. */ -class MetaInfoPanelImpl extends React.PureComponent { +class MetaInfoPanelImpl extends React.PureComponent { state = { showsMoreInfo: false }; /** @@ -145,10 +140,8 @@ class MetaInfoPanelImpl extends React.PureComponent { _renderMoreInfoSection(section: ExtraProfileInfoSection) { return (
-

- {section.label} -

-
+

{section.label}

+
{section.entries.map(({ label, format, value }) => { return (
@@ -166,7 +159,7 @@ class MetaInfoPanelImpl extends React.PureComponent { _renderMoreInfo() { return ( -
+
{this.props.profileExtraInfo.map(this._renderMoreInfoSection)}
); @@ -455,26 +448,28 @@ class MetaInfoPanelImpl extends React.PureComponent { {profilerOverhead ? ( ) : null} - {this.props.hasProfileExtraInfo ? ( -
- -
+ + {this.state.showsMoreInfo ? 'Show Less' : 'Show More'} + + + + {this._renderMoreInfo()} + ) : null} - {this.props.hasProfileExtraInfo && this.state.showsMoreInfo - ? this._renderMoreInfo() - : null} ); } @@ -516,9 +511,7 @@ export const MetaInfoPanel = explicitConnect<{||}, OwnProps, DispatchProps>({ mapStateToProps: (state) => ({ profile: getProfile(state), symbolicationStatus: getSymbolicationStatus(state), - hasProfileExtraInfo: hasProfileExtraInfo(state), profileExtraInfo: getProfileExtraInfo(state), - markerSchemaByName: getMarkerSchemaByName(state), }), mapDispatchToProps: { resymbolicateProfile, diff --git a/src/components/app/MenuButtons/index.js b/src/components/app/MenuButtons/index.js index 619e452201..b3bb5c445b 100644 --- a/src/components/app/MenuButtons/index.js +++ b/src/components/app/MenuButtons/index.js @@ -91,9 +91,7 @@ type State = $ReadOnly<{| |}>; class MenuButtonsImpl extends React.PureComponent { - state = { - metaInfoPanelState: 'initial', - }; + state = { metaInfoPanelState: 'initial' }; componentDidMount() { // Clear out the newly published notice from the URL. @@ -230,6 +228,7 @@ class MenuButtonsImpl extends React.PureComponent { // we still have to pass jwtToken / profileToken, and we don't have // these values anymore when we're in this state. return ; + default: throw assertExhaustiveCheck(metaInfoPanelState); } @@ -237,21 +236,19 @@ class MenuButtonsImpl extends React.PureComponent { _renderMetaInfoButton() { return ( - <> - - wrapper. - label="" - onPanelClose={this._resetMetaInfoState} - panelClassName="metaInfoPanel" - panelContent={this._renderMetaInfoPanel()} - /> - - + + wrapper. + label="" + onPanelClose={this._resetMetaInfoState} + panelClassName="metaInfoPanel" + panelContent={this._renderMetaInfoPanel()} + /> + ); } diff --git a/src/selectors/profile.js b/src/selectors/profile.js index a125fd3a47..5b819ca7ab 100644 --- a/src/selectors/profile.js +++ b/src/selectors/profile.js @@ -926,12 +926,5 @@ export const getProfileUsesMultipleStackTypes: Selector = (state) => { return profile.meta.usesOnlyOneStackType !== true; }; -export const getProfileExtraInfo: Selector = ( - state -) => { - return getProfile(state).meta.extra || []; -}; - -export const hasProfileExtraInfo: Selector = (state) => { - return getProfileExtraInfo(state).length > 0; -}; +export const getProfileExtraInfo: Selector = + createSelector(getProfile, (profile) => profile.meta.extra || []); diff --git a/src/test/components/MenuButtons.test.js b/src/test/components/MenuButtons.test.js index b202340db8..6fdfbec3c9 100644 --- a/src/test/components/MenuButtons.test.js +++ b/src/test/components/MenuButtons.test.js @@ -72,6 +72,7 @@ import { shortenUrl } from '../../utils/shorten-url'; jest.mock('../../utils/shorten-url'); import { symbolicateProfile } from 'firefox-profiler/profile-logic/symbolication'; + jest.mock('firefox-profiler/profile-logic/symbolication'); // Mock hash diff --git a/src/test/components/MetaInfo.test.js b/src/test/components/MetaInfo.test.js new file mode 100644 index 0000000000..624bd464b1 --- /dev/null +++ b/src/test/components/MetaInfo.test.js @@ -0,0 +1,61 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// @flow +import * as React from 'react'; +import { fireFullClick } from '../fixtures/utils'; +import { ensureExists } from '../../utils/flow'; +import { Provider } from 'react-redux'; + +import { render } from 'firefox-profiler/test/fixtures/testing-library'; +import { + getProfileFromTextSamples, + addExtraInfoToProfile, +} from '../fixtures/profiles/processed-profile'; +import { storeWithProfile } from '../fixtures/stores'; +import { MetaInfoPanel } from '../../components/app/MenuButtons/MetaInfo'; + +describe('app/MetaInfo', function () { + function setup(store) { + const renderResult = render( + + + + ); + + return { + ...store, + ...renderResult, + }; + } + + function setupForMoreInfoButton(addExtraInfos: boolean = false) { + const initialProfile = getProfileFromTextSamples('A').profile; + const profile = addExtraInfos + ? addExtraInfoToProfile(initialProfile) + : initialProfile; + return setup(storeWithProfile(profile)); + } + + describe('More Info section', function () { + it('opens more info section if clicked', () => { + const { container } = setupForMoreInfoButton(true); + + expect(container).toMatchSnapshot(); + + const summary = ensureExists(container.querySelector('.moreInfoSummary')); + + fireFullClick(summary); + expect(container).toMatchSnapshot(); + }); + + it("doesn't show the more info button if there isn't any extra info", () => { + const { container } = setupForMoreInfoButton(false); + expect(container).toMatchSnapshot(); + + const summary = container.querySelector('.moreInfoSummary'); + expect(summary).toBeNull(); + }); + }); +}); diff --git a/src/test/components/__snapshots__/MetaInfo.test.js.snap b/src/test/components/__snapshots__/MetaInfo.test.js.snap new file mode 100644 index 0000000000..eeb73df7ac --- /dev/null +++ b/src/test/components/__snapshots__/MetaInfo.test.js.snap @@ -0,0 +1,393 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`app/MetaInfo More Info section doesn't show the more info button if there isn't any extra info 1`] = ` +
+
+
+ + Interval: + + 1ms +
+
+ + Symbols: + + Profile is symbolicated +
+
+ + +
+
+

+ Application +

+
+
+ + Name and version: + + Firefox +
+
+

+ Platform +

+
+
+`; + +exports[`app/MetaInfo More Info section opens more info section if clicked 1`] = ` +
+
+
+ + Interval: + + 1ms +
+
+ + Symbols: + + Profile is symbolicated +
+
+ + +
+
+

+ Application +

+
+
+ + Name and version: + + Firefox +
+
+

+ Platform +

+
+
+ + + +
+
+

+ CPU +

+
+
+ + CPU 1 + +
+ Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz +
+
+
+
+
+

+ Memory +

+
+
+
+

+ Hard Drives +

+
+
+ + SSD + +
+ Samsung SSD 850 EVO 500GB +
+
+
+ + HDD + +
+ Seagate ST1000LM035-1RK172 +
+
+
+
+
+
+
+`; + +exports[`app/MetaInfo More Info section opens more info section if clicked 2`] = ` +
+
+
+ + Interval: + + 1ms +
+
+ + Symbols: + + Profile is symbolicated +
+
+ + +
+
+

+ Application +

+
+
+ + Name and version: + + Firefox +
+
+

+ Platform +

+
+
+ + + +
+
+

+ CPU +

+
+
+ + CPU 1 + +
+ Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz +
+
+
+
+
+

+ Memory +

+
+
+
+

+ Hard Drives +

+
+
+ + SSD + +
+ Samsung SSD 850 EVO 500GB +
+
+
+ + HDD + +
+ Seagate ST1000LM035-1RK172 +
+
+
+
+
+
+
+`; diff --git a/src/test/fixtures/profiles/processed-profile.js b/src/test/fixtures/profiles/processed-profile.js index 8fce5b9048..7dd19b971a 100644 --- a/src/test/fixtures/profiles/processed-profile.js +++ b/src/test/fixtures/profiles/processed-profile.js @@ -1871,6 +1871,41 @@ export function addActiveTabInformationToProfile( }; } +export function addExtraInfoToProfile(profile: Profile): Profile { + profile.meta.extra = [ + { + label: 'CPU', + entries: [ + { + label: 'CPU 1', + format: 'string', + value: 'Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz', + }, + ], + }, + { + label: 'Memory', + entries: [], + }, + { + label: 'Hard Drives', + entries: [ + { + label: 'SSD', + format: 'string', + value: 'Samsung SSD 850 EVO 500GB', + }, + { + label: 'HDD', + format: 'string', + value: 'Seagate ST1000LM035-1RK172', + }, + ], + }, + ]; + return profile; +} + /** * Use this function to create a profile that has private browsing data. * This profile should first be run through addActiveTabInformationToProfile to From 846091048723660976a0658dd8807764dd7b16e0 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 29 Sep 2022 19:11:02 +0200 Subject: [PATCH 3/5] Improve tests --- src/test/components/MenuButtons.test.js | 52 ++- src/test/components/MetaInfo.test.js | 61 --- .../__snapshots__/MenuButtons.test.js.snap | 81 ++++ .../__snapshots__/MetaInfo.test.js.snap | 393 ------------------ .../fixtures/profiles/processed-profile.js | 35 -- 5 files changed, 132 insertions(+), 490 deletions(-) delete mode 100644 src/test/components/MetaInfo.test.js delete mode 100644 src/test/components/__snapshots__/MetaInfo.test.js.snap diff --git a/src/test/components/MenuButtons.test.js b/src/test/components/MenuButtons.test.js index 6fdfbec3c9..7f63be7edc 100644 --- a/src/test/components/MenuButtons.test.js +++ b/src/test/components/MenuButtons.test.js @@ -72,7 +72,6 @@ import { shortenUrl } from '../../utils/shorten-url'; jest.mock('../../utils/shorten-url'); import { symbolicateProfile } from 'firefox-profiler/profile-logic/symbolication'; - jest.mock('firefox-profiler/profile-logic/symbolication'); // Mock hash @@ -518,6 +517,57 @@ describe('app/MenuButtons', function () { expect(getMetaInfoPanel()).toMatchSnapshot(); }); + it('with no extra info there is no more info button', async () => { + const { profile } = getProfileFromTextSamples('A'); + const { displayMetaInfoPanel } = await setupForMetaInfoPanel(profile); + await displayMetaInfoPanel(); + + expect(screen.queryByText('Show More')).not.toBeInTheDocument(); + }); + + it('with more extra info, opens more info section if clicked', async () => { + const { profile } = getProfileFromTextSamples('A'); + profile.meta.extra = [ + { + label: 'CPU', + entries: [ + { + label: 'CPU 1', + format: 'string', + value: 'Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz', + }, + ], + }, + { + label: 'Memory', + entries: [], + }, + { + label: 'Hard Drives', + entries: [ + { + label: 'SSD', + format: 'string', + value: 'Samsung SSD 850 EVO 500GB', + }, + { + label: 'HDD', + format: 'string', + value: 'Seagate ST1000LM035-1RK172', + }, + ], + }, + ]; + + const { displayMetaInfoPanel } = await setupForMetaInfoPanel(profile); + await displayMetaInfoPanel(); + + const summary = screen.getByText('Show More'); + fireFullClick(summary); + const moreInfoPart = document.querySelector('.moreInfoPart'); + expect(moreInfoPart).toMatchSnapshot(); + }); + describe('deleting a profile', () => { const FAKE_HASH = 'FAKE_HASH'; const FAKE_PROFILE_DATA = { diff --git a/src/test/components/MetaInfo.test.js b/src/test/components/MetaInfo.test.js deleted file mode 100644 index 624bd464b1..0000000000 --- a/src/test/components/MetaInfo.test.js +++ /dev/null @@ -1,61 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// @flow -import * as React from 'react'; -import { fireFullClick } from '../fixtures/utils'; -import { ensureExists } from '../../utils/flow'; -import { Provider } from 'react-redux'; - -import { render } from 'firefox-profiler/test/fixtures/testing-library'; -import { - getProfileFromTextSamples, - addExtraInfoToProfile, -} from '../fixtures/profiles/processed-profile'; -import { storeWithProfile } from '../fixtures/stores'; -import { MetaInfoPanel } from '../../components/app/MenuButtons/MetaInfo'; - -describe('app/MetaInfo', function () { - function setup(store) { - const renderResult = render( - - - - ); - - return { - ...store, - ...renderResult, - }; - } - - function setupForMoreInfoButton(addExtraInfos: boolean = false) { - const initialProfile = getProfileFromTextSamples('A').profile; - const profile = addExtraInfos - ? addExtraInfoToProfile(initialProfile) - : initialProfile; - return setup(storeWithProfile(profile)); - } - - describe('More Info section', function () { - it('opens more info section if clicked', () => { - const { container } = setupForMoreInfoButton(true); - - expect(container).toMatchSnapshot(); - - const summary = ensureExists(container.querySelector('.moreInfoSummary')); - - fireFullClick(summary); - expect(container).toMatchSnapshot(); - }); - - it("doesn't show the more info button if there isn't any extra info", () => { - const { container } = setupForMoreInfoButton(false); - expect(container).toMatchSnapshot(); - - const summary = container.querySelector('.moreInfoSummary'); - expect(summary).toBeNull(); - }); - }); -}); diff --git a/src/test/components/__snapshots__/MenuButtons.test.js.snap b/src/test/components/__snapshots__/MenuButtons.test.js.snap index 783ac42320..e701b493b3 100644 --- a/src/test/components/__snapshots__/MenuButtons.test.js.snap +++ b/src/test/components/__snapshots__/MenuButtons.test.js.snap @@ -1132,6 +1132,87 @@ exports[`app/MenuButtons matches the snapshot with device inform
`; +exports[`app/MenuButtons with more extra info, opens more info section if clicked 1`] = ` +
+
+

+ CPU +

+
+
+ + CPU 1 + +
+ Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz +
+
+
+
+
+

+ Memory +

+
+
+
+

+ Hard Drives +

+
+
+ + SSD + +
+ Samsung SSD 850 EVO 500GB +
+
+
+ + HDD + +
+ Seagate ST1000LM035-1RK172 +
+
+
+
+
+`; + exports[`app/MenuButtons with no statistics object should not make the app crash 1`] = `
-
-
- - Interval: - - 1ms -
-
- - Symbols: - - Profile is symbolicated -
-
- - -
-
-

- Application -

-
-
- - Name and version: - - Firefox -
-
-

- Platform -

-
-
-`; - -exports[`app/MetaInfo More Info section opens more info section if clicked 1`] = ` -
-
-
- - Interval: - - 1ms -
-
- - Symbols: - - Profile is symbolicated -
-
- - -
-
-

- Application -

-
-
- - Name and version: - - Firefox -
-
-

- Platform -

-
-
- - - -
-
-

- CPU -

-
-
- - CPU 1 - -
- Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz -
-
-
-
-
-

- Memory -

-
-
-
-

- Hard Drives -

-
-
- - SSD - -
- Samsung SSD 850 EVO 500GB -
-
-
- - HDD - -
- Seagate ST1000LM035-1RK172 -
-
-
-
-
-
-
-`; - -exports[`app/MetaInfo More Info section opens more info section if clicked 2`] = ` -
-
-
- - Interval: - - 1ms -
-
- - Symbols: - - Profile is symbolicated -
-
- - -
-
-

- Application -

-
-
- - Name and version: - - Firefox -
-
-

- Platform -

-
-
- - - -
-
-

- CPU -

-
-
- - CPU 1 - -
- Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz -
-
-
-
-
-

- Memory -

-
-
-
-

- Hard Drives -

-
-
- - SSD - -
- Samsung SSD 850 EVO 500GB -
-
-
- - HDD - -
- Seagate ST1000LM035-1RK172 -
-
-
-
-
-
-
-`; diff --git a/src/test/fixtures/profiles/processed-profile.js b/src/test/fixtures/profiles/processed-profile.js index 7dd19b971a..8fce5b9048 100644 --- a/src/test/fixtures/profiles/processed-profile.js +++ b/src/test/fixtures/profiles/processed-profile.js @@ -1871,41 +1871,6 @@ export function addActiveTabInformationToProfile( }; } -export function addExtraInfoToProfile(profile: Profile): Profile { - profile.meta.extra = [ - { - label: 'CPU', - entries: [ - { - label: 'CPU 1', - format: 'string', - value: 'Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz', - }, - ], - }, - { - label: 'Memory', - entries: [], - }, - { - label: 'Hard Drives', - entries: [ - { - label: 'SSD', - format: 'string', - value: 'Samsung SSD 850 EVO 500GB', - }, - { - label: 'HDD', - format: 'string', - value: 'Seagate ST1000LM035-1RK172', - }, - ], - }, - ]; - return profile; -} - /** * Use this function to create a profile that has private browsing data. * This profile should first be run through addActiveTabInformationToProfile to From 6ee15669d687ed9df2bc6c78dc27ea2e70c2681c Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 29 Sep 2022 19:53:24 +0200 Subject: [PATCH 4/5] Simplify the implementation of the more info button --- locales/en-US/app.ftl | 4 +- src/components/app/MenuButtons/MetaInfo.css | 13 +++-- src/components/app/MenuButtons/MetaInfo.js | 60 ++++++++++----------- src/test/components/MenuButtons.test.js | 4 +- 4 files changed, 41 insertions(+), 40 deletions(-) diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index 9a807f2989..57a160e0f8 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -413,8 +413,8 @@ MenuButtons--metaInfo--attempting-resymbolicate = Attempting to re-symbolicate p MenuButtons--metaInfo--currently-symbolicating = Currently symbolicating profile MenuButtons--metaInfo--cpu = CPU: MenuButtons--metaInfo--main-memory = Main memory: -MenuButtons--index--show-moreInfo-button = Show More -MenuButtons--index--hide-moreInfo-button = Show Less +MenuButtons--index--show-moreInfo-button = Show more +MenuButtons--index--hide-moreInfo-button = Show less # This string is used when we have the information about both physical and # logical CPU cores. diff --git a/src/components/app/MenuButtons/MetaInfo.css b/src/components/app/MenuButtons/MetaInfo.css index 00dc91e054..1067be8932 100644 --- a/src/components/app/MenuButtons/MetaInfo.css +++ b/src/components/app/MenuButtons/MetaInfo.css @@ -68,13 +68,16 @@ font-weight: 700; } -.moreInfoSummary::marker { - content: ''; +.moreInfoSummary { + display: flex; + align-items: center; + justify-content: center; + margin-top: 24px; + user-select: none; } -.moreInfoButton { - width: 100%; - margin-top: 15px; +.moreInfoSummary::marker { + content: ''; } .moreInfoPart { diff --git a/src/components/app/MenuButtons/MetaInfo.js b/src/components/app/MenuButtons/MetaInfo.js index 3a69a4caa2..8cd6bf03f4 100644 --- a/src/components/app/MenuButtons/MetaInfo.js +++ b/src/components/app/MenuButtons/MetaInfo.js @@ -36,11 +36,11 @@ import type { ConnectedProps } from 'firefox-profiler/utils/connect'; import './MetaInfo.css'; -type StateProps = {| +type State = {| showsMoreInfo: boolean, |}; -type OwnProps = $ReadOnly<{| +type StateProps = $ReadOnly<{| profile: Profile, symbolicationStatus: SymbolicationStatus, profileExtraInfo: ExtraProfileInfoSection[], @@ -50,12 +50,12 @@ type DispatchProps = $ReadOnly<{| resymbolicateProfile: typeof resymbolicateProfile, |}>; -type Props = ConnectedProps<{||}, OwnProps, DispatchProps>; +type Props = ConnectedProps<{||}, StateProps, DispatchProps>; /** * This component formats the profile's meta information into a dropdown panel. */ -class MetaInfoPanelImpl extends React.PureComponent { +class MetaInfoPanelImpl extends React.PureComponent { state = { showsMoreInfo: false }; /** @@ -133,7 +133,8 @@ class MetaInfoPanelImpl extends React.PureComponent { } } - _handleMoreInfoButtonClick = () => { + _handleMoreInfoButtonClick = (event: SyntheticMouseEvent<>) => { + event.preventDefault(); this.setState((state) => ({ showsMoreInfo: !state.showsMoreInfo })); }; @@ -159,9 +160,25 @@ class MetaInfoPanelImpl extends React.PureComponent { _renderMoreInfo() { return ( -
- {this.props.profileExtraInfo.map(this._renderMoreInfoSection)} -
+
+ + + {this.state.showsMoreInfo ? 'Show Less' : 'Show More'} + + +
+ {this.props.profileExtraInfo.map(this._renderMoreInfoSection)} +
+
); } @@ -448,28 +465,9 @@ class MetaInfoPanelImpl extends React.PureComponent { {profilerOverhead ? ( ) : null} - {this.props.profileExtraInfo.length !== 0 ? ( -
- - - - {this._renderMoreInfo()} -
- ) : null} + {this.props.profileExtraInfo.length !== 0 + ? this._renderMoreInfo() + : null} ); } @@ -507,7 +505,7 @@ function _formatDate(timestamp: number): string { return timestampDate; } -export const MetaInfoPanel = explicitConnect<{||}, OwnProps, DispatchProps>({ +export const MetaInfoPanel = explicitConnect<{||}, StateProps, DispatchProps>({ mapStateToProps: (state) => ({ profile: getProfile(state), symbolicationStatus: getSymbolicationStatus(state), diff --git a/src/test/components/MenuButtons.test.js b/src/test/components/MenuButtons.test.js index 7f63be7edc..1d157b5eb5 100644 --- a/src/test/components/MenuButtons.test.js +++ b/src/test/components/MenuButtons.test.js @@ -522,7 +522,7 @@ describe('app/MenuButtons', function () { const { displayMetaInfoPanel } = await setupForMetaInfoPanel(profile); await displayMetaInfoPanel(); - expect(screen.queryByText('Show More')).not.toBeInTheDocument(); + expect(screen.queryByText('Show more')).not.toBeInTheDocument(); }); it('with more extra info, opens more info section if clicked', async () => { @@ -562,7 +562,7 @@ describe('app/MenuButtons', function () { const { displayMetaInfoPanel } = await setupForMetaInfoPanel(profile); await displayMetaInfoPanel(); - const summary = screen.getByText('Show More'); + const summary = screen.getByText('Show more'); fireFullClick(summary); const moreInfoPart = document.querySelector('.moreInfoPart'); expect(moreInfoPart).toMatchSnapshot(); From 3cc8b5f5edf52699d8fc41c988a09cf44db47919 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Fri, 30 Sep 2022 11:44:08 +0200 Subject: [PATCH 5/5] Active hover and active styles for the details fake button --- res/css/photon/button.css | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/res/css/photon/button.css b/res/css/photon/button.css index e81d53ba75..2727233739 100644 --- a/res/css/photon/button.css +++ b/res/css/photon/button.css @@ -28,11 +28,13 @@ opacity: 0.4; } -.photon-button:hover:enabled { +/* Note: we're using :not(:disabled) instead of :enabled so that this can apply + * to non-input elements too. */ +.photon-button:hover:not(:disabled) { background-color: var(--grey-90-a20); } -.photon-button:hover:active:enabled { +.photon-button:hover:active:not(:disabled) { background-color: var(--grey-90-a30); } @@ -50,11 +52,11 @@ color: #fff; } -.photon-button-primary:hover:enabled { +.photon-button-primary:hover:not(:disabled) { background-color: var(--blue-70); } -.photon-button-primary:hover:active:enabled { +.photon-button-primary:hover:active:not(:disabled) { background-color: var(--blue-80); } @@ -64,11 +66,11 @@ color: #fff; } -.photon-button-destructive:hover:enabled { +.photon-button-destructive:hover:not(:disabled) { background-color: var(--red-70); } -.photon-button-destructive:hover:active:enabled { +.photon-button-destructive:hover:active:not(:disabled) { background-color: var(--red-80); } @@ -78,11 +80,11 @@ background-color: transparent; } -.photon-button-ghost:hover:enabled { +.photon-button-ghost:hover:not(:disabled) { background-color: var(--grey-90-a10); } -.photon-button-ghost:hover:active:enabled { +.photon-button-ghost:hover:active:not(:disabled) { background-color: var(--grey-90-a20); }