Dedupe dom helpers in timeline tests.
Bug: 380878140
Test: npm run test:unit:ci
Change-Id: Iab5c0f14bdf9a6132c185f65b31e93e5f4e2d0a6
diff --git a/tools/winscope/src/app/components/timeline/expanded-timeline/default_timeline_row_component_test.ts b/tools/winscope/src/app/components/timeline/expanded-timeline/default_timeline_row_component_test.ts
index 6b87048..84ea67f 100644
--- a/tools/winscope/src/app/components/timeline/expanded-timeline/default_timeline_row_component_test.ts
+++ b/tools/winscope/src/app/components/timeline/expanded-timeline/default_timeline_row_component_test.ts
@@ -15,7 +15,7 @@
*/
import {DragDropModule} from '@angular/cdk/drag-drop';
-import {ComponentFixture, TestBed} from '@angular/core/testing';
+import {TestBed} from '@angular/core/testing';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatFormFieldModule} from '@angular/material/form-field';
@@ -28,15 +28,15 @@
import {Rect} from 'common/geometry/rect';
import {TimestampConverterUtils} from 'common/time/test_utils';
import {TimeRange} from 'common/time/time';
+import {DOMTestHelper} from 'test/unit/dom_test_utils';
import {waitToBeCalled} from 'test/unit/spy_utils';
import {TraceBuilder} from 'test/unit/trace_builder';
import {TraceType} from 'trace/trace_type';
import {DefaultTimelineRowComponent} from './default_timeline_row_component';
describe('DefaultTimelineRowComponent', () => {
- let fixture: ComponentFixture<DefaultTimelineRowComponent>;
let component: DefaultTimelineRowComponent;
- let htmlElement: HTMLElement;
+ let dom: DOMTestHelper<DefaultTimelineRowComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
@@ -54,9 +54,9 @@
],
declarations: [DefaultTimelineRowComponent],
}).compileComponents();
- fixture = TestBed.createComponent(DefaultTimelineRowComponent);
+ const fixture = TestBed.createComponent(DefaultTimelineRowComponent);
component = fixture.componentInstance;
- htmlElement = fixture.nativeElement;
+ dom = new DOMTestHelper(fixture, fixture.nativeElement);
});
it('can be created', () => {
@@ -65,14 +65,11 @@
it('can draw entries', async () => {
setTraceAndSelectionRange(10n, 110n);
-
const drawRectSpy = spyOn(
component.canvasDrawer,
'drawRect',
).and.callThrough();
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
const rectHeight = component.canvasDrawer.getScaledCanvasHeight();
const rectWidth = rectHeight;
@@ -106,11 +103,8 @@
it('can draw entries zoomed in', async () => {
setTraceAndSelectionRange(60n, 85n);
-
const drawRectSpy = spyOn(component.canvasDrawer, 'drawRect');
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
const rectHeight = component.canvasDrawer.getScaledCanvasHeight();
const rectWidth = rectHeight;
@@ -129,9 +123,7 @@
it('can draw hovering entry', async () => {
setTraceAndSelectionRange(10n, 110n);
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
const drawRectSpy = spyOn(
component.canvasDrawer,
@@ -154,9 +146,7 @@
);
component.getCanvas().dispatchEvent(event);
- fixture.detectChanges();
- await fixture.whenRenderingDone();
-
+ await dom.detectChangesAndRenderingDone();
await Promise.all(waitPromises);
const rectHeight = component.canvasDrawer.getScaledCanvasHeight();
@@ -178,19 +168,14 @@
it('can draw correct entry on click of first entry', async () => {
setTraceAndSelectionRange(10n, 110n);
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
-
+ await dom.detectChangesAndRenderingDone();
// 9 rect draws - 4 entry rects present + 4 for redraw + 1 for selected entry
await drawCorrectEntryOnClick(0, 10n, 9);
});
it('can draw correct entry on click of middle entry', async () => {
setTraceAndSelectionRange(10n, 110n);
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
const canvasWidth = Math.floor(
component.canvasDrawer.getScaledCanvasWidth() -
@@ -204,9 +189,7 @@
it('can draw correct entry on click when timeline zoomed in near start', async () => {
setTraceAndSelectionRange(10n, 15n);
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
const canvasWidth = Math.floor(
component.canvasDrawer.getScaledCanvasWidth() -
@@ -220,9 +203,7 @@
it('can draw correct entry on click when timeline zoomed in near end', async () => {
setTraceAndSelectionRange(60n, 80n);
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
const canvasWidth = Math.floor(
component.canvasDrawer.getScaledCanvasWidth() -
@@ -236,20 +217,15 @@
it('emits scroll event', async () => {
setTraceAndSelectionRange(10n, 110n);
- fixture.detectChanges();
- await fixture.whenRenderingDone();
-
+ await dom.detectChangesAndRenderingDone();
const spy = spyOn(component.onScrollEvent, 'emit');
- htmlElement.dispatchEvent(new WheelEvent('wheel'));
- fixture.detectChanges();
+ dom.dispatchEvent(new WheelEvent('wheel'));
expect(spy).toHaveBeenCalled();
});
it('tracks mouse position', async () => {
setTraceAndSelectionRange(10n, 110n);
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
const spy = spyOn(component.onMouseXRatioUpdate, 'emit');
const canvas = assertDefined(component.canvasRef).nativeElement;
@@ -258,13 +234,13 @@
Object.defineProperty(mouseMoveEvent, 'target', {value: canvas});
Object.defineProperty(mouseMoveEvent, 'offsetX', {value: 100});
canvas.dispatchEvent(mouseMoveEvent);
- fixture.detectChanges();
+ dom.detectChanges();
expect(spy).toHaveBeenCalledWith(100 / canvas.offsetWidth);
const mouseLeaveEvent = new MouseEvent('mouseleave');
canvas.dispatchEvent(mouseLeaveEvent);
- fixture.detectChanges();
+ dom.detectChanges();
expect(spy).toHaveBeenCalledWith(undefined);
});
@@ -305,9 +281,7 @@
component.canvasDrawer.getScaledCanvasHeight() / 2,
);
component.getCanvas().dispatchEvent(event);
-
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
await Promise.all(waitPromises);
diff --git a/tools/winscope/src/app/components/timeline/expanded-timeline/expanded_timeline_component_test.ts b/tools/winscope/src/app/components/timeline/expanded-timeline/expanded_timeline_component_test.ts
index 8a59898..5b99659 100644
--- a/tools/winscope/src/app/components/timeline/expanded-timeline/expanded_timeline_component_test.ts
+++ b/tools/winscope/src/app/components/timeline/expanded-timeline/expanded_timeline_component_test.ts
@@ -16,7 +16,7 @@
import {DragDropModule} from '@angular/cdk/drag-drop';
import {ChangeDetectionStrategy} from '@angular/core';
-import {ComponentFixture, TestBed} from '@angular/core/testing';
+import {TestBed} from '@angular/core/testing';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatFormFieldModule} from '@angular/material/form-field';
@@ -28,6 +28,7 @@
import {TimelineData} from 'app/timeline_data';
import {assertDefined} from 'common/assert_utils';
import {TimestampConverterUtils} from 'common/time/test_utils';
+import {DOMTestHelper} from 'test/unit/dom_test_utils';
import {PropertyTreeBuilder} from 'test/unit/property_tree_builder';
import {TracesBuilder} from 'test/unit/traces_builder';
import {TracePosition} from 'trace/trace_position';
@@ -37,9 +38,8 @@
import {TransitionTimelineComponent} from './transition_timeline_component';
describe('ExpandedTimelineComponent', () => {
- let fixture: ComponentFixture<ExpandedTimelineComponent>;
let component: ExpandedTimelineComponent;
- let htmlElement: HTMLElement;
+ let dom: DOMTestHelper<ExpandedTimelineComponent>;
let timelineData: TimelineData;
const time10 = TimestampConverterUtils.makeRealTimestamp(10n);
const time11 = TimestampConverterUtils.makeRealTimestamp(11n);
@@ -72,9 +72,9 @@
set: {changeDetection: ChangeDetectionStrategy.Default},
})
.compileComponents();
- fixture = TestBed.createComponent(ExpandedTimelineComponent);
+ const fixture = TestBed.createComponent(ExpandedTimelineComponent);
component = fixture.componentInstance;
- htmlElement = fixture.nativeElement;
+ dom = new DOMTestHelper(fixture, fixture.nativeElement);
timelineData = new TimelineData();
const traces = new TracesBuilder()
.setEntries(TraceType.SURFACE_FLINGER, [{}])
@@ -133,21 +133,17 @@
});
it('renders all timelines', () => {
- fixture.detectChanges();
+ dom.detectChanges();
- const timelineElements = htmlElement.querySelectorAll(
- '.timeline.row single-timeline',
- );
+ const timelineElements = dom.findAll('.timeline.row single-timeline');
expect(timelineElements.length).toEqual(4);
- const transitionElement = htmlElement.querySelectorAll(
- '.timeline.row transition-timeline',
- );
+ const transitionElement = dom.findAll('.timeline.row transition-timeline');
expect(transitionElement.length).toEqual(1);
});
it('passes initial selectedEntry of correct type into each timeline', () => {
- fixture.detectChanges();
+ dom.detectChanges();
const singleTimelines = assertDefined(component.singleTimelines);
expect(singleTimelines.length).toBe(4);
@@ -173,7 +169,7 @@
assertDefined(component.timelineData).setPosition(
TracePosition.fromTimestamp(time11),
);
- fixture.detectChanges();
+ dom.detectChanges();
const singleTimelines = assertDefined(component.singleTimelines);
expect(singleTimelines.length).toBe(4);
diff --git a/tools/winscope/src/app/components/timeline/expanded-timeline/transition_timeline_component_test.ts b/tools/winscope/src/app/components/timeline/expanded-timeline/transition_timeline_component_test.ts
index 39e4405..e77e7ce 100644
--- a/tools/winscope/src/app/components/timeline/expanded-timeline/transition_timeline_component_test.ts
+++ b/tools/winscope/src/app/components/timeline/expanded-timeline/transition_timeline_component_test.ts
@@ -16,7 +16,7 @@
import {DragDropModule} from '@angular/cdk/drag-drop';
import {ChangeDetectionStrategy} from '@angular/core';
-import {ComponentFixture, TestBed} from '@angular/core/testing';
+import {TestBed} from '@angular/core/testing';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatFormFieldModule} from '@angular/material/form-field';
@@ -29,6 +29,7 @@
import {Rect} from 'common/geometry/rect';
import {TimestampConverterUtils} from 'common/time/test_utils';
import {TimeRange, Timestamp} from 'common/time/time';
+import {DOMTestHelper} from 'test/unit/dom_test_utils';
import {PropertyTreeBuilder} from 'test/unit/property_tree_builder';
import {waitToBeCalled} from 'test/unit/spy_utils';
import {TraceBuilder} from 'test/unit/trace_builder';
@@ -37,9 +38,8 @@
import {TransitionTimelineComponent} from './transition_timeline_component';
describe('TransitionTimelineComponent', () => {
- let fixture: ComponentFixture<TransitionTimelineComponent>;
let component: TransitionTimelineComponent;
- let htmlElement: HTMLElement;
+ let dom: DOMTestHelper<TransitionTimelineComponent>;
const time0 = TimestampConverterUtils.makeRealTimestamp(0n);
const time5 = TimestampConverterUtils.makeRealTimestamp(5n);
@@ -76,9 +76,9 @@
set: {changeDetection: ChangeDetectionStrategy.Default},
})
.compileComponents();
- fixture = TestBed.createComponent(TransitionTimelineComponent);
+ const fixture = TestBed.createComponent(TransitionTimelineComponent);
component = fixture.componentInstance;
- htmlElement = fixture.nativeElement;
+ dom = new DOMTestHelper(fixture, fixture.nativeElement);
component.timestampConverter = TimestampConverterUtils.TIMESTAMP_CONVERTER;
component.fullRange = range0to160;
});
@@ -227,14 +227,12 @@
const mouseoutEvent = new MouseEvent('mouseout');
component.getCanvas().dispatchEvent(mouseoutEvent);
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
expect(drawRectSpy).not.toHaveBeenCalled();
await dispatchMousemoveEvent();
component.getCanvas().dispatchEvent(mouseoutEvent);
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
expect(drawRectSpy).toHaveBeenCalledOnceWith(
getExpectedBorderedRect(),
@@ -413,18 +411,14 @@
const drawRectSpy = spyOn(component.canvasDrawer, 'drawRect');
- fixture.detectChanges();
- await fixture.whenRenderingDone();
-
+ await dom.detectChangesAndRenderingDone();
expect(drawRectSpy).toHaveBeenCalledTimes(1);
});
it('emits scroll event', async () => {
await setDefaultTraceAndSelectionRange();
-
const spy = spyOn(component.onScrollEvent, 'emit');
- htmlElement.dispatchEvent(new WheelEvent('wheel'));
- fixture.detectChanges();
+ dom.dispatchEvent(new WheelEvent('wheel'));
expect(spy).toHaveBeenCalled();
});
@@ -438,13 +432,13 @@
Object.defineProperty(mouseMoveEvent, 'target', {value: canvas});
Object.defineProperty(mouseMoveEvent, 'offsetX', {value: 100});
canvas.dispatchEvent(mouseMoveEvent);
- fixture.detectChanges();
+ dom.detectChanges();
expect(spy).toHaveBeenCalledWith(100 / canvas.offsetWidth);
const mouseLeaveEvent = new MouseEvent('mouseleave');
canvas.dispatchEvent(mouseLeaveEvent);
- fixture.detectChanges();
+ dom.detectChanges();
expect(spy).toHaveBeenCalledWith(undefined);
});
@@ -458,8 +452,7 @@
component.transitionEntries = transitions;
component.selectionRange = range10to110;
if (setSelectedEntry) component.selectedEntry = component.trace.getEntry(0);
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
}
function makeTransition(
@@ -514,8 +507,7 @@
.build();
component.transitionEntries = transitions;
component.selectionRange = range;
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
}
function getExpectedBorderedRect(): Rect {
@@ -538,7 +530,6 @@
);
spyOnProperty(mousemoveEvent, 'offsetY').and.returnValue(25 / 2);
component.getCanvas().dispatchEvent(mousemoveEvent);
- fixture.detectChanges();
- await fixture.whenRenderingDone();
+ await dom.detectChangesAndRenderingDone();
}
});
diff --git a/tools/winscope/src/app/components/timeline/mini-timeline/mini_timeline_component_test.ts b/tools/winscope/src/app/components/timeline/mini-timeline/mini_timeline_component_test.ts
index b50e689..15592c4 100644
--- a/tools/winscope/src/app/components/timeline/mini-timeline/mini_timeline_component_test.ts
+++ b/tools/winscope/src/app/components/timeline/mini-timeline/mini_timeline_component_test.ts
@@ -17,7 +17,7 @@
import {DragDropModule} from '@angular/cdk/drag-drop';
import {CdkMenuModule} from '@angular/cdk/menu';
import {ChangeDetectionStrategy, Component, ViewChild} from '@angular/core';
-import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing';
+import {fakeAsync, TestBed} from '@angular/core/testing';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatFormFieldModule} from '@angular/material/form-field';
@@ -28,10 +28,11 @@
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {TimelineData} from 'app/timeline_data';
import {assertDefined} from 'common/assert_utils';
+import {KeyboardEventCode} from 'common/dom_utils';
import {TimestampConverterUtils} from 'common/time/test_utils';
import {TimeRange, Timestamp} from 'common/time/time';
+import {DOMTestHelper} from 'test/unit/dom_test_utils';
import {TracesBuilder} from 'test/unit/traces_builder';
-import {dragElement} from 'test/utils';
import {Trace} from 'trace/trace';
import {TracePosition} from 'trace/trace_position';
import {TraceType} from 'trace/trace_type';
@@ -39,11 +40,15 @@
import {SliderComponent} from './slider_component';
describe('MiniTimelineComponent', () => {
- let fixture: ComponentFixture<TestHostComponent>;
let component: TestHostComponent;
- let htmlElement: HTMLElement;
+ let dom: DOMTestHelper<TestHostComponent>;
let timelineData: TimelineData;
+ const resetButtonSelector = 'button#reset-zoom-btn';
+ const zoomInSelector = '#zoom-in-btn';
+ const zoomOutSelector = '#zoom-out-btn';
+ const zoomControlSelector = '.zoom-control';
+
const timestamp10 = TimestampConverterUtils.makeRealTimestamp(10n);
const timestamp15 = TimestampConverterUtils.makeRealTimestamp(15n);
const timestamp16 = TimestampConverterUtils.makeRealTimestamp(16n);
@@ -92,9 +97,9 @@
set: {changeDetection: ChangeDetectionStrategy.Default},
})
.compileComponents();
- fixture = TestBed.createComponent(TestHostComponent);
+ const fixture = TestBed.createComponent(TestHostComponent);
component = fixture.componentInstance;
- htmlElement = fixture.nativeElement;
+ dom = new DOMTestHelper(fixture, fixture.nativeElement);
timelineData = new TimelineData();
await timelineData.initialize(
@@ -113,7 +118,7 @@
});
it('redraws on resize', () => {
- fixture.detectChanges();
+ dom.detectChanges();
const miniTimelineComponent = assertDefined(
component.miniTimelineComponent,
);
@@ -121,7 +126,7 @@
expect(spy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('resize'));
- fixture.detectChanges();
+ dom.detectChanges();
expect(spy).toHaveBeenCalled();
});
@@ -133,61 +138,49 @@
const zoomRange = timelineData.getZoomRange();
expect(zoomRange).toEqual(expectedZoomRange);
expect(zoomRange).not.toEqual(fullRange);
- fixture.detectChanges();
-
- getResetButton().click();
- fixture.detectChanges();
-
+ dom.detectChanges();
+ dom.findAndClick(resetButtonSelector);
expect(timelineData.getZoomRange()).toEqual(fullRange);
});
it('resets zoom to initial zoom on reset button click if available', () => {
const initialZoom = new TimeRange(timestamp15, timestamp16);
component.initialZoom = initialZoom;
- fixture.detectChanges();
+ dom.detectChanges();
expect(timelineData.getZoomRange()).toEqual(initialZoom);
const newZoom = new TimeRange(timestamp10, timestamp16);
timelineData.setZoom(newZoom);
expect(timelineData.getZoomRange()).toEqual(newZoom);
- fixture.detectChanges();
+ dom.detectChanges();
- getResetButton().click();
- fixture.detectChanges();
-
+ dom.findAndClick(resetButtonSelector);
expect(timelineData.getZoomRange()).toEqual(initialZoom);
expect(timelineData.getFullTimeRange()).not.toEqual(initialZoom);
});
it('show zoom controls when zoomed out', () => {
- const zoomControlDiv = assertDefined(
- htmlElement.querySelector('.zoom-control'),
- );
+ const zoomControlDiv = dom.get(zoomControlSelector).getHTMLElement();
expect(window.getComputedStyle(zoomControlDiv).visibility).toBe('visible');
-
- const zoomButton = getResetButton();
+ const zoomButton = dom.get(resetButtonSelector).getHTMLElement();
expect(window.getComputedStyle(zoomButton).visibility).toBe('visible');
});
it('shows zoom controls when zoomed in', () => {
const zoom = new TimeRange(timestamp15, timestamp16);
timelineData.setZoom(zoom);
+ dom.detectChanges();
- fixture.detectChanges();
-
- const zoomControlDiv = assertDefined(
- htmlElement.querySelector('.zoom-control'),
- );
+ const zoomControlDiv = dom.get(zoomControlSelector).getHTMLElement();
expect(window.getComputedStyle(zoomControlDiv).visibility).toBe('visible');
-
- const zoomButton = getResetButton();
+ const zoomButton = dom.get(resetButtonSelector).getHTMLElement();
expect(window.getComputedStyle(zoomButton).visibility).toBe('visible');
});
it('loads with initial zoom', () => {
const initialZoom = new TimeRange(timestamp15, timestamp16);
component.initialZoom = initialZoom;
- fixture.detectChanges();
+ dom.detectChanges();
const timelineData = assertDefined(component.timelineData);
const zoomRange = timelineData.getZoomRange();
expect(zoomRange.from).toEqual(initialZoom.from);
@@ -195,22 +188,22 @@
});
it('updates timelineData on zoom changed', () => {
- fixture.detectChanges();
+ dom.detectChanges();
const zoom = new TimeRange(timestamp15, timestamp16);
assertDefined(component.miniTimelineComponent).onZoomChanged(zoom);
- fixture.detectChanges();
+ dom.detectChanges();
expect(timelineData.getZoomRange()).toBe(zoom);
});
it('creates an appropriately sized canvas', () => {
- fixture.detectChanges();
+ dom.detectChanges();
const canvas = assertDefined(component.miniTimelineComponent).getCanvas();
expect(canvas.width).toBeGreaterThan(100);
expect(canvas.height).toBeGreaterThan(10);
});
it('getTracesToShow returns traces targeted by selectedTraces', () => {
- fixture.detectChanges();
+ dom.detectChanges();
const selectedTraces = assertDefined(component.selectedTraces);
const selectedTracesTypes = selectedTraces.map((trace) => trace.type);
@@ -224,7 +217,7 @@
it('getTracesToShow adds traces in correct order', () => {
component.selectedTraces = [traceWm, traceSf, traceTransactions];
- fixture.detectChanges();
+ dom.detectChanges();
const tracesToShowTypes = assertDefined(component.miniTimelineComponent)
.getTracesToShow()
.map((trace) => trace.type);
@@ -236,16 +229,16 @@
});
it('updates zoom when slider moved', fakeAsync(() => {
- fixture.detectChanges();
+ dom.detectChanges();
const initialZoom = new TimeRange(timestamp15, timestamp16);
assertDefined(component.miniTimelineComponent).onZoomChanged(initialZoom);
- fixture.detectChanges();
+ dom.detectChanges();
- const slider = assertDefined(htmlElement.querySelector('.slider .handle'));
- expect(window.getComputedStyle(slider).visibility).toEqual('visible');
+ const slider = dom.get('.slider .handle');
+ const sliderEl = slider.getHTMLElement();
+ expect(window.getComputedStyle(sliderEl).visibility).toEqual('visible');
- dragElement(fixture, slider, 100, 8);
-
+ slider.dragElement(100, 8);
const finalZoom = timelineData.getZoomRange();
expect(finalZoom).not.toBe(initialZoom);
}));
@@ -259,16 +252,13 @@
);
miniTimelineComponent.onZoomChanged(initialZoom);
miniTimelineComponent.currentTracePosition = position800;
+ dom.detectChanges();
- fixture.detectChanges();
-
- getZoomInButton().click();
- fixture.detectChanges();
+ dom.findAndClick(zoomInSelector);
const zoomedIn = timelineData.getZoomRange();
checkZoomDifference(initialZoom, zoomedIn);
- getZoomOutButton().click();
- fixture.detectChanges();
+ dom.findAndClick(zoomOutSelector);
const zoomedOut = timelineData.getZoomRange();
checkZoomDifference(zoomedOut, zoomedIn);
});
@@ -280,17 +270,14 @@
assertDefined(component.miniTimelineComponent).onZoomChanged(initialZoom);
timelineData.setPosition(position800);
- fixture.detectChanges();
+ dom.detectChanges();
- getZoomOutButton().click();
- fixture.detectChanges();
-
+ dom.findAndClick(zoomOutSelector);
let finalZoom = timelineData.getZoomRange();
expect(finalZoom.from.getValueNs()).toBe(initialZoom.from.getValueNs());
expect(finalZoom.to.getValueNs()).toBe(initialZoom.to.getValueNs());
zoomOutByScrollWheel();
-
finalZoom = timelineData.getZoomRange();
expect(finalZoom.from.getValueNs()).toBe(initialZoom.from.getValueNs());
expect(finalZoom.to.getValueNs()).toBe(initialZoom.to.getValueNs());
@@ -304,12 +291,10 @@
component.miniTimelineComponent,
);
miniTimelineComponent.onZoomChanged(initialZoom);
-
- fixture.detectChanges();
+ dom.detectChanges();
for (let i = 0; i < 10; i++) {
zoomInByScrollWheel();
-
const finalZoom = timelineData.getZoomRange();
checkZoomDifference(initialZoom, finalZoom);
initialZoom = finalZoom;
@@ -317,7 +302,6 @@
for (let i = 0; i < 9; i++) {
zoomOutByScrollWheel();
-
const finalZoom = timelineData.getZoomRange();
checkZoomDifference(finalZoom, initialZoom);
initialZoom = finalZoom;
@@ -329,7 +313,7 @@
const initialZoom = new TimeRange(timestamp10, timestamp1000);
assertDefined(component.miniTimelineComponent).onZoomChanged(initialZoom);
- fixture.detectChanges();
+ dom.detectChanges();
component.expandedTimelineScrollEvent = {
deltaY: -200,
@@ -337,41 +321,33 @@
x: 10, // scrolling on pos
target: component.miniTimelineComponent?.getCanvas(),
} as unknown as WheelEvent;
- fixture.detectChanges();
+ dom.detectChanges();
const finalZoom = timelineData.getZoomRange();
checkZoomDifference(initialZoom, finalZoom);
});
it('opens context menu', () => {
- fixture.detectChanges();
- expect(document.querySelector('.context-menu')).toBeFalsy();
+ dom.detectChanges();
+ expect(dom.findInDocument('.context-menu')).toBeUndefined();
- assertDefined(component.miniTimelineComponent)
- .getCanvas()
- .dispatchEvent(new MouseEvent('contextmenu'));
- fixture.detectChanges();
-
+ openContextMenu(assertDefined(component.miniTimelineComponent));
const options = getContextMenuItems();
expect(options.length).toEqual(2);
});
it('adds bookmark', () => {
- fixture.detectChanges();
+ dom.detectChanges();
const miniTimelineComponent = assertDefined(
component.miniTimelineComponent,
);
const spy = spyOn(miniTimelineComponent.onToggleBookmark, 'emit');
- miniTimelineComponent
- .getCanvas()
- .dispatchEvent(new MouseEvent('contextmenu'));
- fixture.detectChanges();
-
+ openContextMenu(miniTimelineComponent);
const options = getContextMenuItems();
- expect(options[0].textContent).toContain('Add bookmark');
- options[0].click();
+ options[0].checkText('Add bookmark');
+ options[0].click();
expect(spy).toHaveBeenCalledWith({
range: new TimeRange(timestamp10, timestamp10),
rangeContainsBookmark: false,
@@ -380,21 +356,16 @@
it('removes bookmark', () => {
component.bookmarks = [timestamp10];
- fixture.detectChanges();
+ dom.detectChanges();
const miniTimelineComponent = assertDefined(
component.miniTimelineComponent,
);
const spy = spyOn(miniTimelineComponent.onToggleBookmark, 'emit');
- miniTimelineComponent
- .getCanvas()
- .dispatchEvent(new MouseEvent('contextmenu'));
- fixture.detectChanges();
-
+ openContextMenu(assertDefined(component.miniTimelineComponent));
const options = getContextMenuItems();
- expect(options[0].textContent).toContain('Remove bookmark');
+ options[0].checkText('Remove bookmark');
options[0].click();
-
expect(spy).toHaveBeenCalledWith({
range: new TimeRange(timestamp10, timestamp10),
rangeContainsBookmark: true,
@@ -403,21 +374,17 @@
it('removes all bookmarks', () => {
component.bookmarks = [timestamp10, timestamp1000];
- fixture.detectChanges();
+ dom.detectChanges();
const miniTimelineComponent = assertDefined(
component.miniTimelineComponent,
);
const spy = spyOn(miniTimelineComponent.onRemoveAllBookmarks, 'emit');
- miniTimelineComponent
- .getCanvas()
- .dispatchEvent(new MouseEvent('contextmenu'));
- fixture.detectChanges();
-
+ openContextMenu(miniTimelineComponent);
const options = getContextMenuItems();
- expect(options[1].textContent).toContain('Remove all bookmarks');
- options[1].click();
+ options[1].checkText('Remove all bookmarks');
+ options[1].click();
expect(spy).toHaveBeenCalled();
});
@@ -426,7 +393,7 @@
const initialZoom = new TimeRange(timestamp1000, timestamp2000);
component.initialZoom = initialZoom;
- fixture.detectChanges();
+ dom.detectChanges();
zoomInByKeyW();
const zoomedIn = timelineData.getZoomRange();
@@ -442,11 +409,12 @@
const initialZoom = new TimeRange(timestamp1000, timestamp2000);
component.initialZoom = initialZoom;
- fixture.detectChanges();
+ dom.detectChanges();
while (timelineData.getZoomRange().to !== timestamp4000) {
- document.dispatchEvent(new KeyboardEvent('keydown', {code: 'KeyD'}));
- fixture.detectChanges();
+ dom.dispatchEventInDocument(
+ new KeyboardEvent('keydown', {code: KeyboardEventCode.D}),
+ );
const zoomRange = timelineData.getZoomRange();
const increase =
zoomRange.from.getValueNs() - initialZoom.from.getValueNs();
@@ -458,13 +426,15 @@
// cannot move past end of trace
const finalZoom = timelineData.getZoomRange();
- document.dispatchEvent(new KeyboardEvent('keydown', {code: 'KeyD'}));
- fixture.detectChanges();
+ dom.dispatchEventInDocument(
+ new KeyboardEvent('keydown', {code: KeyboardEventCode.D}),
+ );
expect(timelineData.getZoomRange()).toEqual(finalZoom);
while (timelineData.getZoomRange().from !== timestamp1000) {
- document.dispatchEvent(new KeyboardEvent('keydown', {code: 'KeyA'}));
- fixture.detectChanges();
+ dom.dispatchEventInDocument(
+ new KeyboardEvent('keydown', {code: KeyboardEventCode.A}),
+ );
const zoomRange = timelineData.getZoomRange();
const decrease =
finalZoom.from.getValueNs() - zoomRange.from.getValueNs();
@@ -475,8 +445,9 @@
}
// cannot move before start of trace
- document.dispatchEvent(new KeyboardEvent('keydown', {code: 'KeyA'}));
- fixture.detectChanges();
+ dom.dispatchEventInDocument(
+ new KeyboardEvent('keydown', {code: KeyboardEventCode.A}),
+ );
expect(timelineData.getZoomRange()).toEqual(initialZoom);
});
@@ -485,7 +456,7 @@
const initialZoom = new TimeRange(timestamp1000, timestamp4000);
component.initialZoom = initialZoom;
component.currentTracePosition = TracePosition.fromTimestamp(timestamp2000);
- fixture.detectChanges();
+ dom.detectChanges();
const miniTimelineComponent = assertDefined(
component.miniTimelineComponent,
@@ -501,7 +472,7 @@
(usableRange.to - usableRange.from) * 0.25 + drawer.getPadding().left,
});
canvas.dispatchEvent(mouseMoveEvent);
- fixture.detectChanges();
+ dom.detectChanges();
const fullRangeQuarterTimestamp = timestamp1750;
checkZoomOnTimestamp(
@@ -525,7 +496,7 @@
const initialZoom = new TimeRange(timestamp1000, timestamp4000);
component.initialZoom = initialZoom;
component.currentTracePosition = TracePosition.fromTimestamp(timestamp1750);
- fixture.detectChanges();
+ dom.detectChanges();
const fullRangeQuarterTimestamp = timestamp1750;
checkZoomOnTimestamp(
@@ -543,20 +514,17 @@
zoomOutByScrollWheel,
);
- const zoomInButton = getZoomInButton();
- const zoomOutButton = getZoomOutButton();
-
+ const zoomInButton = dom.get(zoomInSelector);
+ const zoomOutButton = dom.get(zoomOutSelector);
checkZoomOnTimestamp(
fullRangeQuarterTimestamp,
1n,
4n,
() => {
zoomInButton.click();
- fixture.detectChanges();
},
() => {
zoomOutButton.click();
- fixture.detectChanges();
},
);
});
@@ -566,7 +534,7 @@
const initialZoom = new TimeRange(timestamp1000, timestamp4000);
component.initialZoom = initialZoom;
component.currentTracePosition = TracePosition.fromTimestamp(timestamp1750);
- fixture.detectChanges();
+ dom.detectChanges();
const miniTimelineComponent = assertDefined(
component.miniTimelineComponent,
@@ -581,9 +549,9 @@
value: (usableRange.to - usableRange.from) * 0.5,
});
canvas.dispatchEvent(mouseMoveEvent);
- fixture.detectChanges();
+ dom.detectChanges();
canvas.dispatchEvent(new MouseEvent('mouseleave'));
- fixture.detectChanges();
+ dom.detectChanges();
const fullRangeQuarterTimestamp = timestamp1750;
checkZoomOnTimestamp(
@@ -601,20 +569,17 @@
zoomOutByScrollWheel,
);
- const zoomInButton = getZoomInButton();
- const zoomOutButton = getZoomOutButton();
-
+ const zoomInButton = dom.get(zoomInSelector);
+ const zoomOutButton = dom.get(zoomOutSelector);
checkZoomOnTimestamp(
fullRangeQuarterTimestamp,
1n,
4n,
() => {
zoomInButton.click();
- fixture.detectChanges();
},
() => {
zoomOutButton.click();
- fixture.detectChanges();
},
);
});
@@ -624,7 +589,7 @@
const initialZoom = new TimeRange(timestamp2000, timestamp4000);
component.initialZoom = initialZoom;
component.currentTracePosition = TracePosition.fromTimestamp(timestamp1750);
- fixture.detectChanges();
+ dom.detectChanges();
const fullRangeMiddleTimestamp = timestamp3000;
checkZoomOnTimestamp(
@@ -642,20 +607,17 @@
zoomOutByScrollWheel,
);
- const zoomInButton = getZoomInButton();
- const zoomOutButton = getZoomOutButton();
-
+ const zoomInButton = dom.get(zoomInSelector);
+ const zoomOutButton = dom.get(zoomOutSelector);
checkZoomOnTimestamp(
fullRangeMiddleTimestamp,
1n,
2n,
() => {
zoomInButton.click();
- fixture.detectChanges();
},
() => {
zoomOutButton.click();
- fixture.detectChanges();
},
);
});
@@ -664,10 +626,10 @@
initializeTracesForWASDZoom();
const initialZoom = new TimeRange(timestamp1000, timestamp4000);
component.initialZoom = initialZoom;
- fixture.detectChanges();
+ dom.detectChanges();
component.currentTracePosition = TracePosition.fromTimestamp(timestamp2000);
component.expandedTimelineMouseXRatio = 0.25;
- fixture.detectChanges();
+ dom.detectChanges();
const fullRangeQuarterTimestamp = timestamp1750;
checkZoomOnTimestamp(
@@ -698,7 +660,7 @@
undefined,
TimestampConverterUtils.TIMESTAMP_CONVERTER,
);
- fixture.detectChanges();
+ dom.detectChanges();
}
function initializeTracesForWASDZoom() {
@@ -731,13 +693,15 @@
}
function zoomInByKeyW() {
- document.dispatchEvent(new KeyboardEvent('keydown', {code: 'KeyW'}));
- fixture.detectChanges();
+ dom.dispatchEventInDocument(
+ new KeyboardEvent('keydown', {code: KeyboardEventCode.W}),
+ );
}
function zoomOutByKeyS() {
- document.dispatchEvent(new KeyboardEvent('keydown', {code: 'KeyS'}));
- fixture.detectChanges();
+ dom.dispatchEventInDocument(
+ new KeyboardEvent('keydown', {code: KeyboardEventCode.S}),
+ );
}
function zoomInByScrollWheel() {
@@ -747,7 +711,7 @@
x: 10, // scrolling on pos
target: {id: 'mini-timeline-canvas', offsetLeft: 0},
} as unknown as WheelEvent);
- fixture.detectChanges();
+ dom.detectChanges();
}
function zoomOutByScrollWheel() {
@@ -757,30 +721,11 @@
x: 10, // scrolling on pos
target: {id: 'mini-timeline-canvas', offsetLeft: 0},
} as unknown as WheelEvent);
- fixture.detectChanges();
+ dom.detectChanges();
}
- function getResetButton(): HTMLElement {
- return assertDefined(
- htmlElement.querySelector<HTMLElement>('button#reset-zoom-btn'),
- );
- }
-
- function getZoomInButton(): HTMLElement {
- return assertDefined(
- htmlElement.querySelector<HTMLElement>('#zoom-in-btn'),
- );
- }
-
- function getZoomOutButton(): HTMLElement {
- return assertDefined(
- htmlElement.querySelector<HTMLElement>('#zoom-out-btn'),
- );
- }
-
- function getContextMenuItems(): HTMLElement[] {
- const menu = assertDefined(document.querySelector('.context-menu'));
- return Array.from(menu.querySelectorAll<HTMLElement>('.context-menu-item'));
+ function getContextMenuItems(): Array<DOMTestHelper<TestHostComponent>> {
+ return dom.getInDocument('.context-menu')?.findAll('.context-menu-item');
}
function checkZoomOnTimestamp(
@@ -827,6 +772,13 @@
}
}
+ function openContextMenu(miniTimelineComponent: MiniTimelineComponent) {
+ miniTimelineComponent
+ .getCanvas()
+ .dispatchEvent(new MouseEvent('contextmenu'));
+ dom.detectChanges();
+ }
+
@Component({
selector: 'host-component',
template: `
diff --git a/tools/winscope/src/app/components/timeline/mini-timeline/slider_component_test.ts b/tools/winscope/src/app/components/timeline/mini-timeline/slider_component_test.ts
index fd656fa..805d0e5 100644
--- a/tools/winscope/src/app/components/timeline/mini-timeline/slider_component_test.ts
+++ b/tools/winscope/src/app/components/timeline/mini-timeline/slider_component_test.ts
@@ -16,7 +16,7 @@
import {DragDropModule} from '@angular/cdk/drag-drop';
import {ChangeDetectionStrategy} from '@angular/core';
-import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing';
+import {fakeAsync, TestBed} from '@angular/core/testing';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatFormFieldModule} from '@angular/material/form-field';
@@ -28,14 +28,15 @@
import {assertDefined} from 'common/assert_utils';
import {TimestampConverterUtils} from 'common/time/test_utils';
import {TimeRange} from 'common/time/time';
-import {dragElement} from 'test/utils';
+import {DOMTestHelper} from 'test/unit/dom_test_utils';
import {TracePosition} from 'trace/trace_position';
import {MIN_SLIDER_WIDTH, SliderComponent} from './slider_component';
describe('SliderComponent', () => {
- let fixture: ComponentFixture<SliderComponent>;
let component: SliderComponent;
- let htmlElement: HTMLElement;
+ let dom: DOMTestHelper<SliderComponent>;
+ const leftCropperSelector = '.slider .cropper.left';
+ const rightCropperSelector = '.slider .cropper.right';
const time100 = TimestampConverterUtils.makeRealTimestamp(100n);
const time125 = TimestampConverterUtils.makeRealTimestamp(125n);
const time126 = TimestampConverterUtils.makeRealTimestamp(126n);
@@ -63,16 +64,14 @@
set: {changeDetection: ChangeDetectionStrategy.Default},
})
.compileComponents();
- fixture = TestBed.createComponent(SliderComponent);
+ const fixture = TestBed.createComponent(SliderComponent);
component = fixture.componentInstance;
- htmlElement = fixture.nativeElement;
-
+ dom = new DOMTestHelper(fixture, fixture.nativeElement);
component.fullRange = new TimeRange(time100, time200);
component.zoomRange = new TimeRange(time125, time175);
component.currentPosition = TracePosition.fromTimestamp(time150);
component.timestampConverter = TimestampConverterUtils.TIMESTAMP_CONVERTER;
-
- fixture.detectChanges();
+ dom.detectChanges();
});
it('can be created', () => {
@@ -80,7 +79,7 @@
});
it('reposition properly on zoom', () => {
- fixture.detectChanges();
+ dom.detectChanges();
component.ngOnChanges({
zoomRange: {
firstChange: true,
@@ -89,18 +88,18 @@
currentValue: component.zoomRange,
},
});
- fixture.detectChanges();
+ dom.detectChanges();
- const sliderWitdth = component.sliderBox.nativeElement.offsetWidth;
- expect(component.sliderWidth).toBe(sliderWitdth / 2);
- expect(component.dragPosition.x).toBe(sliderWitdth / 4);
+ const sliderWidth = component.sliderBox.nativeElement.offsetWidth;
+ expect(component.sliderWidth).toEqual(sliderWidth / 2);
+ expect(component.dragPosition.x).toEqual(sliderWidth / 4);
});
it('has min width', () => {
component.fullRange = new TimeRange(time100, time200);
component.zoomRange = new TimeRange(time125, time126);
- fixture.detectChanges();
+ dom.detectChanges();
component.ngOnChanges({
zoomRange: {
firstChange: true,
@@ -109,21 +108,19 @@
currentValue: component.zoomRange,
},
});
- fixture.detectChanges();
+ dom.detectChanges();
const sliderWidth = component.sliderBox.nativeElement.offsetWidth;
- expect(component.sliderWidth).toBe(MIN_SLIDER_WIDTH);
- expect(component.dragPosition.x).toBe(
+ expect(component.sliderWidth).toEqual(MIN_SLIDER_WIDTH);
+ expect(component.dragPosition.x).toEqual(
sliderWidth / 4 - MIN_SLIDER_WIDTH / 2,
);
});
it('repositions slider on resize', () => {
- const slider = assertDefined(htmlElement.querySelector('.slider'));
- const cursor = assertDefined(htmlElement.querySelector('.cursor'));
-
- fixture.detectChanges();
-
+ const slider = dom.get('.slider').getHTMLElement();
+ const cursor = dom.get('.cursor').getHTMLElement();
+ dom.detectChanges();
const initialSliderXPos = slider.getBoundingClientRect().left;
const initialCursorXPos = cursor.getBoundingClientRect().left;
@@ -132,18 +129,17 @@
'offsetWidth',
'get',
).and.returnValue(100);
- expect(component.sliderBox.nativeElement.offsetWidth).toBe(100);
+ expect(component.sliderBox.nativeElement.offsetWidth).toEqual(100);
- htmlElement.style.width = '587px';
+ slider.style.width = '587px';
window.dispatchEvent(new Event('resize'));
- fixture.detectChanges();
-
- expect(initialSliderXPos).not.toBe(slider.getBoundingClientRect().left);
- expect(initialCursorXPos).not.toBe(cursor.getBoundingClientRect().left);
+ dom.detectChanges();
+ expect(initialSliderXPos).not.toEqual(slider.getBoundingClientRect().left);
+ expect(initialCursorXPos).not.toEqual(cursor.getBoundingClientRect().left);
});
it('draws current position cursor', () => {
- fixture.detectChanges();
+ dom.detectChanges();
component.ngOnChanges({
currentPosition: {
firstChange: true,
@@ -152,12 +148,10 @@
currentValue: component.currentPosition,
},
});
- fixture.detectChanges();
+ dom.detectChanges();
- const sliderBox = assertDefined(
- htmlElement.querySelector('#timeline-slider-box'),
- );
- const cursor = assertDefined(htmlElement.querySelector('.cursor'));
+ const sliderBox = dom.get('#timeline-slider-box').getHTMLElement();
+ const cursor = dom.get('.cursor').getHTMLElement();
const sliderBoxRect = sliderBox.getBoundingClientRect();
expect(cursor.getBoundingClientRect().left).toBeCloseTo(
(sliderBoxRect.left + sliderBoxRect.right) / 2,
@@ -166,8 +160,7 @@
});
it('moving slider around updates zoom', fakeAsync(async () => {
- fixture.detectChanges();
-
+ dom.detectChanges();
const initialZoom = assertDefined(component.zoomRange);
let lastZoomUpdate: TimeRange | undefined = undefined;
@@ -177,27 +170,21 @@
},
);
- const slider = htmlElement.querySelector('.slider .handle');
- expect(slider).toBeTruthy();
- expect(window.getComputedStyle(assertDefined(slider)).visibility).toBe(
- 'visible',
- );
+ const slider = dom.get('.slider .handle');
+ checkVisible(slider.getHTMLElement());
- dragElement(fixture, assertDefined(slider), 100, 8);
-
+ slider.dragElement(100, 8);
expect(zoomChangedSpy).toHaveBeenCalled();
-
const finalZoom = assertDefined<TimeRange>(lastZoomUpdate);
- expect(finalZoom.from).not.toBe(initialZoom.from);
- expect(finalZoom.to).not.toBe(initialZoom.to);
- expect(finalZoom.to.minus(finalZoom.from.getValueNs()).getValueNs()).toBe(
- initialZoom.to.minus(initialZoom.from.getValueNs()).getValueNs(),
- );
+ expect(finalZoom.from).not.toEqual(initialZoom.from);
+ expect(finalZoom.to).not.toEqual(initialZoom.to);
+ expect(
+ finalZoom.to.minus(finalZoom.from.getValueNs()).getValueNs(),
+ ).toEqual(initialZoom.to.minus(initialZoom.from.getValueNs()).getValueNs());
}));
it('moving slider left pointer around updates zoom', fakeAsync(async () => {
- fixture.detectChanges();
-
+ dom.detectChanges();
const initialZoom = assertDefined(component.zoomRange);
let lastZoomUpdate: TimeRange | undefined = undefined;
@@ -207,14 +194,10 @@
},
);
- const leftCropper = htmlElement.querySelector('.slider .cropper.left');
- expect(leftCropper).toBeTruthy();
- expect(window.getComputedStyle(assertDefined(leftCropper)).visibility).toBe(
- 'visible',
- );
+ const leftCropper = dom.get(leftCropperSelector);
+ checkVisible(leftCropper.getHTMLElement());
- dragElement(fixture, assertDefined(leftCropper), 5, 0);
-
+ leftCropper.dragElement(5, 0);
expect(zoomChangedSpy).toHaveBeenCalled();
const finalZoom = assertDefined<TimeRange>(lastZoomUpdate);
@@ -223,8 +206,7 @@
}));
it('moving slider right pointer around updates zoom', fakeAsync(async () => {
- fixture.detectChanges();
-
+ dom.detectChanges();
const initialZoom = assertDefined(component.zoomRange);
let lastZoomUpdate: TimeRange | undefined = undefined;
@@ -234,14 +216,10 @@
},
);
- const rightCropper = htmlElement.querySelector('.slider .cropper.right');
- expect(rightCropper).toBeTruthy();
- expect(
- window.getComputedStyle(assertDefined(rightCropper)).visibility,
- ).toBe('visible');
+ const rightCropper = dom.get(rightCropperSelector);
+ checkVisible(rightCropper.getHTMLElement());
- dragElement(fixture, assertDefined(rightCropper), 5, 0);
-
+ rightCropper.dragElement(5, 0);
expect(zoomChangedSpy).toHaveBeenCalled();
const finalZoom = assertDefined<TimeRange>(lastZoomUpdate);
@@ -251,8 +229,7 @@
it('cannot slide left cropper past edges', fakeAsync(() => {
component.zoomRange = component.fullRange;
- fixture.detectChanges();
-
+ dom.detectChanges();
const initialZoom = assertDefined(component.zoomRange);
let lastZoomUpdate: TimeRange | undefined = undefined;
@@ -262,25 +239,20 @@
},
);
- const leftCropper = htmlElement.querySelector('.slider .cropper.left');
- expect(leftCropper).toBeTruthy();
- expect(window.getComputedStyle(assertDefined(leftCropper)).visibility).toBe(
- 'visible',
- );
+ const leftCropper = dom.get(leftCropperSelector);
+ checkVisible(leftCropper.getHTMLElement());
- dragElement(fixture, assertDefined(leftCropper), -5, 0);
-
+ leftCropper.dragElement(-5, 0);
expect(zoomChangedSpy).toHaveBeenCalled();
const finalZoom = assertDefined<TimeRange>(lastZoomUpdate);
- expect(finalZoom.from.getValueNs()).toBe(initialZoom.from.getValueNs());
- expect(finalZoom.to.getValueNs()).toBe(initialZoom.to.getValueNs());
+ expect(finalZoom.from.getValueNs()).toEqual(initialZoom.from.getValueNs());
+ expect(finalZoom.to.getValueNs()).toEqual(initialZoom.to.getValueNs());
}));
it('cannot slide right cropper past edges', fakeAsync(() => {
component.zoomRange = component.fullRange;
- fixture.detectChanges();
-
+ dom.detectChanges();
const initialZoom = assertDefined(component.zoomRange);
let lastZoomUpdate: TimeRange | undefined = undefined;
@@ -290,25 +262,20 @@
},
);
- const rightCropper = htmlElement.querySelector('.slider .cropper.right');
- expect(rightCropper).toBeTruthy();
- expect(
- window.getComputedStyle(assertDefined(rightCropper)).visibility,
- ).toBe('visible');
+ const rightCropper = dom.get(rightCropperSelector);
+ checkVisible(rightCropper.getHTMLElement());
- dragElement(fixture, assertDefined(rightCropper), 5, 0);
-
+ rightCropper.dragElement(5, 0);
expect(zoomChangedSpy).toHaveBeenCalled();
const finalZoom = assertDefined<TimeRange>(lastZoomUpdate);
- expect(finalZoom.from.getValueNs()).toBe(initialZoom.from.getValueNs());
- expect(finalZoom.to.getValueNs()).toBe(initialZoom.to.getValueNs());
+ expect(finalZoom.from.getValueNs()).toEqual(initialZoom.from.getValueNs());
+ expect(finalZoom.to.getValueNs()).toEqual(initialZoom.to.getValueNs());
}));
it('cannot slide left cropper past right cropper', fakeAsync(() => {
component.zoomRange = new TimeRange(time125, time125);
- fixture.detectChanges();
-
+ dom.detectChanges();
const initialZoom = assertDefined(component.zoomRange);
let lastZoomUpdate: TimeRange | undefined = undefined;
@@ -318,25 +285,20 @@
},
);
- const leftCropper = htmlElement.querySelector('.slider .cropper.left');
- expect(leftCropper).toBeTruthy();
- expect(window.getComputedStyle(assertDefined(leftCropper)).visibility).toBe(
- 'visible',
- );
+ const leftCropper = dom.get(leftCropperSelector);
+ checkVisible(leftCropper.getHTMLElement());
- dragElement(fixture, assertDefined(leftCropper), 100, 0);
-
+ leftCropper.dragElement(100, 0);
expect(zoomChangedSpy).toHaveBeenCalled();
const finalZoom = assertDefined<TimeRange>(lastZoomUpdate);
- expect(finalZoom.from.getValueNs()).toBe(initialZoom.from.getValueNs());
- expect(finalZoom.to.getValueNs()).toBe(initialZoom.to.getValueNs());
+ expect(finalZoom.from.getValueNs()).toEqual(initialZoom.from.getValueNs());
+ expect(finalZoom.to.getValueNs()).toEqual(initialZoom.to.getValueNs());
}));
it('cannot slide right cropper past left cropper', fakeAsync(() => {
component.zoomRange = new TimeRange(time125, time125);
- fixture.detectChanges();
-
+ dom.detectChanges();
const initialZoom = assertDefined(component.zoomRange);
let lastZoomUpdate: TimeRange | undefined = undefined;
@@ -346,25 +308,20 @@
},
);
- const rightCropper = htmlElement.querySelector('.slider .cropper.right');
- expect(rightCropper).toBeTruthy();
- expect(
- window.getComputedStyle(assertDefined(rightCropper)).visibility,
- ).toBe('visible');
+ const rightCropper = dom.get(rightCropperSelector);
+ checkVisible(rightCropper.getHTMLElement());
- dragElement(fixture, assertDefined(rightCropper), -100, 0);
-
+ rightCropper.dragElement(-100, 0);
expect(zoomChangedSpy).toHaveBeenCalled();
const finalZoom = assertDefined<TimeRange>(lastZoomUpdate);
- expect(finalZoom.from.getValueNs()).toBe(initialZoom.from.getValueNs());
- expect(finalZoom.to.getValueNs()).toBe(initialZoom.to.getValueNs());
+ expect(finalZoom.from.getValueNs()).toEqual(initialZoom.from.getValueNs());
+ expect(finalZoom.to.getValueNs()).toEqual(initialZoom.to.getValueNs());
}));
it('cannot move slider past edges', fakeAsync(() => {
component.zoomRange = component.fullRange;
- fixture.detectChanges();
-
+ dom.detectChanges();
const initialZoom = assertDefined(component.zoomRange);
let lastZoomUpdate: TimeRange | undefined = undefined;
@@ -374,18 +331,18 @@
},
);
- const slider = htmlElement.querySelector('.slider .handle');
- expect(slider).toBeTruthy();
- expect(window.getComputedStyle(assertDefined(slider)).visibility).toBe(
- 'visible',
- );
+ const slider = dom.get('.slider .handle');
+ checkVisible(slider.getHTMLElement());
- dragElement(fixture, assertDefined(slider), 100, 8);
-
+ slider.dragElement(100, 8);
expect(zoomChangedSpy).toHaveBeenCalled();
const finalZoom = assertDefined<TimeRange>(lastZoomUpdate);
- expect(finalZoom.from.getValueNs()).toBe(initialZoom.from.getValueNs());
- expect(finalZoom.to.getValueNs()).toBe(initialZoom.to.getValueNs());
+ expect(finalZoom.from.getValueNs()).toEqual(initialZoom.from.getValueNs());
+ expect(finalZoom.to.getValueNs()).toEqual(initialZoom.to.getValueNs());
}));
+
+ function checkVisible(element: HTMLElement) {
+ expect(window.getComputedStyle(element).visibility).toEqual('visible');
+ }
});
diff --git a/tools/winscope/src/app/components/timeline/timeline_component_test.ts b/tools/winscope/src/app/components/timeline/timeline_component_test.ts
index 3558900..792591d 100644
--- a/tools/winscope/src/app/components/timeline/timeline_component_test.ts
+++ b/tools/winscope/src/app/components/timeline/timeline_component_test.ts
@@ -18,7 +18,7 @@
import {DragDropModule} from '@angular/cdk/drag-drop';
import {CdkMenuModule} from '@angular/cdk/menu';
import {ChangeDetectionStrategy, Component, ViewChild} from '@angular/core';
-import {ComponentFixture, TestBed} from '@angular/core/testing';
+import {TestBed} from '@angular/core/testing';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatFormFieldModule} from '@angular/material/form-field';
@@ -26,7 +26,6 @@
import {MatInputModule} from '@angular/material/input';
import {MatSelectModule} from '@angular/material/select';
import {MatTooltipModule} from '@angular/material/tooltip';
-import {By} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {
MatDrawer,
@@ -50,6 +49,7 @@
TraceSearchRequest,
WinscopeEvent,
} from 'messaging/winscope_event';
+import {checkTooltips, DOMTestHelper} from 'test/unit/dom_test_utils';
import {TracesBuilder} from 'test/unit/traces_builder';
import {TraceBuilder} from 'test/unit/trace_builder';
import {UnitTestUtils} from 'test/unit/utils';
@@ -89,9 +89,11 @@
const position110 = TracePosition.fromTimestamp(time110);
const position112 = TracePosition.fromTimestamp(time112);
- let fixture: ComponentFixture<TestHostComponent>;
+ const nextEntrySelector = '#next_entry_button';
+ const prevEntrySelector = '#prev_entry_button';
+
let component: TestHostComponent;
- let htmlElement: HTMLElement;
+ let dom: DOMTestHelper<TestHostComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
@@ -126,9 +128,9 @@
set: {changeDetection: ChangeDetectionStrategy.Default},
})
.compileComponents();
- fixture = TestBed.createComponent(TestHostComponent);
+ const fixture = TestBed.createComponent(TestHostComponent);
component = fixture.componentInstance;
- htmlElement = fixture.nativeElement;
+ dom = new DOMTestHelper(fixture, fixture.nativeElement);
});
it('can be created', () => {
@@ -144,19 +146,15 @@
undefined,
TimestampConverterUtils.TIMESTAMP_CONVERTER,
);
- fixture.detectChanges();
+ dom.detectChanges();
const timelineComponent = assertDefined(component.timeline);
- const button = assertDefined(
- htmlElement.querySelector(`.${timelineComponent.TOGGLE_BUTTON_CLASS}`),
- );
-
// initially not expanded
- let expandedTimelineElement = fixture.debugElement.query(
- By.directive(ExpandedTimelineComponent),
+ let expandedTimelineElement = dom.findByDirective(
+ ExpandedTimelineComponent,
);
- expect(expandedTimelineElement).toBeFalsy();
+ expect(expandedTimelineElement).toBeUndefined();
let isExpanded = false;
timelineComponent.setEmitEvent(async (event: WinscopeEvent) => {
@@ -164,18 +162,16 @@
isExpanded = (event as ExpandedTimelineToggled).isTimelineExpanded;
});
- button.dispatchEvent(new Event('click'));
- expandedTimelineElement = fixture.debugElement.query(
- By.directive(ExpandedTimelineComponent),
+ const button = dom.findAndClick(
+ `.${timelineComponent.TOGGLE_BUTTON_CLASS}`,
);
- expect(expandedTimelineElement).toBeTruthy();
+ expandedTimelineElement = dom.findByDirective(ExpandedTimelineComponent);
+ expect(expandedTimelineElement).toBeDefined();
expect(isExpanded).toBeTrue();
- button.dispatchEvent(new Event('click'));
- expandedTimelineElement = fixture.debugElement.query(
- By.directive(ExpandedTimelineComponent),
- );
- expect(expandedTimelineElement).toBeFalsy();
+ button.click();
+ expandedTimelineElement = dom.findByDirective(ExpandedTimelineComponent);
+ expect(expandedTimelineElement).toBeUndefined();
expect(isExpanded).toBeFalse();
});
@@ -188,18 +184,14 @@
undefined,
TimestampConverterUtils.TIMESTAMP_CONVERTER,
);
- fixture.detectChanges();
+ dom.detectChanges();
- expect(htmlElement.querySelector('.time-selector')).toBeNull();
- expect(htmlElement.querySelector('.trace-selector')).toBeNull();
+ expect(dom.find('.time-selector')).toBeUndefined();
+ expect(dom.find('.trace-selector')).toBeUndefined();
- const errorMessageContainer = assertDefined(
- htmlElement.querySelector('.no-timeline-msg'),
- );
- expect(errorMessageContainer.textContent).toContain('No timeline to show!');
- expect(errorMessageContainer.textContent).toContain(
- 'All loaded traces contain no timestamps.',
- );
+ const errorMessageContainer = dom.get('.no-timeline-msg');
+ errorMessageContainer.checkText('No timeline to show!');
+ errorMessageContainer.checkText('All loaded traces contain no timestamps.');
checkNoTimelineNavigation();
});
@@ -207,18 +199,14 @@
it('handles some empty traces and some with one timestamp', async () => {
await loadTracesWithOneTimestamp();
- expect(htmlElement.querySelector('#time-selector')).toBeTruthy();
- const shownSelection = assertDefined(
- htmlElement.querySelector('#trace-selector .shown-selection'),
- );
- expect(shownSelection.innerHTML).toContain('Window Manager');
- expect(shownSelection.innerHTML).not.toContain('Surface Flinger');
+ expect(dom.find('#time-selector')).toBeDefined();
+ const shownSelection = dom.get('#trace-selector .shown-selection');
+ shownSelection.checkInnerHTML('Window Manager');
+ shownSelection.checkInnerHTML('Surface Flinger', false);
- const errorMessageContainer = assertDefined(
- htmlElement.querySelector('.no-timeline-msg'),
- );
- expect(errorMessageContainer.textContent).toContain('No timeline to show!');
- expect(errorMessageContainer.textContent).toContain(
+ const errorMessageContainer = dom.get('.no-timeline-msg');
+ errorMessageContainer.checkText('No timeline to show!');
+ errorMessageContainer.checkText(
'Only a single timestamp has been recorded.',
);
@@ -227,20 +215,16 @@
it('processes active trace input and updates selected traces', async () => {
loadAllTraces();
- fixture.detectChanges();
+ dom.detectChanges();
const timelineComponent = assertDefined(component.timeline);
- const nextEntryButton = assertDefined(
- htmlElement.querySelector<HTMLElement>('#next_entry_button'),
- );
- const prevEntryButton = assertDefined(
- htmlElement.querySelector<HTMLElement>('#prev_entry_button'),
- );
+ const nextEntryButton = dom.get(nextEntrySelector);
+ const prevEntryButton = dom.get(prevEntrySelector);
timelineComponent.selectedTraces = [
getLoadedTrace(TraceType.SURFACE_FLINGER),
];
- fixture.detectChanges();
+ dom.detectChanges();
checkActiveTraceSurfaceFlinger(nextEntryButton, prevEntryButton);
// setting same trace as active does not affect selected traces
@@ -297,40 +281,32 @@
TimestampConverterUtils.TIMESTAMP_CONVERTER,
);
timelineData.setPosition(position100);
- fixture.detectChanges();
- const nextEntryButton = assertDefined(
- htmlElement.querySelector<HTMLElement>('#next_entry_button'),
- );
- const prevEntryButton = assertDefined(
- htmlElement.querySelector<HTMLElement>('#prev_entry_button'),
- );
+ dom.detectChanges();
+ const nextEntryButton = dom.get(nextEntrySelector);
+ const prevEntryButton = dom.get(prevEntrySelector);
expect(timelineData.getActiveTrace()).toBeUndefined();
expect(timelineData.getCurrentPosition()?.timestamp.getValueNs()).toEqual(
100n,
);
- expect(prevEntryButton.getAttribute('disabled')).toEqual('true');
- expect(nextEntryButton.getAttribute('disabled')).toEqual('true');
+ prevEntryButton.checkDisabled(true);
+ nextEntryButton.checkDisabled(true);
});
it('handles ActiveTraceChanged event', async () => {
loadSfWmTraces();
- fixture.detectChanges();
+ dom.detectChanges();
const timelineComponent = assertDefined(component.timeline);
- const nextEntryButton = assertDefined(
- htmlElement.querySelector<HTMLElement>('#next_entry_button'),
- );
- const prevEntryButton = assertDefined(
- htmlElement.querySelector<HTMLElement>('#prev_entry_button'),
- );
+ const nextEntryButton = dom.get(nextEntrySelector);
+ const prevEntryButton = dom.get(prevEntrySelector);
const spy = spyOn(
assertDefined(timelineComponent.miniTimeline?.drawer),
'draw',
);
await updateActiveTrace(TraceType.SURFACE_FLINGER);
- fixture.detectChanges();
+ dom.detectChanges();
checkActiveTraceSurfaceFlinger(nextEntryButton, prevEntryButton);
expect(spy).toHaveBeenCalled();
});
@@ -355,32 +331,26 @@
await component.timeline?.onWinscopeEvent(new TraceAddRequest(searchTrace));
expectSelectedTraceTypes(allTraceTypes);
- await openSelectPanel();
+ await dom.openMatSelect();
- const matOptions =
- document.documentElement.querySelectorAll<HTMLInputElement>('mat-option');
- await UnitTestUtils.checkTooltips(
- Array.from(matOptions),
- [
- 'test query, 0',
- 'mock_screen_recording',
- 'file descriptor',
- 'file descriptor',
- 'file descriptor',
- 'Test Window, mock_view_capture',
- ],
- fixture,
- );
- expect(matOptions.item(0).textContent).toContain('Search test query');
- const sfOption = matOptions.item(2);
- expect(sfOption.textContent).toContain('Surface Flinger');
- expect(sfOption.ariaDisabled).toEqual('true');
+ const matOptions = dom.getMatSelectPanel().findAll('mat-option');
+ await checkTooltips(Array.from(matOptions), [
+ 'test query, 0',
+ 'mock_screen_recording',
+ 'file descriptor',
+ 'file descriptor',
+ 'file descriptor',
+ 'Test Window, mock_view_capture',
+ ]);
+ matOptions[0].checkText('Search test query');
+ const sfOption = matOptions[2];
+ sfOption.checkText('Surface Flinger');
+ expect(sfOption.getHTMLElement().ariaDisabled).toEqual('true');
for (const i of [1, 3, 4]) {
- expect(matOptions.item(i).ariaDisabled).toEqual('false');
+ expect(matOptions[1].getHTMLElement().ariaDisabled).toEqual('false');
}
- matOptions.item(3).click();
- fixture.detectChanges();
+ matOptions[3].click();
const expectedTypes = [
TraceType.SEARCH,
TraceType.SCREEN_RECORDING,
@@ -389,58 +359,45 @@
TraceType.VIEW_CAPTURE,
];
expectSelectedTraceTypes(expectedTypes);
- const traceIcons = Array.from(
- htmlElement.querySelectorAll<HTMLElement>(
- '#trace-selector .shown-selection .mat-icon',
- ),
- ).slice(1);
+ const traceIcons = dom
+ .findAll('#trace-selector .shown-selection .mat-icon')
+ .slice(1);
traceIcons.forEach((el, index) => {
- const text = el.textContent?.trim();
const expectedType = expectedTypes[index];
- expect(text).toEqual(TRACE_INFO[expectedType].icon);
+ el.checkTextExact(TRACE_INFO[expectedType].icon);
});
- await UnitTestUtils.checkTooltips(
- traceIcons,
- [
- 'Search test query',
- 'Screen Recording mock_screen_recording',
- TRACE_INFO[TraceType.SURFACE_FLINGER].name,
- TRACE_INFO[TraceType.PROTO_LOG].name,
- 'View Capture Test Window',
- ],
- fixture,
- );
+ await checkTooltips(traceIcons, [
+ 'Search test query',
+ 'Screen Recording mock_screen_recording',
+ TRACE_INFO[TraceType.SURFACE_FLINGER].name,
+ TRACE_INFO[TraceType.PROTO_LOG].name,
+ 'View Capture Test Window',
+ ]);
- matOptions.item(3).click();
- fixture.detectChanges();
+ matOptions[3].click();
expectSelectedTraceTypes(allTraceTypes);
- const newIcons = htmlElement.querySelectorAll(
- '#trace-selector .shown-selection .mat-icon',
- );
+ const newIcons = dom.findAll('#trace-selector .shown-selection .mat-icon');
expect(
Array.from(newIcons)
- .map((icon) => icon.textContent?.trim())
+ .map((icon) => icon.getText())
.slice(1),
).toEqual(allTraceTypes.map((type) => TRACE_INFO[type].icon));
});
it('update name and disables option for dumps', async () => {
- loadAllTraces(component, fixture, false);
- await openSelectPanel();
+ loadAllTraces(component, dom, false);
+ await dom.openMatSelect();
- const matOptions =
- document.documentElement.querySelectorAll<HTMLInputElement>('mat-option'); // [WM, SF, SR, ProtoLog, VC]
+ const matOptions = dom.getMatSelectPanel().findAll('mat-option'); // [WM, SF, SR, ProtoLog, VC]
for (const i of [0, 2, 4]) {
- expect(matOptions.item(i).ariaDisabled).toEqual('false');
+ expect(matOptions[i].getHTMLElement().ariaDisabled).toEqual('false');
}
for (const i of [1, 3]) {
- expect(matOptions.item(i).ariaDisabled).toEqual('true');
+ expect(matOptions[i].getHTMLElement().ariaDisabled).toEqual('true');
}
- expect(matOptions.item(3).textContent).toContain('ProtoLog Dump');
- expect(matOptions.item(4).textContent).toContain(
- 'View Capture Test Window',
- );
+ matOptions[3].checkText('ProtoLog Dump');
+ matOptions[4].checkText('View Capture Test Window');
});
it('next button disabled if no next entry', () => {
@@ -451,22 +408,20 @@
100n,
);
- const nextEntryButton = assertDefined(
- htmlElement.querySelector('#next_entry_button'),
- );
- expect(nextEntryButton.getAttribute('disabled')).toBeFalsy();
+ const nextEntryButton = dom.get(nextEntrySelector);
+ nextEntryButton.checkDisabled(false);
timelineData.setPosition(position90);
- fixture.detectChanges();
- expect(nextEntryButton.getAttribute('disabled')).toBeFalsy();
+ dom.detectChanges();
+ nextEntryButton.checkDisabled(false);
timelineData.setPosition(position110);
- fixture.detectChanges();
- expect(nextEntryButton.getAttribute('disabled')).toBeTruthy();
+ dom.detectChanges();
+ nextEntryButton.checkDisabled(true);
timelineData.setPosition(position112);
- fixture.detectChanges();
- expect(nextEntryButton.getAttribute('disabled')).toBeTruthy();
+ dom.detectChanges();
+ nextEntryButton.checkDisabled(true);
});
it('prev button disabled if no prev entry', () => {
@@ -476,36 +431,30 @@
expect(timelineData.getCurrentPosition()?.timestamp.getValueNs()).toEqual(
100n,
);
- const prevEntryButton = assertDefined(
- htmlElement.querySelector('#prev_entry_button'),
- );
- expect(prevEntryButton.getAttribute('disabled')).toBeTruthy();
+ const prevEntryButton = dom.get(prevEntrySelector);
+ prevEntryButton.checkDisabled(true);
timelineData.setPosition(position90);
- fixture.detectChanges();
- expect(prevEntryButton.getAttribute('disabled')).toBeTruthy();
+ dom.detectChanges();
+ prevEntryButton.checkDisabled(true);
timelineData.setPosition(position110);
- fixture.detectChanges();
- expect(prevEntryButton.getAttribute('disabled')).toBeFalsy();
+ dom.detectChanges();
+ prevEntryButton.checkDisabled(false);
timelineData.setPosition(position112);
- fixture.detectChanges();
- expect(prevEntryButton.getAttribute('disabled')).toBeFalsy();
+ dom.detectChanges();
+ prevEntryButton.checkDisabled(false);
});
it('next button enabled for different active viewers', async () => {
loadSfWmTraces();
- const nextEntryButton = assertDefined(
- htmlElement.querySelector('#next_entry_button'),
- );
-
- expect(nextEntryButton.getAttribute('disabled')).toBeNull();
+ const nextEntryButton = dom.get(nextEntrySelector);
+ nextEntryButton.checkDisabled(false);
await updateActiveTrace(TraceType.WINDOW_MANAGER);
- fixture.detectChanges();
-
- expect(nextEntryButton.getAttribute('disabled')).toBeNull();
+ dom.detectChanges();
+ nextEntryButton.checkDisabled(false);
});
it('changes timestamp on next entry button press', () => {
@@ -516,9 +465,7 @@
.getCurrentPosition()
?.timestamp.getValueNs(),
).toEqual(100n);
- const nextEntryButton = assertDefined(
- htmlElement.querySelector<HTMLElement>('#next_entry_button'),
- );
+ const nextEntryButton = dom.get(nextEntrySelector);
testCurrentTimestampOnButtonClick(nextEntryButton, position105, 110n);
@@ -541,9 +488,7 @@
.getCurrentPosition()
?.timestamp.getValueNs(),
).toEqual(100n);
- const prevEntryButton = assertDefined(
- htmlElement.querySelector<HTMLElement>('#prev_entry_button'),
- );
+ const prevEntryButton = dom.get(prevEntrySelector);
// In this state we are already on the first entry at timestamp 100, so
// there is no entry to move to before and we just don't update the timestamp
@@ -568,27 +513,22 @@
const spyNextEntry = spyOn(timelineComponent, 'moveToNextEntry');
const spyPrevEntry = spyOn(timelineComponent, 'moveToPreviousEntry');
- document.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowRight'}));
- fixture.detectChanges();
+ dom.keydownArrowRight(true);
expect(spyNextEntry).toHaveBeenCalled();
- const formElement = htmlElement.querySelector('.time-input input');
+ const formElement = dom.get('.time-input input').getHTMLElement();
const focusInEvent = new FocusEvent('focusin');
Object.defineProperty(focusInEvent, 'target', {value: formElement});
- document.dispatchEvent(focusInEvent);
- fixture.detectChanges();
+ dom.dispatchEventInDocument(focusInEvent);
- document.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowLeft'}));
- fixture.detectChanges();
+ dom.keydownArrowLeft(true);
expect(spyPrevEntry).not.toHaveBeenCalled();
const focusOutEvent = new FocusEvent('focusout');
Object.defineProperty(focusOutEvent, 'target', {value: formElement});
- document.dispatchEvent(focusOutEvent);
- fixture.detectChanges();
+ dom.dispatchEventInDocument(focusOutEvent);
- document.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowLeft'}));
- fixture.detectChanges();
+ dom.keydownArrowLeft(true);
expect(spyPrevEntry).toHaveBeenCalled();
});
@@ -601,9 +541,7 @@
?.timestamp.getValueNs(),
).toEqual(100n);
- const timeInputField = assertDefined(
- document.querySelector<HTMLInputElement>('.time-input.nano'),
- );
+ const timeInputField = dom.get('.time-input.nano');
testCurrentTimestampOnTimeInput(
timeInputField,
@@ -647,9 +585,7 @@
?.timestamp.getValueNs(),
).toEqual(100n);
- const timeInputField = assertDefined(
- document.querySelector<HTMLInputElement>('.time-input.human'),
- );
+ const timeInputField = dom.get('.time-input.human');
testCurrentTimestampOnTimeInput(
timeInputField,
@@ -698,9 +634,7 @@
?.timestamp.valueOf(),
).toEqual(100n);
- const timeInputField = assertDefined(
- document.querySelector<HTMLInputElement>('.time-input.human'),
- );
+ const timeInputField = dom.get('.time-input.human');
testCurrentTimestampOnTimeInput(
timeInputField,
@@ -719,9 +653,7 @@
?.timestamp.valueOf(),
).toEqual(100n);
- const timeInputField = assertDefined(
- document.querySelector<HTMLInputElement>('.time-input.human'),
- );
+ const timeInputField = dom.get('.time-input.human');
testCurrentTimestampOnTimeInput(
timeInputField,
@@ -752,7 +684,7 @@
],
firstTimeline,
);
- await openSelectPanel();
+ await dom.openMatSelect();
clickTraceFromSelectPanel(2);
clickTraceFromSelectPanel(3);
clickTraceFromSelectPanel(4);
@@ -763,7 +695,10 @@
const secondFixture = TestBed.createComponent(TestHostComponent);
const secondHost = secondFixture.componentInstance;
- loadAllTraces(secondHost, secondFixture);
+ loadAllTraces(
+ secondHost,
+ new DOMTestHelper(secondFixture, secondFixture.nativeElement),
+ );
const secondTimeline = assertDefined(secondHost.timeline);
expectSelectedTraceTypes(
[TraceType.SCREEN_RECORDING, TraceType.SURFACE_FLINGER],
@@ -778,7 +713,10 @@
const thirdFixture = TestBed.createComponent(TestHostComponent);
const thirdHost = thirdFixture.componentInstance;
- loadAllTraces(thirdHost, thirdFixture);
+ loadAllTraces(
+ thirdHost,
+ new DOMTestHelper(thirdFixture, thirdFixture.nativeElement),
+ );
const thirdTimeline = assertDefined(thirdHost.timeline);
expectSelectedTraceTypes(
[
@@ -804,7 +742,7 @@
firstTimeline,
);
await updateActiveTrace(TraceType.PROTO_LOG);
- await openSelectPanel();
+ await dom.openMatSelect();
clickTraceFromSelectPanel(1);
clickTraceFromSelectPanel(4);
expectSelectedTraceTypes(
@@ -818,7 +756,10 @@
const secondFixture = TestBed.createComponent(TestHostComponent);
const secondHost = secondFixture.componentInstance;
- loadAllTraces(secondHost, secondFixture);
+ loadAllTraces(
+ secondHost,
+ new DOMTestHelper(secondFixture, secondFixture.nativeElement),
+ );
const secondTimeline = assertDefined(secondHost.timeline);
expectSelectedTraceTypes(
[
@@ -834,13 +775,16 @@
it('does not apply stored trace deselection if only one timestamp available', async () => {
loadAllTraces();
await updateActiveTrace(TraceType.PROTO_LOG);
- await openSelectPanel();
+ await dom.openMatSelect();
clickTraceFromSelectPanel(2);
const secondFixture = TestBed.createComponent(TestHostComponent);
const secondHost = secondFixture.componentInstance;
const secondElement = secondFixture.nativeElement;
- await loadTracesWithOneTimestamp(secondHost, secondFixture);
+ await loadTracesWithOneTimestamp(
+ secondHost,
+ new DOMTestHelper(secondFixture, secondFixture.nativeElement),
+ );
const shownSelection = assertDefined(
secondElement.querySelector('#trace-selector .shown-selection'),
@@ -861,7 +805,7 @@
],
component.timeline,
);
- await openSelectPanel();
+ await dom.openMatSelect();
clickTraceFromSelectPanel(3);
clickTraceFromSelectPanel(4);
expectSelectedTraceTypes(
@@ -873,7 +817,7 @@
component.timeline,
);
await updateActiveTrace(TraceType.PROTO_LOG);
- fixture.detectChanges();
+ dom.detectChanges();
expectSelectedTraceTypes(
[
TraceType.SCREEN_RECORDING,
@@ -886,7 +830,10 @@
const secondFixture = TestBed.createComponent(TestHostComponent);
const secondHost = secondFixture.componentInstance;
- loadAllTraces(secondHost, secondFixture);
+ loadAllTraces(
+ secondHost,
+ new DOMTestHelper(secondFixture, secondFixture.nativeElement),
+ );
const secondTimeline = assertDefined(secondHost.timeline);
expectSelectedTraceTypes(
[
@@ -910,7 +857,7 @@
],
component.timeline,
);
- await openSelectPanel();
+ await dom.openMatSelect();
clickTraceFromSelectPanel(3);
clickTraceFromSelectPanel(4);
expectSelectedTraceTypes(
@@ -924,7 +871,10 @@
const secondFixture = TestBed.createComponent(TestHostComponent);
const secondHost = secondFixture.componentInstance;
- loadSfWmTraces(secondHost, secondFixture);
+ loadSfWmTraces(
+ secondHost,
+ new DOMTestHelper(secondFixture, secondFixture.nativeElement),
+ );
const secondTimeline = assertDefined(secondHost.timeline);
expectSelectedTraceTypes(
[TraceType.SURFACE_FLINGER, TraceType.WINDOW_MANAGER],
@@ -933,7 +883,10 @@
const thirdFixture = TestBed.createComponent(TestHostComponent);
const thirdHost = thirdFixture.componentInstance;
- loadAllTraces(thirdHost, thirdFixture);
+ loadAllTraces(
+ thirdHost,
+ new DOMTestHelper(thirdFixture, thirdFixture.nativeElement),
+ );
const thirdTimeline = assertDefined(thirdHost.timeline);
expectSelectedTraceTypes(
[
@@ -951,13 +904,16 @@
[TraceType.SURFACE_FLINGER, TraceType.WINDOW_MANAGER],
component.timeline,
);
- await openSelectPanel();
+ await dom.openMatSelect();
clickTraceFromSelectPanel(1);
expectSelectedTraceTypes([TraceType.SURFACE_FLINGER], component.timeline);
const secondFixture = TestBed.createComponent(TestHostComponent);
const secondHost = secondFixture.componentInstance;
- loadAllTraces(secondHost, secondFixture);
+ loadAllTraces(
+ secondHost,
+ new DOMTestHelper(secondFixture, secondFixture.nativeElement),
+ );
const secondTimeline = assertDefined(secondHost.timeline);
expectSelectedTraceTypes(
[
@@ -976,17 +932,12 @@
expect(timelineComponent.bookmarks).toEqual([]);
expect(timelineComponent.currentPositionBookmarked()).toBeFalse();
- const bookmarkIcon = assertDefined(
- htmlElement.querySelector<HTMLElement>('.bookmark-icon'),
- );
- bookmarkIcon.click();
- fixture.detectChanges();
+ const bookmarkIcon = dom.findAndClick('.bookmark-icon');
expect(timelineComponent.bookmarks).toEqual([time100]);
expect(timelineComponent.currentPositionBookmarked()).toBeTrue();
bookmarkIcon.click();
- fixture.detectChanges();
expect(timelineComponent.bookmarks).toEqual([]);
expect(timelineComponent.currentPositionBookmarked()).toBeFalse();
});
@@ -1029,7 +980,7 @@
loadSfWmTraces();
const timelineComponent = assertDefined(component.timeline);
timelineComponent.bookmarks = [time100, time101, time112];
- fixture.detectChanges();
+ dom.detectChanges();
openContextMenu();
clickRemoveAllBookmarksOption();
@@ -1063,10 +1014,8 @@
).and.returnValue(Promise.resolve(trace));
const canvas = miniTimelineComponent.getCanvas();
canvas.dispatchEvent(new MouseEvent('mousedown'));
- fixture.detectChanges();
- await fixture.whenStable();
- fixture.detectChanges();
- await fixture.whenStable();
+ await dom.detectChangesAndWaitStable();
+ await dom.detectChangesAndWaitStable();
expect(activeTrace).toEqual(trace);
expect(position).toBeDefined();
@@ -1112,11 +1061,10 @@
loadSfWmTraces();
const timelineComponent = assertDefined(component.timeline);
timelineComponent.isDisabled = true;
- fixture.detectChanges();
+ dom.detectChanges();
const spyNextEntry = spyOn(timelineComponent, 'moveToNextEntry');
- document.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowRight'}));
- fixture.detectChanges();
+ dom.keydownArrowRight(true);
expect(spyNextEntry).not.toHaveBeenCalled();
});
@@ -1131,10 +1079,7 @@
spyOnProperty(wheelEvent, 'deltaY').and.returnValue(-200);
spyOnProperty(wheelEvent, 'deltaX').and.returnValue(0);
spyOnProperty(wheelEvent, 'y').and.returnValue(10);
- assertDefined(htmlElement.querySelector('single-timeline')).dispatchEvent(
- wheelEvent,
- );
- fixture.detectChanges();
+ dom.get('single-timeline').dispatchEvent(wheelEvent);
expect(expandedDrawSpy).toHaveBeenCalledTimes(5); // 3 entries total + 2 selected
expect(miniDrawSpy).toHaveBeenCalledTimes(1); // all on one canvas so spy called once
@@ -1142,12 +1087,9 @@
expandedDrawSpy.calls.reset();
miniDrawSpy.calls.reset();
spyOnProperty(wheelEvent, 'target').and.returnValue(
- assertDefined(htmlElement.querySelector('#mini-timeline-canvas')),
+ dom.get('#mini-timeline-canvas').getHTMLElement(),
);
- assertDefined(htmlElement.querySelector('mini-timeline')).dispatchEvent(
- wheelEvent,
- );
- fixture.detectChanges();
+ dom.get('mini-timeline').dispatchEvent(wheelEvent);
expect(expandedDrawSpy).toHaveBeenCalledTimes(4); // 2 entries total + 2 selected
expect(miniDrawSpy).toHaveBeenCalledTimes(1);
});
@@ -1161,15 +1103,12 @@
const clickEvent = new MouseEvent('mousedown');
spyOnProperty(clickEvent, 'offsetX').and.returnValue(0);
spyOnProperty(clickEvent, 'offsetY').and.returnValue(0);
- assertDefined(
- htmlElement.querySelector<HTMLElement>('single-timeline #canvas'),
- ).dispatchEvent(clickEvent);
- fixture.detectChanges();
+ dom.get('single-timeline #canvas').dispatchEvent(clickEvent);
expect(expandedDrawSpy).toHaveBeenCalledTimes(3); // redraws SF timeline row
expect(miniDrawSpy).toHaveBeenCalledTimes(1); // all on one canvas so spy called once
});
- function loadSfWmTraces(hostComponent = component, hostFixture = fixture) {
+ function loadSfWmTraces(hostComponent = component, domHelper = dom) {
const traces = new TracesBuilder()
.setTimestamps(TraceType.SURFACE_FLINGER, [time100, time110])
.setTimestamps(TraceType.WINDOW_MANAGER, [
@@ -1188,12 +1127,12 @@
);
timelineData.setPosition(position100);
hostComponent.allTraces = hostComponent.timelineData.getTraces();
- hostFixture.detectChanges();
+ domHelper.detectChanges();
}
function loadAllTraces(
hostComponent = component,
- hostFixture = fixture,
+ domHelper = dom,
loadAllTraces = true,
) {
const traces = new TracesBuilder()
@@ -1235,7 +1174,7 @@
TimestampConverterUtils.TIMESTAMP_CONVERTER,
);
hostComponent.allTraces = traces;
- hostFixture.detectChanges();
+ domHelper.detectChanges();
}
function loadTracesWithLargeTimeRange() {
@@ -1262,7 +1201,7 @@
);
timelineData.setPosition(position100);
component.allTraces = timelineData.getTraces();
- fixture.detectChanges();
+ dom.detectChanges();
}
function getLoadedTrace(type: TraceType): Trace<object> {
@@ -1275,7 +1214,7 @@
async function loadTracesWithOneTimestamp(
hostComponent = component,
- hostFixture = fixture,
+ domHelper = dom,
) {
const traces = new TracesBuilder()
.setTimestamps(TraceType.SURFACE_FLINGER, [])
@@ -1287,9 +1226,8 @@
TimestampConverterUtils.TIMESTAMP_CONVERTER,
);
hostComponent.allTraces = traces;
- hostFixture.detectChanges();
- await hostFixture.whenStable();
- hostFixture.detectChanges();
+ await domHelper.detectChangesAndWaitStable();
+ domHelper.detectChanges();
}
async function updateActiveTrace(type: TraceType) {
@@ -1311,121 +1249,101 @@
}
function testCurrentTimestampOnButtonClick(
- button: HTMLElement,
+ button: DOMTestHelper<TestHostComponent>,
pos: TracePosition,
expectedNs: bigint,
) {
const timelineData = assertDefined(component.timelineData);
timelineData.setPosition(pos);
- fixture.detectChanges();
+ dom.detectChanges();
button.click();
- fixture.detectChanges();
expect(timelineData.getCurrentPosition()?.timestamp.getValueNs()).toEqual(
expectedNs,
);
}
function testCurrentTimestampOnTimeInput(
- inputField: HTMLInputElement,
+ inputField: DOMTestHelper<TestHostComponent>,
pos: TracePosition,
textInput: string,
expectedNs: bigint,
) {
const timelineData = assertDefined(component.timelineData);
timelineData.setPosition(pos);
- fixture.detectChanges();
+ dom.detectChanges();
- inputField.value = textInput;
+ inputField.updateValue(textInput);
inputField.dispatchEvent(new Event('change'));
- fixture.detectChanges();
expect(timelineData.getCurrentPosition()?.timestamp.getValueNs()).toEqual(
expectedNs,
);
}
- async function openSelectPanel() {
- const selectTrigger = assertDefined(
- htmlElement.querySelector<HTMLElement>('.mat-select-trigger'),
- );
- selectTrigger.click();
- fixture.detectChanges();
- await fixture.whenStable();
- }
-
function clickTraceFromSelectPanel(index: number) {
- const matOptions = assertDefined(
- document.documentElement.querySelectorAll<HTMLElement>('mat-option'),
- );
- matOptions.item(index).click();
- fixture.detectChanges();
+ dom.getMatSelectPanel().findAndClickByIndex('mat-option', index);
}
function checkActiveTraceSurfaceFlinger(
- nextEntryButton: HTMLElement,
- prevEntryButton: HTMLElement,
+ nextEntryButton: DOMTestHelper<TestHostComponent>,
+ prevEntryButton: DOMTestHelper<TestHostComponent>,
) {
testCurrentTimestampOnButtonClick(prevEntryButton, position110, 100n);
- expect(prevEntryButton.getAttribute('disabled')).toEqual('true');
- expect(nextEntryButton.getAttribute('disabled')).toBeNull();
+ prevEntryButton.checkDisabled(true);
+ nextEntryButton.checkDisabled(false);
testCurrentTimestampOnButtonClick(nextEntryButton, position100, 110n);
- expect(prevEntryButton.getAttribute('disabled')).toBeNull();
- expect(nextEntryButton.getAttribute('disabled')).toEqual('true');
+ prevEntryButton.checkDisabled(false);
+ nextEntryButton.checkDisabled(true);
}
function checkActiveTraceWindowManager(
- nextEntryButton: HTMLElement,
- prevEntryButton: HTMLElement,
+ nextEntryButton: DOMTestHelper<TestHostComponent>,
+ prevEntryButton: DOMTestHelper<TestHostComponent>,
) {
testCurrentTimestampOnButtonClick(prevEntryButton, position90, 90n);
- expect(prevEntryButton.getAttribute('disabled')).toEqual('true');
- expect(nextEntryButton.getAttribute('disabled')).toBeNull();
+ prevEntryButton.checkDisabled(true);
+ nextEntryButton.checkDisabled(false);
testCurrentTimestampOnButtonClick(nextEntryButton, position90, 101n);
- expect(prevEntryButton.getAttribute('disabled')).toBeNull();
- expect(nextEntryButton.getAttribute('disabled')).toBeNull();
+ prevEntryButton.checkDisabled(false);
+ nextEntryButton.checkDisabled(false);
testCurrentTimestampOnButtonClick(nextEntryButton, position110, 112n);
- expect(prevEntryButton.getAttribute('disabled')).toBeNull();
- expect(nextEntryButton.getAttribute('disabled')).toEqual('true');
+ prevEntryButton.checkDisabled(false);
+ nextEntryButton.checkDisabled(true);
}
function checkActiveTraceHasOneEntry(
- nextEntryButton: HTMLElement,
- prevEntryButton: HTMLElement,
+ nextEntryButton: DOMTestHelper<TestHostComponent>,
+ prevEntryButton: DOMTestHelper<TestHostComponent>,
) {
- expect(prevEntryButton.getAttribute('disabled')).toEqual('true');
- expect(nextEntryButton.getAttribute('disabled')).toEqual('true');
+ prevEntryButton.checkDisabled(true);
+ nextEntryButton.checkDisabled(true);
}
function checkNoTimelineNavigation() {
const timelineComponent = assertDefined(component.timeline);
// no expand button
expect(
- htmlElement.querySelector(`.${timelineComponent.TOGGLE_BUTTON_CLASS}`),
- ).toBeNull();
+ dom.find(`.${timelineComponent.TOGGLE_BUTTON_CLASS}`),
+ ).toBeUndefined();
// no timelines shown
- const miniTimelineElement = fixture.debugElement.query(
- By.directive(MiniTimelineComponent),
- );
- expect(miniTimelineElement).toBeFalsy();
+ const miniTimelineElement = dom.findByDirective(MiniTimelineComponent);
+ expect(miniTimelineElement).toBeUndefined();
// arrow key presses don't do anything
const spyNextEntry = spyOn(timelineComponent, 'moveToNextEntry');
const spyPrevEntry = spyOn(timelineComponent, 'moveToPreviousEntry');
- document.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowRight'}));
- fixture.detectChanges();
+ dom.keydownArrowRight(true);
expect(spyNextEntry).not.toHaveBeenCalled();
- document.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowLeft'}));
- fixture.detectChanges();
+ dom.keydownArrowLeft(true);
expect(spyPrevEntry).not.toHaveBeenCalled();
}
function openContextMenu(xOffset = 0, clickBelowMarker = false) {
- const miniTimelineCanvas = assertDefined(
- htmlElement.querySelector<HTMLElement>('#mini-timeline-canvas'),
- );
+ const miniTimelineCanvas = dom.get('#mini-timeline-canvas');
+ const canvasEl = miniTimelineCanvas.getHTMLElement();
const yOffset = clickBelowMarker
? assertDefined(component.timeline?.miniTimeline?.drawer?.getHeight()) /
6 +
@@ -1434,53 +1352,37 @@
const event = new MouseEvent('contextmenu');
spyOnProperty(event, 'offsetX').and.returnValue(
- miniTimelineCanvas.offsetLeft +
- miniTimelineCanvas.offsetWidth / 2 +
- xOffset,
+ canvasEl.offsetLeft + canvasEl.offsetWidth / 2 + xOffset,
);
spyOnProperty(event, 'offsetY').and.returnValue(
- miniTimelineCanvas.offsetTop + yOffset,
+ canvasEl.offsetTop + yOffset,
);
miniTimelineCanvas.dispatchEvent(event);
- fixture.detectChanges();
}
function clickToggleBookmarkOption() {
- const menu = assertDefined(document.querySelector('.context-menu'));
- const toggleOption = assertDefined(
- menu.querySelector<HTMLElement>('.context-menu-item'),
- );
- toggleOption.click();
- fixture.detectChanges();
+ const menu = dom.getInDocument('.context-menu');
+ menu.findAndClick('.context-menu-item');
}
function clickRemoveAllBookmarksOption() {
- const menu = assertDefined(document.querySelector('.context-menu'));
- const options = assertDefined(
- menu.querySelectorAll<HTMLElement>('.context-menu-item'),
- );
- options.item(1).click();
- fixture.detectChanges();
+ const menu = dom.getInDocument('.context-menu');
+ menu.findAndClickByIndex('.context-menu-item', 1);
}
function checkTimelineEnabled() {
- expect(htmlElement.querySelector('.disabled-component')).toBeNull();
- expect(htmlElement.querySelector('.disabled-message')).toBeNull();
+ expect(dom.find('.disabled-component')).toBeUndefined();
+ expect(dom.find('.disabled-message')).toBeUndefined();
}
function checkTimelineDisabled() {
- expect(htmlElement.querySelector('.disabled-component')).toBeTruthy();
- expect(htmlElement.querySelector('.disabled-message')).toBeTruthy();
+ expect(dom.find('.disabled-component')).toBeDefined();
+ expect(dom.find('.disabled-message')).toBeDefined();
}
function openExpandedTimeline() {
const timelineComponent = assertDefined(component.timeline);
- assertDefined(
- htmlElement.querySelector<HTMLElement>(
- `.${timelineComponent.TOGGLE_BUTTON_CLASS}`,
- ),
- ).click();
- fixture.detectChanges();
+ dom.findAndClick(`.${timelineComponent.TOGGLE_BUTTON_CLASS}`);
}
@Component({