UNPKG

chrome-devtools-frontend

Version:
233 lines (200 loc) • 9.67 kB
// Copyright 2020 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 type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js'; import type * as Protocol from '../../generated/protocol.js'; import {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js'; import * as Common from '../common/common.js'; import * as Platform from '../platform/platform.js'; import * as SDK from './sdk.js'; const {urlString} = Platform.DevToolsPath; type PersistentHighlightSettingItem = SDK.OverlayPersistentHighlighter.PersistentHighlightSettingItem; type PersistentHighlighterCallbacks = SDK.OverlayPersistentHighlighter.PersistentHighlighterCallbacks; function resetSavedSetting(forcedState: Array<PersistentHighlightSettingItem> = []): void { const setting = Common.Settings.Settings.instance().createLocalSetting<PersistentHighlightSettingItem[]>( 'persistent-highlight-setting', []); setting.set(forcedState); } function assertSavedSettingState(expected: unknown): void { const setting = Common.Settings.Settings.instance().createLocalSetting<PersistentHighlightSettingItem[]>( 'persistent-highlight-setting', []); assert.deepEqual(setting.get(), expected); } const NON_RELATED_DOCUMENT_URL_FOR_TEST = urlString`https://notexample.com/`; const DOCUMENT_URL_FOR_TEST = urlString`https://example.com/`; const NODE_PATH_FOR_TEST = 'body > div'; const EXISTING_NODE_ID = 1 as Protocol.DOM.NodeId; const PATH_TO_NODE_ID_FOR_TEST: Record<string, Protocol.DOM.NodeId> = { 'body > div': EXISTING_NODE_ID, 'body > div + a': 2 as Protocol.DOM.NodeId, }; const NODE_ID_TO_PATH_FOR_TEST = Object.fromEntries(Object.entries(PATH_TO_NODE_ID_FOR_TEST).map(([path, nodeId]) => [nodeId, path])); function createStubDOMNode(nodeId: Protocol.DOM.NodeId|null): SDK.DOMModel.DOMNode|null { if (!nodeId) { return null; } const path = NODE_ID_TO_PATH_FOR_TEST[nodeId]; if (!path) { return null; } const domNode = sinon.createStubInstance(SDK.DOMModel.DOMNode, { path, }); domNode.id = nodeId; return domNode; } describeWithEnvironment('OverlayPersistentHighlighter', () => { let mockOverlayModel: sinon.SinonStubbedInstance<SDK.OverlayModel.OverlayModel>; let stubbedCallbacks: sinon.SinonStubbedInstance<PersistentHighlighterCallbacks>; let highlighter: SDK.OverlayPersistentHighlighter.OverlayPersistentHighlighter; beforeEach(() => { stubbedCallbacks = { onFlexOverlayStateChanged: sinon.stub(), onGridOverlayStateChanged: sinon.stub(), onScrollSnapOverlayStateChanged: sinon.stub(), onContainerQueryOverlayStateChanged: sinon.stub(), }; const stubDOMDocument = sinon.createStubInstance(SDK.DOMModel.DOMDocument); // Somehow we're not able to stub this properly // sinon says cannot stub non-existent property. stubDOMDocument.documentURL = DOCUMENT_URL_FOR_TEST; mockOverlayModel = sinon.createStubInstance(SDK.OverlayModel.OverlayModel, { getDOMModel: sinon.createStubInstance(SDK.DOMModel.DOMModel, { existingDocument: stubDOMDocument, requestDocument: sinon.stub<[], Promise<SDK.DOMModel.DOMDocument>>().resolves(stubDOMDocument), nodeForId: sinon.stub<[Protocol.DOM.NodeId | null], SDK.DOMModel.DOMNode|null>().callsFake(createStubDOMNode), pushNodeByPathToFrontend: sinon.stub<[string], Promise<Protocol.DOM.NodeId|null>>().callsFake(async (path: string) => { return PATH_TO_NODE_ID_FOR_TEST[path] ?? null; }), }), target: sinon.createStubInstance(SDK.Target.Target, { overlayAgent: { invoke_setShowGridOverlays: sinon.stub(), invoke_setShowFlexOverlays: sinon.stub(), invoke_setShowScrollSnapOverlays: sinon.stub(), invoke_setShowContainerQueryOverlays: sinon.stub(), invoke_setShowIsolatedElements: sinon.stub(), } as sinon.SinonStubbedInstance<ProtocolProxyApi.OverlayApi>, }), }); highlighter = new SDK.OverlayPersistentHighlighter.OverlayPersistentHighlighter(mockOverlayModel, stubbedCallbacks); resetSavedSetting(); }); it('is able to highlight flexbox elements', () => { highlighter.highlightFlexInOverlay(EXISTING_NODE_ID); assert.deepEqual( stubbedCallbacks.onFlexOverlayStateChanged.firstCall.args, [{nodeId: EXISTING_NODE_ID, enabled: true}]); assert(highlighter.isFlexHighlighted(EXISTING_NODE_ID)); assertSavedSettingState([{ path: NODE_PATH_FOR_TEST, url: DOCUMENT_URL_FOR_TEST, type: SDK.OverlayPersistentHighlighter.HighlightType.FLEX, }]); highlighter.hideFlexInOverlay(EXISTING_NODE_ID); assert.deepEqual( stubbedCallbacks.onFlexOverlayStateChanged.secondCall.args, [{nodeId: EXISTING_NODE_ID, enabled: false}]); assert(!highlighter.isFlexHighlighted(EXISTING_NODE_ID)); assertSavedSettingState([]); }); it('is able to highlight grid elements', () => { highlighter.highlightGridInOverlay(EXISTING_NODE_ID); assert(highlighter.isGridHighlighted(EXISTING_NODE_ID)); assert.deepEqual( stubbedCallbacks.onGridOverlayStateChanged.firstCall.args, [{nodeId: EXISTING_NODE_ID, enabled: true}]); assertSavedSettingState([{ path: NODE_PATH_FOR_TEST, url: DOCUMENT_URL_FOR_TEST, type: SDK.OverlayPersistentHighlighter.HighlightType.GRID, }]); highlighter.hideGridInOverlay(EXISTING_NODE_ID); assert.deepEqual( stubbedCallbacks.onGridOverlayStateChanged.secondCall.args, [{nodeId: EXISTING_NODE_ID, enabled: false}]); assert(!highlighter.isGridHighlighted(EXISTING_NODE_ID)); assertSavedSettingState([]); }); it('is able to highlight scroll snap elements', () => { highlighter.highlightScrollSnapInOverlay(EXISTING_NODE_ID); assert(highlighter.isScrollSnapHighlighted(EXISTING_NODE_ID)); assert.deepEqual( stubbedCallbacks.onScrollSnapOverlayStateChanged.firstCall.args, [{nodeId: EXISTING_NODE_ID, enabled: true}]); assertSavedSettingState([{ path: NODE_PATH_FOR_TEST, url: DOCUMENT_URL_FOR_TEST, type: SDK.OverlayPersistentHighlighter.HighlightType.SCROLL_SNAP, }]); highlighter.hideScrollSnapInOverlay(EXISTING_NODE_ID); assert(!highlighter.isScrollSnapHighlighted(EXISTING_NODE_ID)); assert.deepEqual( stubbedCallbacks.onScrollSnapOverlayStateChanged.secondCall.args, [{nodeId: EXISTING_NODE_ID, enabled: false}]); assertSavedSettingState([]); }); it('is able to highlight container query elements', () => { highlighter.highlightContainerQueryInOverlay(EXISTING_NODE_ID); assert(highlighter.isContainerQueryHighlighted(EXISTING_NODE_ID)); assert.deepEqual( stubbedCallbacks.onContainerQueryOverlayStateChanged.firstCall.args, [{nodeId: EXISTING_NODE_ID, enabled: true}]); assertSavedSettingState([{ path: NODE_PATH_FOR_TEST, url: DOCUMENT_URL_FOR_TEST, type: SDK.OverlayPersistentHighlighter.HighlightType.CONTAINER_QUERY, }]); highlighter.hideContainerQueryInOverlay(EXISTING_NODE_ID); assert(!highlighter.isContainerQueryHighlighted(EXISTING_NODE_ID)); assert.deepEqual( stubbedCallbacks.onContainerQueryOverlayStateChanged.secondCall.args, [{nodeId: EXISTING_NODE_ID, enabled: false}]); assertSavedSettingState([]); }); it('is able to highlight isolated elements', () => { highlighter.highlightIsolatedElementInOverlay(EXISTING_NODE_ID); assert(highlighter.isIsolatedElementHighlighted(EXISTING_NODE_ID)); assertSavedSettingState([{ path: NODE_PATH_FOR_TEST, url: DOCUMENT_URL_FOR_TEST, type: SDK.OverlayPersistentHighlighter.HighlightType.ISOLATED_ELEMENT, }]); highlighter.hideIsolatedElementInOverlay(EXISTING_NODE_ID); assert(!highlighter.isIsolatedElementHighlighted(EXISTING_NODE_ID)); assertSavedSettingState([]); }); it('updating setting state keeps the highlights not related to the current document', () => { resetSavedSetting([{ url: NON_RELATED_DOCUMENT_URL_FOR_TEST, path: NODE_PATH_FOR_TEST, type: SDK.OverlayPersistentHighlighter.HighlightType.FLEX, }]); highlighter.highlightFlexInOverlay(EXISTING_NODE_ID); highlighter.hideFlexInOverlay(EXISTING_NODE_ID); assertSavedSettingState([{ url: NON_RELATED_DOCUMENT_URL_FOR_TEST, path: NODE_PATH_FOR_TEST, type: SDK.OverlayPersistentHighlighter.HighlightType.FLEX, }]); }); it('restoring highlights for document highlights all the saved higlights in the setting for the current document', async () => { const paths = Object.keys(PATH_TO_NODE_ID_FOR_TEST); resetSavedSetting([ { url: DOCUMENT_URL_FOR_TEST, path: paths[0], type: SDK.OverlayPersistentHighlighter.HighlightType.GRID, }, { url: DOCUMENT_URL_FOR_TEST, path: paths[1], type: SDK.OverlayPersistentHighlighter.HighlightType.FLEX, }, ]); await highlighter.restoreHighlightsForDocument(); assert(stubbedCallbacks.onGridOverlayStateChanged.calledWith( {nodeId: PATH_TO_NODE_ID_FOR_TEST[paths[0]], enabled: true})); assert(highlighter.isGridHighlighted(PATH_TO_NODE_ID_FOR_TEST[paths[0]])); assert(stubbedCallbacks.onFlexOverlayStateChanged.calledWith( {nodeId: PATH_TO_NODE_ID_FOR_TEST[paths[1]], enabled: true})); assert(highlighter.isFlexHighlighted(PATH_TO_NODE_ID_FOR_TEST[paths[1]])); }); });