Add timing types to TimelineOverviewCalculator

This CL updates the TimelineOverviewCalculator by moving it into its own
file, and changing its types from `number` to the `MilliSeconds` type.
This is important because the trace engine works primarily in
microseconds, so if we just use the `number` type we could easily get
into a confusing world where we are passing round numbers in different
units.

Bug: 1464206
Change-Id: I439c120c83950c2ca2cfa0c892b9f9065359dba7
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/4777912
Reviewed-by: Nancy Li <nancyly@chromium.org>
Commit-Queue: Jack Franklin <jacktfranklin@chromium.org>
This commit is contained in:
Jack Franklin
2023-08-16 09:07:39 +00:00
committed by Devtools-frontend LUCI CQ
parent 76dc7d12fe
commit 5d07f613bd
14 changed files with 160 additions and 127 deletions
+1
View File
@@ -2030,6 +2030,7 @@ grd_files_debug_sources = [
"front_end/ui/legacy/components/perf_ui/OverviewGrid.js",
"front_end/ui/legacy/components/perf_ui/PieChart.js",
"front_end/ui/legacy/components/perf_ui/TimelineGrid.js",
"front_end/ui/legacy/components/perf_ui/TimelineOverviewCalculator.js",
"front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.js",
"front_end/ui/legacy/components/perf_ui/chartViewport.css.legacy.js",
"front_end/ui/legacy/components/perf_ui/filmStripView.css.legacy.js",
+23 -13
View File
@@ -4,9 +4,10 @@
import type * as Common from '../../core/common/common.js';
import * as SDK from '../../core/sdk/sdk.js';
import * as TraceEngine from '../../models/trace/trace.js';
import * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js';
import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';
import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';
import * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js';
import {NetworkLogView} from './NetworkLogView.js';
import {NetworkTimeBoundary} from './NetworkTimeCalculator.js';
@@ -102,8 +103,8 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie
this.onResize();
}
override calculator(): PerfUI.TimelineOverviewPane.TimelineOverviewCalculator {
return super.calculator() as PerfUI.TimelineOverviewPane.TimelineOverviewCalculator;
override calculator(): PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator {
return super.calculator() as PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator;
}
override onResize(): void {
@@ -147,7 +148,10 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie
this.span *= 1.25;
}
calculator.setBounds(calculator.minimumBoundary(), calculator.minimumBoundary() + this.span);
calculator.setBounds(
calculator.minimumBoundary(),
TraceEngine.Types.Timing.MilliSeconds(calculator.minimumBoundary() + this.span));
this.lastBoundary = new NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());
}
@@ -172,8 +176,8 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie
if (endTime === Number.MAX_VALUE) {
endTime = calculator.maximumBoundary();
}
const startX = calculator.computePosition(startTime);
const endX = calculator.computePosition(endTime) + 1;
const startX = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(startTime));
const endX = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(endTime)) + 1;
context.fillRect(startX, y, endX - startX, _bandHeight);
context.strokeRect(startX, y, endX - startX, _bandHeight);
}
@@ -232,8 +236,10 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie
context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--legacy-selection-bg-color');
const start = timeRanges[0].start * 1000;
const end = timeRanges[0].end * 1000;
// The network overview works in seconds, but the calcululator deals in
// milliseconds, hence the multiplication by 1000.
const start = TraceEngine.Types.Timing.MilliSeconds(timeRanges[0].start * 1000);
const end = TraceEngine.Types.Timing.MilliSeconds(timeRanges[0].end * 1000);
context.fillRect(
calculator.computePosition(start) - borderSize, y - size / 2 - borderSize,
calculator.computePosition(end) - calculator.computePosition(start) + 1 + 2 * borderSize, size * borderSize);
@@ -246,8 +252,8 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie
ThemeSupport.ThemeSupport.instance().getComputedValue(RequestTimeRangeNameToColor[type]);
context.lineWidth = size;
const start = timeRanges[j].start * 1000;
const end = timeRanges[j].end * 1000;
const start = TraceEngine.Types.Timing.MilliSeconds(timeRanges[j].start * 1000);
const end = TraceEngine.Types.Timing.MilliSeconds(timeRanges[j].end * 1000);
context.moveTo(calculator.computePosition(start) - 0, y);
context.lineTo(calculator.computePosition(end) + 1, y);
context.stroke();
@@ -260,7 +266,9 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie
context.beginPath();
context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(NetworkLogView.getDCLEventColor());
for (let i = this.domContentLoadedEvents.length - 1; i >= 0; --i) {
const x = Math.round(calculator.computePosition(this.domContentLoadedEvents[i])) + 0.5;
const position =
calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(this.domContentLoadedEvents[i]));
const x = Math.round(position) + 0.5;
context.moveTo(x, 0);
context.lineTo(x, height);
}
@@ -269,7 +277,8 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie
context.beginPath();
context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(NetworkLogView.getLoadEventColor());
for (let i = this.loadEvents.length - 1; i >= 0; --i) {
const x = Math.round(calculator.computePosition(this.loadEvents[i])) + 0.5;
const position = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(this.loadEvents[i]));
const x = Math.round(position) + 0.5;
context.moveTo(x, 0);
context.lineTo(x, height);
}
@@ -279,7 +288,8 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie
context.lineWidth = 2;
context.beginPath();
context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--network-frame-divider-color');
const x = Math.round(calculator.computePosition(this.selectedFilmStripTime));
const timeInMilliseconds = TraceEngine.Types.Timing.MilliSeconds(this.selectedFilmStripTime);
const x = Math.round(calculator.computePosition(timeInMilliseconds));
context.moveTo(x, 0);
context.lineTo(x, height);
context.stroke();
+4 -4
View File
@@ -49,15 +49,13 @@ import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
import * as Search from '../search/search.js';
import {BlockedURLsPane} from './BlockedURLsPane.js';
import {Events, type RequestActivatedEvent} from './NetworkDataGridNode.js';
import {NetworkItemView} from './NetworkItemView.js';
import {NetworkLogView} from './NetworkLogView.js';
import {NetworkOverview} from './NetworkOverview.js';
import networkPanelStyles from './networkPanel.css.js';
import {NetworkSearchScope} from './NetworkSearchScope.js';
import {NetworkTransferTimeCalculator, type NetworkTimeCalculator} from './NetworkTimeCalculator.js';
import {type NetworkTimeCalculator, NetworkTransferTimeCalculator} from './NetworkTimeCalculator.js';
const UIStrings = {
/**
@@ -780,7 +778,9 @@ export class NetworkPanel extends UI.Panel.Panel implements UI.ContextMenu.Provi
const request = event.data;
this.calculator.updateBoundaries(request);
// FIXME: Unify all time units across the frontend!
this.overviewPane.setBounds(this.calculator.minimumBoundary() * 1000, this.calculator.maximumBoundary() * 1000);
this.overviewPane.setBounds(
TraceEngine.Types.Timing.MilliSeconds(this.calculator.minimumBoundary() * 1000),
TraceEngine.Types.Timing.MilliSeconds(this.calculator.maximumBoundary() * 1000));
this.networkOverview.updateRequest(request);
this.overviewPane.scheduleUpdate();
}
+1 -1
View File
@@ -58,7 +58,7 @@ export class TimelineMiniMap extends
this.#overviewComponent.reset();
}
setBounds(min: number, max: number): void {
setBounds(min: TraceEngine.Types.Timing.MilliSeconds, max: TraceEngine.Types.Timing.MilliSeconds): void {
this.#overviewComponent.setBounds(min, max);
}
+2 -1
View File
@@ -1098,7 +1098,8 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
if (model && this.performanceModel) {
this.performanceModel.addEventListener(Events.WindowChanged, this.onModelWindowChanged, this);
this.#minimapComponent.setBounds(
model.timelineModel().minimumRecordTime(), model.timelineModel().maximumRecordTime());
TraceEngine.Types.Timing.MilliSeconds(model.timelineModel().minimumRecordTime()),
TraceEngine.Types.Timing.MilliSeconds(model.timelineModel().maximumRecordTime()));
PerfUI.LineLevelProfile.Performance.instance().reset();
for (const profile of model.timelineModel().cpuProfiles()) {
PerfUI.LineLevelProfile.Performance.instance().appendCPUProfile(profile.cpuProfileData, profile.target);
@@ -4,6 +4,7 @@
import * as EnvironmentHelpers from '../../../../../test/unittests/front_end/helpers/EnvironmentHelpers.js';
import * as TraceLoader from '../../../../../test/unittests/front_end/helpers/TraceLoader.js';
import * as TraceEngine from '../../../../models/trace/trace.js';
import * as Timeline from '../../../../panels/timeline/timeline.js';
import * as ComponentSetup from '../../helpers/helpers.js';
@@ -28,7 +29,10 @@ async function renderMiniMap(containerSelector: string, options: {showMemory: bo
const models = await TraceLoader.TraceLoader.allModels(null, fileName);
minimap.setBounds(models.timelineModel.minimumRecordTime(), models.timelineModel.maximumRecordTime());
minimap.setBounds(
TraceEngine.Types.Timing.MilliSeconds(models.timelineModel.minimumRecordTime()),
TraceEngine.Types.Timing.MilliSeconds(models.timelineModel.maximumRecordTime()),
);
minimap.setWindowTimes(models.performanceModel.window().left, models.performanceModel.window().right);
minimap.setData({
traceParsedData: models.traceParsedData,
@@ -39,6 +39,7 @@ devtools_module("perf_ui") {
"OverviewGrid.ts",
"PieChart.ts",
"TimelineGrid.ts",
"TimelineOverviewCalculator.ts",
"TimelineOverviewPane.ts",
]
@@ -37,10 +37,9 @@ import * as UI from '../../legacy.js';
import * as ThemeSupport from '../../theme_support/theme_support.js';
import {ChartViewport, type ChartViewportDelegate} from './ChartViewport.js';
import {TimelineGrid, type Calculator} from './TimelineGrid.js';
import flameChartStyles from './flameChart.css.legacy.js';
import {DEFAULT_FONT_SIZE, getFontFamilyForCanvas} from './Font.js';
import {type Calculator, TimelineGrid} from './TimelineGrid.js';
const UIStrings = {
/**
@@ -2090,20 +2089,20 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin<EventTypes, type
return this.dataProvider.formatValue(value - this.zeroTime(), precision);
}
maximumBoundary(): number {
return this.chartViewport.windowRightTime();
maximumBoundary(): TraceEngine.Types.Timing.MilliSeconds {
return TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.windowRightTime());
}
minimumBoundary(): number {
return this.chartViewport.windowLeftTime();
minimumBoundary(): TraceEngine.Types.Timing.MilliSeconds {
return TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.windowLeftTime());
}
zeroTime(): number {
return this.dataProvider.minimumBoundary();
zeroTime(): TraceEngine.Types.Timing.MilliSeconds {
return TraceEngine.Types.Timing.MilliSeconds(this.dataProvider.minimumBoundary());
}
boundarySpan(): number {
return this.maximumBoundary() - this.minimumBoundary();
boundarySpan(): TraceEngine.Types.Timing.MilliSeconds {
return TraceEngine.Types.Timing.MilliSeconds(this.maximumBoundary() - this.minimumBoundary());
}
}
@@ -31,11 +31,12 @@
import * as Common from '../../../../core/common/common.js';
import * as i18n from '../../../../core/i18n/i18n.js';
import * as Platform from '../../../../core/platform/platform.js';
import * as TraceEngine from '../../../../models/trace/trace.js';
import * as UI from '../../legacy.js';
import * as ThemeSupport from '../../theme_support/theme_support.js';
import {TimelineGrid, type Calculator} from './TimelineGrid.js';
import overviewGridStyles from './overviewGrid.css.legacy.js';
import {type Calculator, TimelineGrid} from './TimelineGrid.js';
const UIStrings = {
/**
@@ -393,8 +394,10 @@ export class Window extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
if (!this.calculator) {
return;
}
const startValue = this.calculator.formatValue(this.getRawSliderValue(/* leftSlider */ true));
const endValue = this.calculator.formatValue(this.getRawSliderValue(/* leftSlider */ false));
const startValue = this.calculator.formatValue(
TraceEngine.Types.Timing.MilliSeconds(this.getRawSliderValue(/* leftSlider */ true)));
const endValue = this.calculator.formatValue(
TraceEngine.Types.Timing.MilliSeconds(this.getRawSliderValue(/* leftSlider */ false)));
UI.ARIAUtils.setAriaValueText(this.leftResizeElement, String(startValue));
UI.ARIAUtils.setAriaValueText(this.rightResizeElement, String(endValue));
}
@@ -0,0 +1,81 @@
// 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 i18n from '../../../../core/i18n/i18n.js';
import * as TraceEngine from '../../../../models/trace/trace.js';
import {type Calculator} from './TimelineGrid.js';
export class TimelineOverviewCalculator implements Calculator {
#minimumBoundary: TraceEngine.Types.Timing.MilliSeconds = TraceEngine.Types.Timing.MilliSeconds(0);
#maximumBoundary: TraceEngine.Types.Timing.MilliSeconds = TraceEngine.Types.Timing.MilliSeconds(100);
private workingArea!: number;
private navStartTimes?: readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[];
computePosition(time: TraceEngine.Types.Timing.MilliSeconds): number {
return (time - this.#minimumBoundary) / this.boundarySpan() * this.workingArea;
}
positionToTime(position: number): number {
return position / this.workingArea * this.boundarySpan() + this.#minimumBoundary;
}
setBounds(
minimumBoundary: TraceEngine.Types.Timing.MilliSeconds,
maximumBoundary: TraceEngine.Types.Timing.MilliSeconds): void {
this.#minimumBoundary = minimumBoundary;
this.#maximumBoundary = maximumBoundary;
}
setNavStartTimes(navStartTimes: readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[]): void {
this.navStartTimes = navStartTimes;
}
setDisplayWidth(clientWidth: number): void {
this.workingArea = clientWidth;
}
reset(): void {
this.setBounds(
TraceEngine.Types.Timing.MilliSeconds(0),
TraceEngine.Types.Timing.MilliSeconds(100),
);
}
formatValue(value: number, precision?: number): string {
// If there are nav start times the value needs to be remapped.
if (this.navStartTimes) {
// Find the latest possible nav start time which is considered earlier
// than the value passed through.
for (let i = this.navStartTimes.length - 1; i >= 0; i--) {
const startTimeMilliseconds = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(
this.navStartTimes[i].ts,
);
if (value > startTimeMilliseconds) {
value -= (startTimeMilliseconds - this.zeroTime());
break;
}
}
}
return i18n.TimeUtilities.preciseMillisToString(value - this.zeroTime(), precision);
}
maximumBoundary(): TraceEngine.Types.Timing.MilliSeconds {
return this.#maximumBoundary;
}
minimumBoundary(): TraceEngine.Types.Timing.MilliSeconds {
return this.#minimumBoundary;
}
zeroTime(): TraceEngine.Types.Timing.MilliSeconds {
return this.#minimumBoundary;
}
boundarySpan(): TraceEngine.Types.Timing.MilliSeconds {
return TraceEngine.Types.Timing.MilliSeconds(this.#maximumBoundary - this.#minimumBoundary);
}
}
@@ -29,12 +29,11 @@
*/
import * as Common from '../../../../core/common/common.js';
import * as i18n from '../../../../core/i18n/i18n.js';
import * as TraceEngine from '../../../../models/trace/trace.js';
import * as UI from '../../legacy.js';
import {Events as OverviewGridEvents, OverviewGrid, type WindowChangedWithPositionEvent} from './OverviewGrid.js';
import {type Calculator} from './TimelineGrid.js';
import {TimelineOverviewCalculator} from './TimelineOverviewCalculator.js';
import timelineOverviewInfoStyles from './timelineOverviewInfo.css.js';
export class TimelineOverviewPane extends Common.ObjectWrapper.eventMixin<EventTypes, typeof UI.Widget.VBox>(
@@ -141,7 +140,9 @@ export class TimelineOverviewPane extends Common.ObjectWrapper.eventMixin<EventT
this.update();
}
setBounds(minimumBoundary: number, maximumBoundary: number): void {
setBounds(
minimumBoundary: TraceEngine.Types.Timing.MilliSeconds,
maximumBoundary: TraceEngine.Types.Timing.MilliSeconds): void {
this.overviewCalculator.setBounds(minimumBoundary, maximumBoundary);
this.overviewGrid.setResizeEnabled(true);
this.cursorEnabled = true;
@@ -178,7 +179,7 @@ export class TimelineOverviewPane extends Common.ObjectWrapper.eventMixin<EventT
const filteredMarkers = new Map<number, Element>();
for (const time of this.markers.keys()) {
const marker = this.markers.get(time) as HTMLElement;
const position = Math.round(this.overviewCalculator.computePosition(time));
const position = Math.round(this.overviewCalculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(time)));
// Limit the number of markers to one per pixel.
if (filteredMarkers.has(position)) {
continue;
@@ -269,78 +270,6 @@ export type EventTypes = {
[Events.WindowChanged]: WindowChangedEvent,
};
export class TimelineOverviewCalculator implements Calculator {
private minimumBoundaryInternal!: number;
private maximumBoundaryInternal!: number;
private workingArea!: number;
private navStartTimes?: readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[];
constructor() {
this.reset();
}
computePosition(time: number): number {
return (time - this.minimumBoundaryInternal) / this.boundarySpan() * this.workingArea;
}
positionToTime(position: number): number {
return position / this.workingArea * this.boundarySpan() + this.minimumBoundaryInternal;
}
setBounds(minimumBoundary: number, maximumBoundary: number): void {
this.minimumBoundaryInternal = minimumBoundary;
this.maximumBoundaryInternal = maximumBoundary;
}
setNavStartTimes(navStartTimes: readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[]): void {
this.navStartTimes = navStartTimes;
}
setDisplayWidth(clientWidth: number): void {
this.workingArea = clientWidth;
}
reset(): void {
this.setBounds(0, 100);
}
formatValue(value: number, precision?: number): string {
// If there are nav start times the value needs to be remapped.
if (this.navStartTimes) {
// Find the latest possible nav start time which is considered earlier
// than the value passed through.
for (let i = this.navStartTimes.length - 1; i >= 0; i--) {
const startTimeMilliseconds = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(
this.navStartTimes[i].ts,
);
if (value > startTimeMilliseconds) {
value -= (startTimeMilliseconds - this.zeroTime());
break;
}
}
}
return i18n.TimeUtilities.preciseMillisToString(value - this.zeroTime(), precision);
}
maximumBoundary(): number {
return this.maximumBoundaryInternal;
}
minimumBoundary(): number {
return this.minimumBoundaryInternal;
}
zeroTime(): number {
return this.minimumBoundaryInternal;
}
boundarySpan(): number {
return this.maximumBoundaryInternal - this.minimumBoundaryInternal;
}
}
export interface TimelineOverview {
show(parentElement: Element, insertBefore?: Element|null): void;
update(): void;
@@ -13,6 +13,7 @@ import * as NetworkPriorities from './NetworkPriorities.js';
import * as OverviewGrid from './OverviewGrid.js';
import * as PieChart from './PieChart.js';
import * as TimelineGrid from './TimelineGrid.js';
import * as TimelineOverviewCalculator from './TimelineOverviewCalculator.js';
import * as TimelineOverviewPane from './TimelineOverviewPane.js';
export {
@@ -27,5 +28,6 @@ export {
OverviewGrid,
PieChart,
TimelineGrid,
TimelineOverviewCalculator,
TimelineOverviewPane,
};
@@ -3,13 +3,12 @@
// found in the LICENSE file.
import type * as Common from '../../../../../front_end/core/common/common.js';
import * as Network from '../../../../../front_end/panels/network/network.js';
import type * as Platform from '../../../../../front_end/core/platform/platform.js';
import {assertNotNullOrUndefined} from '../../../../../front_end/core/platform/platform.js';
import * as SDK from '../../../../../front_end/core/sdk/sdk.js';
import * as Network from '../../../../../front_end/panels/network/network.js';
import * as Coordinator from '../../../../../front_end/ui/components/render_coordinator/render_coordinator.js';
import type * as PerfUI from '../../../../../front_end/ui/legacy/components/perf_ui/perf_ui.js';
import {assertNotNullOrUndefined} from '../../../../../front_end/core/platform/platform.js';
import {createTarget} from '../../helpers/EnvironmentHelpers.js';
import {describeWithMockConnection} from '../../helpers/MockConnection.js';
@@ -40,7 +39,8 @@ describeWithMockConnection('NetworkOverview', () => {
zeroTime: sinon.stub(),
boundarySpan: sinon.stub(),
};
networkOverview.setCalculator(calculator as unknown as PerfUI.TimelineOverviewPane.TimelineOverviewCalculator);
networkOverview.setCalculator(
calculator as unknown as PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator);
networkOverview.markAsRoot();
networkOverview.show(document.body);
const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
@@ -2,49 +2,51 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import type * as TraceEngine from '../../../../../../../front_end/models/trace/trace.js';
import * as TraceEngine from '../../../../../../../front_end/models/trace/trace.js';
import * as PerfUI from '../../../../../../../front_end/ui/legacy/components/perf_ui/perf_ui.js';
import {describeWithLocale} from '../../../../helpers/EnvironmentHelpers.js';
const {assert} = chai;
const {MilliSeconds} = TraceEngine.Types.Timing;
describeWithLocale('TimelineOverviewCalculator', () => {
it('can calculate pixels for a given time', async () => {
const calculator = new PerfUI.TimelineOverviewPane.TimelineOverviewCalculator();
const calculator = new PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator();
calculator.setDisplayWidth(200);
calculator.setBounds(0, 100);
calculator.setBounds(MilliSeconds(0), MilliSeconds(100));
assert.strictEqual(calculator.computePosition(50), 100);
assert.strictEqual(calculator.computePosition(MilliSeconds(50)), 100);
});
it('can calculate the time position for a pixel value', async () => {
const calculator = new PerfUI.TimelineOverviewPane.TimelineOverviewCalculator();
const calculator = new PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator();
calculator.setDisplayWidth(200);
calculator.setBounds(0, 100);
calculator.setBounds(MilliSeconds(0), MilliSeconds(100));
assert.strictEqual(calculator.positionToTime(100), 50);
});
it('formats time values', async () => {
const calculator = new PerfUI.TimelineOverviewPane.TimelineOverviewCalculator();
const calculator = new PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator();
calculator.setDisplayWidth(200);
calculator.setBounds(0, 100);
calculator.setBounds(MilliSeconds(0), MilliSeconds(100));
const result = calculator.formatValue(55.234);
assert.deepEqual(result, '55\u00A0ms');
});
it('formats time values with custom precision', async () => {
const calculator = new PerfUI.TimelineOverviewPane.TimelineOverviewCalculator();
const calculator = new PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator();
calculator.setDisplayWidth(200);
calculator.setBounds(0, 100);
calculator.setBounds(MilliSeconds(0), MilliSeconds(100));
const result = calculator.formatValue(55.234, 2);
assert.deepEqual(result, '55.23\u00A0ms');
});
it('adjusts times based on navigaton start times', async () => {
const calculator = new PerfUI.TimelineOverviewPane.TimelineOverviewCalculator();
const calculator = new PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator();
calculator.setDisplayWidth(200);
calculator.setBounds(0, 100);
calculator.setBounds(MilliSeconds(0), MilliSeconds(100));
const fakeNavStart = {
// TraceEngine events are in microseconds
ts: 100_000,
@@ -56,9 +58,9 @@ describeWithLocale('TimelineOverviewCalculator', () => {
});
it('returns the correct range', async () => {
const calculator = new PerfUI.TimelineOverviewPane.TimelineOverviewCalculator();
const calculator = new PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator();
calculator.setDisplayWidth(200);
calculator.setBounds(0, 100);
calculator.setBounds(MilliSeconds(0), MilliSeconds(100));
assert.strictEqual(calculator.boundarySpan(), 100);
});
});