chrome-devtools-frontend
Version:
Chrome DevTools UI
282 lines (223 loc) • 11.1 kB
text/typescript
// 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 * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';
import * as TimelineComponents from './components/components.js';
function nestedBreadcrumbs(): {
initialBreadcrumb: Trace.Types.File.Breadcrumb,
breadcrumb1: Trace.Types.File.Breadcrumb,
breadcrumb2: Trace.Types.File.Breadcrumb,
} {
const initialTraceWindow: Trace.Types.Timing.TraceWindowMicro = {
min: Trace.Types.Timing.Micro(1000),
max: Trace.Types.Timing.Micro(10000),
range: Trace.Types.Timing.Micro(9000),
};
const traceWindow1: Trace.Types.Timing.TraceWindowMicro = {
min: Trace.Types.Timing.Micro(3000),
max: Trace.Types.Timing.Micro(9000),
range: Trace.Types.Timing.Micro(6000),
};
const traceWindow2: Trace.Types.Timing.TraceWindowMicro = {
min: Trace.Types.Timing.Micro(4000),
max: Trace.Types.Timing.Micro(6000),
range: Trace.Types.Timing.Micro(2000),
};
const breadcrumb2: Trace.Types.File.Breadcrumb = {
window: traceWindow2,
child: null,
};
const breadcrumb1: Trace.Types.File.Breadcrumb = {
window: traceWindow1,
child: breadcrumb2,
};
const initialBreadcrumb: Trace.Types.File.Breadcrumb = {
window: initialTraceWindow,
child: breadcrumb1,
};
return {
initialBreadcrumb,
breadcrumb1,
breadcrumb2,
};
}
describe('Timeline breadcrumbs', () => {
it('can create breadcrumbs', () => {
const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();
TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);
const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);
crumbs.add(breadcrumb1.window);
crumbs.add(breadcrumb2.window);
assert.deepEqual(
TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),
[initialBreadcrumb, breadcrumb1, breadcrumb2]);
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);
});
it('can activate breadcrumbs', () => {
const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();
TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);
const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);
crumbs.add(breadcrumb1.window);
crumbs.add(breadcrumb2.window);
// Last added breadcrumb should be active
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);
// Make sure breadcrumb 1 can be actived
crumbs.setActiveBreadcrumb(breadcrumb1, {
removeChildBreadcrumbs: false,
updateVisibleWindow: true,
});
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb1);
// Make sure initial breadcrumb can be actived
crumbs.setActiveBreadcrumb(initialBreadcrumb, {
removeChildBreadcrumbs: false,
updateVisibleWindow: true,
});
assert.deepEqual(crumbs.activeBreadcrumb, initialBreadcrumb);
// No breadcrumb were removed
assert.deepEqual(
TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),
[initialBreadcrumb, breadcrumb1, breadcrumb2]);
});
it('can overwrite child breadcrumbs when a new one is added', () => {
const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();
TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);
const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);
crumbs.add(breadcrumb1.window);
crumbs.add(breadcrumb2.window);
// Last added breadcrumb should be active
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);
// Currently, breadcrumbs structure is:
// initialBreadcrumb -> breadcrumb1 -> breadcrumb2(activated)
assert.deepEqual(
TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),
[initialBreadcrumb, breadcrumb1, breadcrumb2]);
// In this test we want to check if the children of the activated breadcrumb will be overwrritten if a new one is added
// Make the initial breadcrumb active:
// initialBreadcrumb(activated) -> breadcrumb1 -> breadcrumb2
crumbs.setActiveBreadcrumb(initialBreadcrumb, {
removeChildBreadcrumbs: false,
updateVisibleWindow: true,
});
assert.deepEqual(crumbs.activeBreadcrumb, initialBreadcrumb);
// Add a new breadcrumb
const traceWindow4: Trace.Types.Timing.TraceWindowMicro = {
min: Trace.Types.Timing.Micro(2000),
max: Trace.Types.Timing.Micro(5000),
range: Trace.Types.Timing.Micro(3000),
};
const breadcrumb4: Trace.Types.File.Breadcrumb = {
window: traceWindow4,
child: null,
};
crumbs.add(traceWindow4);
// Breadcrumbs should look like this:
// initialBreadcrumb -> breadcrumb4
assert.deepEqual(
TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb), [initialBreadcrumb, breadcrumb4]);
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb4);
});
it('can remove breadcrumbs', () => {
const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();
TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);
const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);
crumbs.add(breadcrumb1.window);
crumbs.add(breadcrumb2.window);
assert.deepEqual(
TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),
[initialBreadcrumb, breadcrumb1, breadcrumb2]);
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);
crumbs.setActiveBreadcrumb(breadcrumb1, {
removeChildBreadcrumbs: true,
updateVisibleWindow: true,
});
assert.deepEqual(
TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb), [initialBreadcrumb, breadcrumb1]);
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb1);
});
it('can not create a breadcrumb equal to the parent breadcrumb', () => {
const {initialBreadcrumb} = nestedBreadcrumbs();
assert.throws(() => {
TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);
const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);
const equalTraceWindow: Trace.Types.Timing.TraceWindowMicro = {
min: initialBreadcrumb.window.min,
max: initialBreadcrumb.window.max,
range: initialBreadcrumb.window.range,
};
crumbs.add(equalTraceWindow);
}, 'Can not add a breadcrumb that is equal to or is outside of the parent breadcrumb TimeWindow');
});
it('can create breadcrumbs with equal start or end as the parent breadcrumb', () => {
const initialTraceWindow: Trace.Types.Timing.TraceWindowMicro = {
min: Trace.Types.Timing.Micro(1000),
max: Trace.Types.Timing.Micro(10000),
range: Trace.Types.Timing.Micro(9000),
};
TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialTraceWindow);
const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialTraceWindow);
const traceWindow1: Trace.Types.Timing.TraceWindowMicro = {
min: Trace.Types.Timing.Micro(1000),
max: Trace.Types.Timing.Micro(9000),
range: Trace.Types.Timing.Micro(8000),
};
const traceWindow2: Trace.Types.Timing.TraceWindowMicro = {
min: Trace.Types.Timing.Micro(3000),
max: Trace.Types.Timing.Micro(9000),
range: Trace.Types.Timing.Micro(6000),
};
crumbs.add(traceWindow1);
crumbs.add(traceWindow2);
const breadcrumb2: Trace.Types.File.Breadcrumb = {
window: traceWindow2,
child: null,
};
const breadcrumb1: Trace.Types.File.Breadcrumb = {
window: traceWindow1,
child: breadcrumb2,
};
const initialBreadcrumb: Trace.Types.File.Breadcrumb = {
window: initialTraceWindow,
child: breadcrumb1,
};
assert.deepEqual(
TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),
[initialBreadcrumb, breadcrumb1, breadcrumb2]);
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);
});
it('correctly sets the last breadrumb and trace bound window when a new initial breadcrumb is provided', () => {
const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();
TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);
const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);
crumbs.setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb);
assert.deepEqual(
TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),
[initialBreadcrumb, breadcrumb1, breadcrumb2]);
assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);
// Make sure the trace bounds were correctly set to the last breadcrumb bounds
assert.deepEqual(
TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);
// Make sure the TimelineVisibleWindow was correctly set to the last breadcrumb bounds
assert.deepEqual(
TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);
});
it('it will not update the trace window when activating a breadcrumb if the option is set to false', () => {
const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();
TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);
const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);
crumbs.setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb);
// Make sure the trace bounds were correctly set to the last breadcrumb bounds
assert.deepEqual(
TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);
// Now activate breadcrumb1, but tell it not to update the bounds
crumbs.setActiveBreadcrumb(breadcrumb1, {removeChildBreadcrumbs: false, updateVisibleWindow: false});
// The visible window is still breadcrumb2.
assert.deepEqual(
TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.timelineTraceWindow, breadcrumb2.window);
// Now activate breadcrumb1, but ask it to update the bounds this time
crumbs.setActiveBreadcrumb(breadcrumb1, {removeChildBreadcrumbs: false, updateVisibleWindow: true});
// Now the window has changed.
assert.deepEqual(
TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.timelineTraceWindow, breadcrumb1.window);
});
});