UNPKG

chrome-devtools-frontend

Version:
126 lines (113 loc) 6.06 kB
// 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 Trace from '../../../models/trace/trace.js'; import {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js'; import {TraceLoader} from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as Timeline from '../timeline.js'; function initTrackAppender( flameChartData: PerfUI.FlameChart.FlameChartTimelineData, parsedTrace: Trace.Handlers.Types.ParsedTrace, entryData: Trace.Types.Events.Event[], entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[], ): Timeline.InteractionsTrackAppender.InteractionsTrackAppender { const entityMapper = new Timeline.Utils.EntityMapper.EntityMapper(parsedTrace); const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender( flameChartData, parsedTrace, entryData, entryTypeByLevel, entityMapper); return compatibilityTracksAppender.interactionsTrackAppender(); } describeWithEnvironment('InteractionsTrackAppender', function() { async function renderTrackAppender(context: Mocha.Suite|Mocha.Context, trace: string): Promise<{ entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[], flameChartData: PerfUI.FlameChart.FlameChartTimelineData, interactionsTrackAppender: Timeline.InteractionsTrackAppender.InteractionsTrackAppender, entryData: Trace.Types.Events.Event[], parsedTrace: Readonly<Trace.Handlers.Types.ParsedTrace>, }> { const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = []; const entryData: Trace.Types.Events.Event[] = []; const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); const {parsedTrace} = await TraceLoader.traceEngine(context, trace); const interactionsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); interactionsTrackAppender.appendTrackAtLevel(0); return { entryTypeByLevel, parsedTrace, flameChartData, interactionsTrackAppender, entryData, }; } describe('appendTrackAtLevel', function() { it('marks all levels used by the track with the `TrackAppender` type', async function() { const {entryTypeByLevel} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); // All events fit on the top level assert.lengthOf(entryTypeByLevel, 1); assert.deepEqual(entryTypeByLevel, [ Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER, ]); }); it('takes over no levels if there are no interactions', async function() { // animation trace has no interactions in it. const {entryTypeByLevel} = await renderTrackAppender(this, 'animation.json.gz'); assert.lengthOf(entryTypeByLevel, 0); }); it('only shows the top level interactions', async function() { const {entryData, parsedTrace} = await renderTrackAppender(this, 'nested-interactions.json.gz'); assert.strictEqual(entryData.length, parsedTrace.UserInteractions.interactionEventsWithNoNesting.length); }); it('creates a flamechart group', async function() { const {flameChartData} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); assert.lengthOf(flameChartData.groups, 1); assert.strictEqual(flameChartData.groups[0].name, 'Interactions'); }); it('adds all interactions with the correct start times', async function() { const {flameChartData, parsedTrace, entryData} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); const events = parsedTrace.UserInteractions.interactionEventsWithNoNesting; for (const event of events) { const markerIndex = entryData.indexOf(event); assert.exists(markerIndex); assert.strictEqual(flameChartData.entryStartTimes[markerIndex], Trace.Helpers.Timing.microToMilli(event.ts)); } }); it('adds total times correctly', async function() { const {flameChartData, parsedTrace, entryData} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); const events = parsedTrace.UserInteractions.interactionEventsWithNoNesting; for (const event of events) { const markerIndex = entryData.indexOf(event); assert.exists(markerIndex); const expectedTotalTimeForEvent = Trace.Helpers.Timing.microToMilli((event.dur || 0) as Trace.Types.Timing.Micro); assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], expectedTotalTimeForEvent); } }); }); it('candy-stripes and adds warning triangles to long interactions', async function() { const {parsedTrace, flameChartData, entryData} = await renderTrackAppender(this, 'one-second-interaction.json.gz'); const longInteraction = parsedTrace.UserInteractions.longestInteractionEvent; if (!longInteraction) { throw new Error('Could not find longest interaction'); } const entryIndex = entryData.indexOf(longInteraction); const decorationsForEntry = flameChartData.entryDecorations[entryIndex]; assert.deepEqual(decorationsForEntry, [ { type: PerfUI.FlameChart.FlameChartDecorationType.CANDY, startAtTime: Trace.Types.Timing.Micro(200_000), endAtTime: longInteraction.processingEnd, }, { type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE, customEndTime: longInteraction.processingEnd, }, ]); }); it('does not candy-stripe interactions less than 200ms', async function() { const {flameChartData} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); // None of the interactions are over 200ms, so we do not expect to see any decorations assert.lengthOf(flameChartData.entryDecorations, 0); }); });