UNPKG

chrome-devtools-frontend

Version:
124 lines (101 loc) • 5.67 kB
// Copyright 2022 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 SDK from '../../core/sdk/sdk.js'; import type * as Protocol from '../../generated/protocol.js'; import {createTarget} from '../../testing/EnvironmentHelpers.js'; import {describeWithMockConnection} from '../../testing/MockConnection.js'; import * as UI from '../../ui/legacy/legacy.js'; import type * as LighthouseModule from './lighthouse.js'; describeWithMockConnection('LighthouseReportRenderer', () => { // eslint-disable-next-line @typescript-eslint/naming-convention let Lighthouse: typeof LighthouseModule; let target: SDK.Target.Target; let sourceElement: HTMLElement; let linkElement: HTMLElement; const PATH = 'TEST_PATH'; const NODE_ID = 42 as Protocol.DOM.NodeId; const NODE = {id: NODE_ID} as SDK.DOMModel.DOMNode; const SNIPPET = 'SNIPPET'; const LH_NODE_HTML = (path: string, snippet: string) => `<div class="lh-node" data-path="${path}" data-snippet="${snippet}"></div>`; beforeEach(async () => { Lighthouse = await import('./lighthouse.js'); const tabTarget = createTarget({type: SDK.Target.Type.TAB}); createTarget({parentTarget: tabTarget, subtype: 'prerender'}); target = createTarget({parentTarget: tabTarget}); linkElement = document.createElement('div'); linkElement.textContent = 'link'; sourceElement = document.createElement('div'); }); it('resolves node and calls linkifier', async () => { sourceElement.innerHTML = LH_NODE_HTML(PATH, SNIPPET); const domModel = target.model(SDK.DOMModel.DOMModel); assert.exists(domModel); sinon.stub(domModel, 'pushNodeByPathToFrontend').withArgs(PATH).returns(Promise.resolve(NODE_ID)); sinon.stub(domModel, 'nodeForId').withArgs(NODE_ID).returns(NODE); sinon.stub(Common.Linkifier.Linkifier, 'linkify') .withArgs(NODE, {tooltip: SNIPPET, preventKeyboardFocus: undefined}) .returns(Promise.resolve(linkElement)); await Lighthouse.LighthouseReportRenderer.LighthouseReportRenderer.linkifyNodeDetails(sourceElement); assert.include([...sourceElement.firstChild?.childNodes || []], linkElement); }); it('handles multiple nodes', async () => { const domModel = target.model(SDK.DOMModel.DOMModel); assert.exists(domModel); const pushNodeByPathToFrontend = sinon.stub(domModel, 'pushNodeByPathToFrontend'); const nodeForId = sinon.stub(domModel, 'nodeForId'); const linkify = sinon.stub(Common.Linkifier.Linkifier, 'linkify'); const NUM_NODES = 3; for (let i = 1; i <= NUM_NODES; ++i) { sourceElement.innerHTML += LH_NODE_HTML(PATH + i, SNIPPET + i); const nodeId = i as Protocol.DOM.NodeId; const node = {id: nodeId} as SDK.DOMModel.DOMNode; pushNodeByPathToFrontend.withArgs(PATH + i).returns(Promise.resolve(nodeId)); nodeForId.withArgs(nodeId).returns(node); linkify.withArgs(node, {tooltip: SNIPPET + i, preventKeyboardFocus: undefined}) .returns(Promise.resolve(document.createTextNode(`link${i}`))); } await Lighthouse.LighthouseReportRenderer.LighthouseReportRenderer.linkifyNodeDetails(sourceElement); assert.strictEqual(sourceElement.childNodes.length, NUM_NODES); assert.deepEqual([...sourceElement.childNodes].map(n => n.textContent), ['link1', 'link2', 'link3']); }); it('resets tooltip', async () => { sourceElement.innerHTML = LH_NODE_HTML(PATH, SNIPPET); const domModel = target.model(SDK.DOMModel.DOMModel); assert.exists(domModel); sinon.stub(domModel, 'pushNodeByPathToFrontend').returns(Promise.resolve(NODE_ID)); sinon.stub(domModel, 'nodeForId').returns(NODE); sinon.stub(Common.Linkifier.Linkifier, 'linkify').returns(Promise.resolve(linkElement)); const installTooltip = sinon.spy(UI.Tooltip.Tooltip, 'install'); await Lighthouse.LighthouseReportRenderer.LighthouseReportRenderer.linkifyNodeDetails(sourceElement); assert.isTrue(installTooltip.calledOnceWith(sourceElement.firstChild as HTMLElement, '')); }); it('only keeps link and screenshot', async () => { sourceElement.innerHTML = LH_NODE_HTML(PATH, SNIPPET); assert.exists(sourceElement.firstElementChild); sourceElement.firstElementChild.innerHTML = 'foo<div class="lh-element-screenshot"></div>bar'; const domModel = target.model(SDK.DOMModel.DOMModel); assert.exists(domModel); sinon.stub(domModel, 'pushNodeByPathToFrontend').returns(Promise.resolve(NODE_ID)); sinon.stub(domModel, 'nodeForId').returns(NODE); sinon.stub(Common.Linkifier.Linkifier, 'linkify').returns(Promise.resolve(linkElement)); await Lighthouse.LighthouseReportRenderer.LighthouseReportRenderer.linkifyNodeDetails(sourceElement); assert.strictEqual( sourceElement.firstElementChild.innerHTML, '<div class="lh-element-screenshot"></div><div>link</div>'); }); it('skips malformed nodes', async () => { const originalHtml = [ LH_NODE_HTML('', SNIPPET), LH_NODE_HTML('UNKNOWN_PATH', SNIPPET), LH_NODE_HTML('PATH_WIHTOUT_NODE', SNIPPET), ].join(''); const domModel = target.model(SDK.DOMModel.DOMModel); assert.exists(domModel); sinon.stub(domModel, 'pushNodeByPathToFrontend').withArgs('PATH_WIHTOUT_NODE').returns(Promise.resolve(NODE_ID)); sourceElement.innerHTML = originalHtml; await Lighthouse.LighthouseReportRenderer.LighthouseReportRenderer.linkifyNodeDetails(sourceElement); assert.strictEqual(sourceElement.innerHTML, originalHtml); }); });