Add test to FlameChart#highlightEntry
Adding test coverage to FlameChart.ts
Bug: 1440169
Change-Id: Iad8d516c6cedb6b446aeeaba695d0e50d041fbd8
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/4573696
Reviewed-by: Andres Olivares <andoli@chromium.org>
Commit-Queue: Jack Franklin <jacktfranklin@chromium.org>
Auto-Submit: Jack Franklin <jacktfranklin@chromium.org>
diff --git a/front_end/ui/components/docs/performance_panel/BUILD.gn b/front_end/ui/components/docs/performance_panel/BUILD.gn
index 61ee7da..1d2b3e1 100644
--- a/front_end/ui/components/docs/performance_panel/BUILD.gn
+++ b/front_end/ui/components/docs/performance_panel/BUILD.gn
@@ -8,7 +8,6 @@
ts_library("ts") {
testonly = true
sources = [
- "FlameChartHelpers.ts",
"basic.ts",
"flamechart.ts",
"track_example.ts",
diff --git a/front_end/ui/components/docs/performance_panel/FlameChartHelpers.ts b/front_end/ui/components/docs/performance_panel/FlameChartHelpers.ts
deleted file mode 100644
index 0e09f59..0000000
--- a/front_end/ui/components/docs/performance_panel/FlameChartHelpers.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2023 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import * as PerfUI from '../../../legacy/components/perf_ui/perf_ui.js';
-import type * as SDK from '../../../../core/sdk/sdk.js';
-
-export class FakeProvider implements PerfUI.FlameChart.FlameChartDataProvider {
- minimumBoundary(): number {
- return 0;
- }
-
- totalTime(): number {
- return 100;
- }
-
- formatValue(value: number): string {
- return value.toString();
- }
-
- maxStackDepth(): number {
- return 3;
- }
-
- prepareHighlightedEntryInfo(_entryIndex: number): Element|null {
- return null;
- }
-
- canJumpToEntry(_entryIndex: number): boolean {
- return false;
- }
-
- entryTitle(entryIndex: number): string|null {
- return `Entry ${entryIndex}`;
- }
-
- entryFont(_entryIndex: number): string|null {
- return null;
- }
-
- entryColor(_entryIndex: number): string {
- return 'lightblue';
- }
-
- decorateEntry(): boolean {
- return false;
- }
-
- forceDecoration(_entryIndex: number): boolean {
- return false;
- }
-
- textColor(_entryIndex: number): string {
- return 'black';
- }
-
- navStartTimes(): Map<string, SDK.TracingModel.Event> {
- return new Map();
- }
-
- timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
- return PerfUI.FlameChart.FlameChartTimelineData.createEmpty();
- }
-}
diff --git a/front_end/ui/components/docs/performance_panel/flamechart.ts b/front_end/ui/components/docs/performance_panel/flamechart.ts
index 3026b09..3ef2528 100644
--- a/front_end/ui/components/docs/performance_panel/flamechart.ts
+++ b/front_end/ui/components/docs/performance_panel/flamechart.ts
@@ -3,12 +3,13 @@
// found in the LICENSE file.
import * as EnvironmentHelpers from '../../../../../test/unittests/front_end/helpers/EnvironmentHelpers.js';
+import * as TimelineHelpers from '../../../../../test/unittests/front_end/helpers/TimelineHelpers.js';
import * as TraceHelpers from '../../../../../test/unittests/front_end/helpers/TraceHelpers.js';
import * as PerfUI from '../../../legacy/components/perf_ui/perf_ui.js';
import * as ComponentSetup from '../../helpers/helpers.js';
+
import type * as Platform from '../../../../core/platform/platform.js';
import * as TraceEngine from '../../../../models/trace/trace.js';
-import {FakeProvider} from './FlameChartHelpers.js';
await EnvironmentHelpers.initializeGlobalVars();
await ComponentSetup.ComponentServerSetup.setup();
@@ -17,7 +18,7 @@
* Render a basic flame chart with 3 events on the same level
**/
function renderExample1() {
- class FakeProviderWithBasicEvents extends FakeProvider {
+ class FakeProviderWithBasicEvents extends TimelineHelpers.FakeFlameChartProvider {
override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
return PerfUI.FlameChart.FlameChartTimelineData.create({
entryLevels: [1, 1, 1],
@@ -58,7 +59,7 @@
* Render a flame chart with main thread long events to stripe and a warning triangle.
**/
function renderExample2() {
- class FakeProviderWithLongTasksForStriping extends FakeProvider {
+ class FakeProviderWithLongTasksForStriping extends TimelineHelpers.FakeFlameChartProvider {
override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
return PerfUI.FlameChart.FlameChartTimelineData.create({
entryLevels: [1, 1, 2],
diff --git a/front_end/ui/legacy/components/perf_ui/FlameChart.ts b/front_end/ui/legacy/components/perf_ui/FlameChart.ts
index 22e8fde..893e355 100644
--- a/front_end/ui/legacy/components/perf_ui/FlameChart.ts
+++ b/front_end/ui/legacy/components/perf_ui/FlameChart.ts
@@ -97,7 +97,7 @@
private canvas: HTMLCanvasElement;
private entryInfo: HTMLElement;
private readonly markerHighlighElement: HTMLElement;
- private readonly highlightElement: HTMLElement;
+ readonly highlightElement: HTMLElement;
private readonly selectedElement: HTMLElement;
private rulerEnabled: boolean;
private barHeight: number;
diff --git a/test/unittests/front_end/helpers/TimelineHelpers.ts b/test/unittests/front_end/helpers/TimelineHelpers.ts
index fd6d753..d5b9eb1 100644
--- a/test/unittests/front_end/helpers/TimelineHelpers.ts
+++ b/test/unittests/front_end/helpers/TimelineHelpers.ts
@@ -4,6 +4,7 @@
import * as SDK from '../../../../front_end/core/sdk/sdk.js';
import type * as TimelineModel from '../../../../front_end/models/timeline_model/timeline_model.js';
+import * as PerfUI from '../../../../front_end/ui/legacy/components/perf_ui/perf_ui.js';
import type * as TraceEngine from '../../../../front_end/models/trace/trace.js';
import * as Timeline from '../../../../front_end/panels/timeline/timeline.js';
import {loadTraceEventsLegacyEventPayload} from './TraceHelpers.js';
@@ -127,3 +128,61 @@
performanceModel,
};
}
+
+export class FakeFlameChartProvider implements PerfUI.FlameChart.FlameChartDataProvider {
+ minimumBoundary(): number {
+ return 0;
+ }
+
+ totalTime(): number {
+ return 100;
+ }
+
+ formatValue(value: number): string {
+ return value.toString();
+ }
+
+ maxStackDepth(): number {
+ return 3;
+ }
+
+ prepareHighlightedEntryInfo(_entryIndex: number): Element|null {
+ return null;
+ }
+
+ canJumpToEntry(_entryIndex: number): boolean {
+ return false;
+ }
+
+ entryTitle(entryIndex: number): string|null {
+ return `Entry ${entryIndex}`;
+ }
+
+ entryFont(_entryIndex: number): string|null {
+ return null;
+ }
+
+ entryColor(_entryIndex: number): string {
+ return 'lightblue';
+ }
+
+ decorateEntry(): boolean {
+ return false;
+ }
+
+ forceDecoration(_entryIndex: number): boolean {
+ return false;
+ }
+
+ textColor(_entryIndex: number): string {
+ return 'black';
+ }
+
+ navStartTimes(): Map<string, SDK.TracingModel.Event> {
+ return new Map();
+ }
+
+ timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
+ return PerfUI.FlameChart.FlameChartTimelineData.createEmpty();
+ }
+}
diff --git a/test/unittests/front_end/ui/legacy/components/perf_ui/FlameChart_test.ts b/test/unittests/front_end/ui/legacy/components/perf_ui/FlameChart_test.ts
index 1c11b90..63cc96a 100644
--- a/test/unittests/front_end/ui/legacy/components/perf_ui/FlameChart_test.ts
+++ b/test/unittests/front_end/ui/legacy/components/perf_ui/FlameChart_test.ts
@@ -3,10 +3,16 @@
// found in the LICENSE file.
import * as TraceEngine from '../../../../../../../front_end/models/trace/trace.js';
+import type * as Platform from '../../../../../../../front_end/core/platform/platform.js';
+import type * as Common from '../../../../../../../front_end/core/common/common.js';
+import {FakeFlameChartProvider} from '../../../../helpers/TimelineHelpers.js';
+import {MockFlameChartDelegate} from '../../../../helpers/TraceHelpers.js';
+import {renderElementIntoDOM} from '../../../../helpers/DOMHelpers.js';
import * as PerfUI from '../../../../../../../front_end/ui/legacy/components/perf_ui/perf_ui.js';
+import {describeWithEnvironment} from '../../../../helpers/EnvironmentHelpers.js';
const {assert} = chai;
-describe('FlameChart', () => {
+describeWithEnvironment('FlameChart', () => {
it('sorts decorations, putting candy striping before warning triangles', async () => {
const decorations: PerfUI.FlameChart.FlameChartDecoration[] = [
{type: 'WARNING_TRIANGLE'},
@@ -18,4 +24,81 @@
{type: 'WARNING_TRIANGLE'},
]);
});
+
+ let chartInstance: PerfUI.FlameChart.FlameChart|null = null;
+
+ afterEach(() => {
+ if (chartInstance) {
+ chartInstance.detach();
+ }
+ });
+
+ describe('highlightEntry', () => {
+ function renderChart(chart: PerfUI.FlameChart.FlameChart): void {
+ const container = document.createElement('div');
+ renderElementIntoDOM(container);
+ chart.markAsRoot();
+ chart.setWindowTimes(0, 100);
+ chart.show(container);
+ chart.update();
+ }
+
+ it('updates the chart to highlight the entry and dispatches an event', async () => {
+ class FakeProvider extends FakeFlameChartProvider {
+ override entryColor(_entryIndex: number): string {
+ return 'red';
+ }
+
+ override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
+ return PerfUI.FlameChart.FlameChartTimelineData.create({
+ entryLevels: [1, 1, 1],
+ entryStartTimes: [5, 60, 80],
+ entryTotalTimes: [50, 10, 10],
+ groups: [{
+ name: 'Test Group' as Platform.UIString.LocalizedString,
+ startLevel: 1,
+ style: {
+ height: 17,
+ padding: 4,
+ collapsible: false,
+ color: 'black',
+ backgroundColor: 'grey',
+ nestingLevel: 0,
+ itemsHeight: 17,
+ },
+ }],
+ });
+ }
+ }
+
+ const provider = new FakeProvider();
+ const delegate = new MockFlameChartDelegate();
+ chartInstance = new PerfUI.FlameChart.FlameChart(provider, delegate);
+ renderChart(chartInstance);
+
+ const highlightedEventListener = sinon.stub();
+ chartInstance.addEventListener(PerfUI.FlameChart.Events.EntryHighlighted, highlightedEventListener);
+
+ // Nothing highlighted, so the highlightElement should be hidden.
+ assert.isTrue(chartInstance.highlightElement.classList.contains('hidden'));
+
+ const entryIndexToHighlight = 2;
+ chartInstance.highlightEntry(entryIndexToHighlight);
+
+ // Ensure that the highlighted div is positioned. We cannot assert exact
+ // pixels due to differences in screen sizes and resolution across
+ // machines, but we can ensure that they have all been set.
+ assert.isDefined(chartInstance.highlightElement.style.height);
+ assert.isDefined(chartInstance.highlightElement.style.top);
+ assert.isDefined(chartInstance.highlightElement.style.left);
+ assert.isDefined(chartInstance.highlightElement.style.width);
+ // And that it is not hidden.
+ assert.isFalse(chartInstance.highlightElement.classList.contains('hidden'));
+
+ // Ensure that the event listener was called with the right index
+ assert.strictEqual(highlightedEventListener.callCount, 1);
+ const event = highlightedEventListener.args[0][0] as Common.EventTarget.EventTargetEvent<number>;
+ assert.strictEqual(event.data, entryIndexToHighlight);
+ });
+ });
});