chrome-devtools-frontend
Version:
Chrome DevTools UI
272 lines (243 loc) • 11.7 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 Common from '../../core/common/common.js';
import * as Host from '../../core/host/host.js';
import {expectCalled} from '../../testing/ExpectStubCall.js';
import {getVeId} from '../../testing/VisualLoggingHelpers.js';
import * as VisualLogging from './visual_logging-testing.js';
describe('LoggingEvents', () => {
let parent: Element;
let element: Element;
let veid: number;
let throttler: Common.Throttler.Throttler;
beforeEach(() => {
parent = document.createElement('div');
element = document.createElement('div');
VisualLogging.LoggingState.getOrCreateLoggingState(parent, {ve: 1});
VisualLogging.LoggingState.getOrCreateLoggingState(element, {ve: 1, context: '42'}, parent);
veid = getVeId(element);
throttler = new Common.Throttler.Throttler(1000000);
});
afterEach(async () => {
await throttler.schedule(async () => {}, Common.Throttler.Scheduling.AS_SOON_AS_POSSIBLE);
});
async function assertThrottled(stub: sinon.SinonStub) {
await new Promise(resolve => setTimeout(resolve, 0));
sinon.assert.notCalled(stub);
await throttler.process?.();
sinon.assert.calledOnce(stub);
}
it('calls UI binding to log an impression', async () => {
const recordImpression = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordImpression',
);
await VisualLogging.LoggingEvents.logImpressions([element, parent]);
sinon.assert.calledOnce(recordImpression);
assert.sameDeepMembers(recordImpression.firstCall.firstArg.impressions, [
{id: veid, type: 1, context: 42, parent: getVeId(parent), height: 0, width: 0},
{id: getVeId(parent), type: 1, height: 0, width: 0},
]);
});
it('calls UI binding to log a click', async () => {
const recordClick = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordClick',
);
// @ts-expect-error
const event = new MouseEvent('click', {button: 0, sourceCapabilities: new InputDeviceCapabilities()});
VisualLogging.LoggingEvents.logClick(throttler)(element, event);
await assertThrottled(recordClick);
assert.deepEqual(recordClick.firstCall.firstArg, {veid, mouseButton: 0, doubleClick: false});
});
it('does not set mouse button for synthetic clicks', async () => {
const recordClick = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordClick',
);
const event = new MouseEvent('click', {button: 0});
VisualLogging.LoggingEvents.logClick(throttler)(element, event);
await assertThrottled(recordClick);
assert.deepEqual(recordClick.firstCall.firstArg, {veid, doubleClick: false});
});
it('calls UI binding to log a double click', async () => {
const recordClick = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordClick',
);
const event = new MouseEvent('dblclick', {button: 1});
VisualLogging.LoggingEvents.logClick(throttler)(element, event, {doubleClick: true});
await assertThrottled(recordClick);
assert.deepEqual(recordClick.firstCall.firstArg, {veid, doubleClick: true});
});
it('calls UI binding to log a change', async () => {
const recordChange = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordChange',
);
await VisualLogging.LoggingEvents.logChange(element);
sinon.assert.calledOnce(recordChange);
assert.deepEqual(recordChange.firstCall.firstArg, {veid});
});
it('calls UI binding to log a change of specific type', async () => {
const recordChange = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordChange',
);
VisualLogging.LoggingState.getLoggingState(element)!.pendingChangeContext = 'instertText';
await VisualLogging.LoggingEvents.logChange(element);
sinon.assert.calledOnce(recordChange);
assert.deepEqual(recordChange.firstCall.firstArg, {veid, context: 296063892});
});
it('calls UI binding to log a keydown with any code', async () => {
const recordKeyDown = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordKeyDown',
);
const event = new KeyboardEvent('keydown');
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event);
await assertThrottled(recordKeyDown);
assert.deepEqual(recordKeyDown.firstCall.firstArg, {veid});
});
it('calls UI binding to log a keydown with a matching code', async () => {
const recordKeyDown = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordKeyDown',
);
const event = new KeyboardEvent('keydown', {code: 'Enter', key: 'Enter'});
VisualLogging.LoggingState.getLoggingState(element)!.config.track = {keydown: 'Enter|Escape'};
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event);
await assertThrottled(recordKeyDown);
assert.deepEqual(recordKeyDown.firstCall.firstArg, {veid, context: 513111094});
});
it('calls UI binding to log a keydown with a matching key', async () => {
const recordKeyDown = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordKeyDown',
);
const event = new KeyboardEvent('keydown', {code: 'Period', key: '>'});
VisualLogging.LoggingState.getLoggingState(element)!.config.track = {keydown: '>'};
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event);
await assertThrottled(recordKeyDown);
assert.deepEqual(recordKeyDown.firstCall.firstArg, {veid: getVeId(element), context: -1098575095});
});
it('calls UI binding to log a keydown with an provided context', async () => {
const recordKeyDown = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordKeyDown',
);
const event = new KeyboardEvent('keydown', {code: 'Enter'});
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event, '21');
await assertThrottled(recordKeyDown);
assert.deepEqual(recordKeyDown.firstCall.firstArg, {veid, context: 21});
});
it('throttles subsequent keydowns', async () => {
const recordKeyDown = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordKeyDown',
);
const event = new KeyboardEvent('keydown', {code: 'Enter'});
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event);
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event);
await assertThrottled(recordKeyDown);
});
it('does not drop keydowns with a specific context', async () => {
const recordKeyDown = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordKeyDown',
);
const event = new KeyboardEvent('keydown', {code: 'Enter'});
sinon.stub(event, 'currentTarget').value(element);
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event, '1');
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event, '2');
await new Promise(resolve => setTimeout(resolve, 0));
sinon.assert.calledOnce(recordKeyDown);
await throttler.process?.();
sinon.assert.calledTwice(recordKeyDown);
assert.deepEqual(recordKeyDown.firstCall.firstArg, {veid, context: 1});
assert.deepEqual(recordKeyDown.secondCall.firstArg, {veid, context: 2});
});
it('throttles subsequent keydowns with the same context', async () => {
const recordKeyDown = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordKeyDown',
);
const event = new KeyboardEvent('keydown', {code: 'Enter'});
sinon.stub(event, 'currentTarget').value(element);
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event, '1');
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event, '1');
await assertThrottled(recordKeyDown);
assert.deepEqual(recordKeyDown.firstCall.firstArg, {veid, context: 1});
});
it('does not call UI binding to log a keydown with a non-matching code', async () => {
const recordKeyDown = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordKeyDown',
);
const event = new KeyboardEvent('keydown', {code: 'KeyQ'});
VisualLogging.LoggingState.getLoggingState(element)!.config.track = {keydown: 'Enter|Escape'};
void VisualLogging.LoggingEvents.logKeyDown(throttler)(element, event);
sinon.assert.notCalled(recordKeyDown);
});
it('calls UI binding to log a hover event', async () => {
const recordHover = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordHover',
);
const event = new MouseEvent('click', {button: 1});
sinon.stub(event, 'currentTarget').value(element);
void VisualLogging.LoggingEvents.logHover(new Common.Throttler.Throttler(0))(event);
await expectCalled(recordHover);
assert.deepEqual(recordHover.firstCall.firstArg, {veid});
});
it('calls UI binding to log a drag event', async () => {
const recordDrag = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordDrag',
);
const event = new MouseEvent('click', {button: 1});
sinon.stub(event, 'currentTarget').value(element);
void VisualLogging.LoggingEvents.logDrag(throttler)(event);
await assertThrottled(recordDrag);
assert.deepEqual(recordDrag.firstCall.firstArg, {veid});
});
it('calls UI binding to log a resize event', async () => {
const recordResize = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordResize',
);
VisualLogging.LoggingEvents.logResize(element, new DOMRect(0, 0, 100, 50));
assert.deepEqual(recordResize.firstCall.firstArg, {veid, width: 100, height: 50});
});
it('throttles calls UI binding to log a resize event', async () => {
const recordResize = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordResize',
);
VisualLogging.LoggingEvents.logResize(element, new DOMRect(0, 0, 100, 50));
assert.deepEqual(recordResize.firstCall.firstArg, {veid, width: 100, height: 50});
});
it('calls UI binding to log a setting access event', async () => {
const recordSettingAccess = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordSettingAccess',
);
await VisualLogging.LoggingEvents.logSettingAccess('test-setting', 'test-value');
assert.deepEqual(
recordSettingAccess.lastCall.firstArg, {name: -1361026584, numeric_value: undefined, string_value: 856719891});
await VisualLogging.LoggingEvents.logSettingAccess('test-setting', 123);
assert.deepEqual(
recordSettingAccess.lastCall.firstArg, {name: -1361026584, numeric_value: 123, string_value: undefined});
});
it('calls UI binding to log a function call event', async () => {
const recordFunctionCall = sinon.stub(
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
'recordFunctionCall',
);
await VisualLogging.LoggingEvents.logFunctionCall('test-function', 'test-context');
assert.deepEqual(recordFunctionCall.lastCall.firstArg, {name: -1470917656, context: 617717214});
await VisualLogging.LoggingEvents.logFunctionCall('test-function');
assert.deepEqual(recordFunctionCall.lastCall.firstArg, {name: -1470917656, context: undefined});
});
});