diff --git a/elements-sk/modules/tabs-sk/tabs-sk.ts b/elements-sk/modules/tabs-sk/tabs-sk.ts index f01de67..c92eae7 100644 --- a/elements-sk/modules/tabs-sk/tabs-sk.ts +++ b/elements-sk/modules/tabs-sk/tabs-sk.ts
@@ -108,7 +108,7 @@ } } - attributeChangedCallback(name: string, oldValue: any, newValue: any) { + attributeChangedCallback(_name: string, oldValue: any, newValue: any) { if (oldValue === newValue) { return; }
diff --git a/perf/modules/explore-simple-sk/explore-simple-sk.ts b/perf/modules/explore-simple-sk/explore-simple-sk.ts index 8d1d73b..3db98fc 100644 --- a/perf/modules/explore-simple-sk/explore-simple-sk.ts +++ b/perf/modules/explore-simple-sk/explore-simple-sk.ts
@@ -179,6 +179,8 @@ // max number of charts to show on a page const chartsPerPage = 11; +const HOVER_DEBOUNCE_MS = 100; + export interface ZoomWithDelta { zoom: CommitRange; delta: CommitNumber; @@ -597,6 +599,8 @@ private selectedAnomaly: Anomaly | null = null; + private hoverTimeout: number = -1; + // material UI private settingsDialog: MdDialog | null = null; @@ -1152,12 +1156,14 @@ // This action is treated as onChartMouseDown and not as // onChartSelect so the tooltip only closes. private onChartMouseDown(): void { + window.clearTimeout(this.hoverTimeout); this.closeTooltip(); } // Close the tooltip when moving away while hovering. // Tooltip stays if the data point has been selected (clicked-on) private onChartMouseOut(): void { + window.clearTimeout(this.hoverTimeout); if (!this.tooltipSelected) { this.closeTooltip(); } @@ -1165,34 +1171,35 @@ // onChartOver shows the tooltip whenever a user hovers their mouse // over a data point in the google chart - private async onChartOver({ detail }: CustomEvent<PlotShowTooltipEventDetails>): Promise<void> { + private onChartOver({ detail }: CustomEvent<PlotShowTooltipEventDetails>): void { + window.clearTimeout(this.hoverTimeout); const chart = this.googleChartPlot!.value!; - // Highlight the paramset corresponding to the trace being hovered on. if (this.paramset) { this.paramset!.highlight = fromKey(chart.getTraceName(detail.tableCol)); } - // do not show tooltip if tooltip is selected if (this.tooltipSelected) { return; } - const index = detail; - const commitPos = chart.getCommitPosition(index.tableRow); - const position = chart.getPositionByIndex(index); - const traceName = chart.getTraceName(index.tableCol); - const currentCommit = this.getCommitDetails(commitPos); - const prevCommit = this.getCommitDetails(this.getPreviousCommit(index.tableRow!, traceName)); - this.enableTooltip( - { - x: index.tableRow - (this.selectedRange?.begin || 0), - y: chart.getYValue(index), - xPos: position.x, - yPos: position.y, - name: chart.getTraceName(index.tableCol), - }, - [prevCommit, currentCommit], - false - ); + + this.hoverTimeout = window.setTimeout(() => { + const commitPos = chart.getCommitPosition(detail.tableRow); + const position = chart.getPositionByIndex(detail); + const traceName = chart.getTraceName(detail.tableCol); + const currentCommit = this.getCommitDetails(commitPos); + const prevCommit = this.getCommitDetails(this.getPreviousCommit(detail.tableRow!, traceName)); + this.enableTooltip( + { + x: detail.tableRow - (this.selectedRange?.begin || 0), + y: chart.getYValue(detail), + xPos: position.x, + yPos: position.y, + name: chart.getTraceName(detail.tableCol), + }, + [prevCommit, currentCommit], + false + ); + }, HOVER_DEBOUNCE_MS); } connectedCallback(): void {
diff --git a/perf/modules/explore-simple-sk/explore-simple-sk_test.ts b/perf/modules/explore-simple-sk/explore-simple-sk_test.ts index a3f0dd7..bc539d0 100644 --- a/perf/modules/explore-simple-sk/explore-simple-sk_test.ts +++ b/perf/modules/explore-simple-sk/explore-simple-sk_test.ts
@@ -1625,4 +1625,103 @@ assert.isTrue(dataServiceStub.calledOnce); }); }); + + describe('Hover Debouncing', () => { + let explore: ExploreSimpleSk; + let clock: sinon.SinonFakeTimers; + let enableTooltipStub: sinon.SinonStub; + + beforeEach(async () => { + fetchMock.get(/.*\/_\/initpage\/.*/, { + dataframe: { paramset: {} }, + }); + fetchMock.get('/_/login/status', { + email: 'someone@example.org', + roles: ['editor'], + }); + + explore = setUpElementUnderTest<ExploreSimpleSk>('explore-simple-sk')(); + await fetchMock.flush(true); + + clock = sinon.useFakeTimers(); + enableTooltipStub = sinon.stub(explore, 'enableTooltip'); + + (explore as any).googleChartPlot = { + value: { + getTraceName: () => 'trace1', + getCommitPosition: () => 100, + getPositionByIndex: () => ({ x: 10, y: 20 }), + getYValue: () => 15, + }, + }; + (explore as any).getCommitDetails = () => ({}); + (explore as any).getPreviousCommit = () => null; + }); + + afterEach(() => { + clock.restore(); + sinon.restore(); + }); + + it('debounces rapid hover events', () => { + const event = new CustomEvent('plot-data-mouseover', { + detail: { tableRow: 1, tableCol: 1 }, + }); + + // Trigger multiple hovers + explore['onChartOver'](event as any); + clock.tick(50); + explore['onChartOver'](event as any); + clock.tick(50); + explore['onChartOver'](event as any); + + assert.isFalse(enableTooltipStub.called, 'Should not be called before 100ms delay'); + + clock.tick(100); + assert.isTrue(enableTooltipStub.calledOnce, 'Should be called once after delay'); + }); + + it('cancels pending hover on mouseOut', () => { + const event = new CustomEvent('plot-data-mouseover', { + detail: { tableRow: 1, tableCol: 1 }, + }); + + explore['onChartOver'](event as any); + clock.tick(50); + + explore['onChartMouseOut'](); + clock.tick(100); + + assert.isFalse(enableTooltipStub.called, 'Pending hover should be cancelled'); + }); + + it('cancels pending hover on mouseDown', () => { + const event = new CustomEvent('plot-data-mouseover', { + detail: { tableRow: 1, tableCol: 1 }, + }); + + explore['onChartOver'](event as any); + clock.tick(50); + + explore['onChartMouseDown'](); + clock.tick(100); + + assert.isFalse(enableTooltipStub.called, 'Pending hover should be cancelled'); + }); + + it('does not trigger hover if tooltip is already selected', () => { + const event = new CustomEvent('plot-data-mouseover', { + detail: { tableRow: 1, tableCol: 1 }, + }); + + (explore as any).tooltipSelected = true; + explore['onChartOver'](event as any); + clock.tick(150); + + assert.isFalse( + enableTooltipStub.called, + 'Should not trigger hover logic when tooltip is selected' + ); + }); + }); });
diff --git a/perf/modules/report-page-sk/BUILD.bazel b/perf/modules/report-page-sk/BUILD.bazel index 34948e2..21861fb 100644 --- a/perf/modules/report-page-sk/BUILD.bazel +++ b/perf/modules/report-page-sk/BUILD.bazel
@@ -98,10 +98,3 @@ "//puppeteer-tests:util_ts_lib", ], ) - -ts_library( - name = "test_data_ts_lib", - srcs = ["test_data.ts"], - visibility = ["//visibility:public"], - deps = ["//perf/modules/json:index_ts_lib"], -)
diff --git a/perf/modules/report-page-sk/report-page-sk-demo.scss b/perf/modules/report-page-sk/report-page-sk-demo.scss index 8ee0990..03285fe 100644 --- a/perf/modules/report-page-sk/report-page-sk-demo.scss +++ b/perf/modules/report-page-sk/report-page-sk-demo.scss
@@ -1,6 +1,3 @@ @import '../../../elements-sk/modules/styles/table'; @import '../../../elements-sk/modules/styles/select'; @import '../../../elements-sk/modules/styles/buttons'; - -report-page-sk { -}
diff --git a/perf/modules/report-page-sk/report-page-sk.scss b/perf/modules/report-page-sk/report-page-sk.scss index 9e5a69c..17042c6 100644 --- a/perf/modules/report-page-sk/report-page-sk.scss +++ b/perf/modules/report-page-sk/report-page-sk.scss
@@ -12,34 +12,6 @@ margin-left: 0.5em; } } - #commits-dialog { - overflow: auto; - width: 45%; - padding: 16px; - border: solid var(--on-background) 1px; - color: var(--on-background); - background: var(--background); - - #closeIcon { - position: absolute; - right: 0; - top: 0; - margin: 0; - margin-right: 11px; - border: none; - padding: 5px; - cursor: pointer; - } - - .footer { - display: flex; - justify-content: right; - } - - li { - margin-top: 5px; - } - } .common-commits { padding-bottom: 16px;
diff --git a/perf/modules/report-page-sk/report-page-sk.ts b/perf/modules/report-page-sk/report-page-sk.ts index a116566..fa0843f 100644 --- a/perf/modules/report-page-sk/report-page-sk.ts +++ b/perf/modules/report-page-sk/report-page-sk.ts
@@ -27,7 +27,7 @@ // * whether it's been checked. // * the graph generated for it. // * beginning and end time ranges. -export interface AnomalyDataPoint { +interface AnomalyDataPoint { // The anomaly object that this tracker is maintaining anomaly: Anomaly; // Boolean field to track whether the given anomaly has been selected @@ -40,7 +40,7 @@ timerange: Timerange; } -export class AnomalyTracker { +class AnomalyTracker { // Internal map for anomalies private tracker: { [key: string]: AnomalyDataPoint }; @@ -100,14 +100,6 @@ return ret; } - - getTimerangeMap(): { [key: string]: Timerange } { - const map: { [key: string]: Timerange } = {}; - for (const anomalyId in this.tracker) { - map[anomalyId] = this.tracker[anomalyId].timerange; - } - return map; - } } export class ReportPageSk extends ElementSk { @@ -159,9 +151,7 @@ @x-axis-toggled=${ele.syncXAxisLabel} @range-changing-in-multi=${ele.syncExtendRangeOnSummaryBar} @selection-changing-in-multi=${ele.syncChartSelection} - @even-x-axis-spacing-changed=${ele.syncEvenXAxisSpacing} - @open-anomaly-chart=${(e: CustomEvent<Anomaly>) => - ele.anomaliesTable!.openAnomalyChartListener(e)}></div> + @even-x-axis-spacing-changed=${ele.syncEvenXAxisSpacing}></div> <div id="bottom-spacer"></div> `;
diff --git a/perf/modules/report-page-sk/test_data.ts b/perf/modules/report-page-sk/test_data.ts deleted file mode 100644 index a3601e3..0000000 --- a/perf/modules/report-page-sk/test_data.ts +++ /dev/null
@@ -1,90 +0,0 @@ -import { Anomaly, QueryConfig } from '../json'; - -export const anomalies: Anomaly[] = [ - { - id: '1', - test_path: 'internal.client.v8/x64/v8/JetStream2/maglev-future/async-fs/Average', - bug_id: 0, - start_revision: 95942, - end_revision: 95942, - is_improvement: false, - recovered: false, - state: '', - statistic: '', - units: 'score', - degrees_of_freedom: 0, - median_before_anomaly: 108.074, - median_after_anomaly: 102.443, - p_value: 0, - segment_size_after: 0, - segment_size_before: 0, - std_dev_before_anomaly: 0, - t_statistic: 0, - subscription_name: 'Dummy Perf Sheriff', - bug_component: 'ComponentA>SubComponentA', - bug_labels: ['Label1', 'Label2'], - bug_cc_emails: ['abcd@google.com'], - bisect_ids: [], - }, - { - id: '2', - test_path: 'internal.client.v8/x64/v8/JetStream2/maglev-future/async-fs/Wall-Time', - bug_id: 0, - start_revision: 95940, - end_revision: 95944, - is_improvement: false, - recovered: false, - state: '', - statistic: '', - units: '', - degrees_of_freedom: 0, - median_before_anomaly: 1854.3049999999998, - median_after_anomaly: 1953.7269999999999, - p_value: 0, - segment_size_after: 0, - segment_size_before: 0, - std_dev_before_anomaly: 0, - t_statistic: 0, - subscription_name: 'Dummy Perf Sheriff', - bug_component: 'ComponentB>SubComponentB>SubcomponentC', - bug_labels: ['Label1', 'Label2'], - bug_cc_emails: ['abcd@google.com'], - bisect_ids: [], - }, - { - id: '3', - test_path: 'internal.client.v8/x64/v8/JetStream2/maglev/async-fs/Average-Score', - bug_id: 0, - start_revision: 95944, - end_revision: 95945, - is_improvement: false, - recovered: false, - state: '', - statistic: '', - units: '', - degrees_of_freedom: 0, - median_before_anomaly: 46.2635, - median_after_anomaly: 48.7535, - p_value: 0, - segment_size_after: 0, - segment_size_before: 0, - std_dev_before_anomaly: 0, - t_statistic: 0, - subscription_name: 'Dummy Perf Sheriff', - bug_component: 'ComponentB>SubComponentB>SubcomponentC', - bug_labels: ['Label1', 'Label3'], - bug_cc_emails: ['abcd@google.com'], - bisect_ids: [], - }, -]; - -export const bugIdTitleMap = { - 123: 'Bug 123 Title', - 456: 'Bug 456 Title', -}; - -export const defaultConfig: QueryConfig = { - default_param_selections: null, - default_url_values: null, - include_params: null, -};
diff --git a/skottie/modules/helpers/availableFonts.ts b/skottie/modules/helpers/availableFonts.ts index 95b53d9..757e9be 100644 --- a/skottie/modules/helpers/availableFonts.ts +++ b/skottie/modules/helpers/availableFonts.ts
@@ -483,6 +483,90 @@ fStyle: 'Regular', fFamily: 'GochiHand', }, + + // These are manually curated GSF named variation instances. + // They all map to the same TTF (GoogleSansFlex.ttf) at load time. + { + fName: 'GoogleSansFlex-Thin', + fStyle: 'Thin', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-ThinItalic', + fStyle: 'Thin Italic', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-ExtraLight', + fStyle: 'ExtraLight', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-ExtraLightItalic', + fStyle: 'ExtraLight Italic', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-Light', + fStyle: 'Light', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-LightItalic', + fStyle: 'Light Italic', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-Medium', + fStyle: 'Medium', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-MediumItalic', + fStyle: 'Medium Italic', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-SemiBold', + fStyle: 'SemiBold', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-SemiBoldItalic', + fStyle: 'SemiBold Italic', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-Bold', + fStyle: 'Bold', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-BoldItalic', + fStyle: 'Bold Italic', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-ExtraBold', + fStyle: 'ExtraBold', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-ExtraBoldItalic', + fStyle: 'ExtraBold Italic', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-Black', + fStyle: 'Black', + fFamily: 'GoogleSansFlex', + }, + { + fName: 'GoogleSansFlex-BlackItalic', + fStyle: 'Black Italic', + fFamily: 'GoogleSansFlex', + }, + { fName: 'GowunDodum-Regular', fStyle: 'Regular',