blob: e6fae4ab0550836b8aba46dd701465d9e8ee7086 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {assert} from 'chai';
import {expectError} from '../../conductor/events.js';
import {loadTraceAndWaitToFullyRender, searchForComponent} from '../helpers/performance-helpers.js';
import type {DevToolsPage} from '../shared/frontend-helper.js';
import type {InspectedPage} from '../shared/target-helper.js';
async function loadTrace(devToolsPage: DevToolsPage, inspectedPage: InspectedPage, resource: string) {
// Scripts in these traces happen to fail asserts in formatter_worker.
expectError(/ScopeParser\.js|formatter_worker\.js/);
await devToolsPage.reloadWithParams({});
const url = new URL(devToolsPage.page.url());
url.pathname = url.pathname.replace('devtools_app.html', 'trace_app.html');
url.search = '';
const traceUrl = `${inspectedPage.getResourcesPath()}/${resource}`;
// Can't do this because SanitizeFrontendQueryParam does not allow timeline, and when
// the sanitized url differs from the page url workers will fail to load (like the
// formatter worker).
// But it's fine, Performance panel will always open because of TraceRevealer.
// url.searchParams.set('panel', 'timeline');
url.searchParams.set('isChromeForTesting', 'true');
url.searchParams.set('traceURL', traceUrl);
await devToolsPage.page.goto(url.href);
// Wait for Performance panel to open.
await loadTraceAndWaitToFullyRender(devToolsPage, async () => {});
// Performance and Sources.
assert.lengthOf(await devToolsPage.$$('.tabbed-pane-header[aria-label="Main toolbar"] .tabbed-pane-header-tab'), 2);
}
async function searchAndClickOnStackTrace(
devToolsPage: DevToolsPage, searchTerm: string, expectedHighlightedContent: string,
expectedSourceLocation: string) {
// This is a function on a firebase script that has sourcemaps.
await searchForComponent(searchTerm, devToolsPage);
await devToolsPage.raf();
await devToolsPage.timeout(3000);
// Prefer stack trace if present.
const containerEl =
await devToolsPage.$('.timeline-details-stack-values') ?? await devToolsPage.$('.timeline-details-view');
assert.isOk(containerEl);
const topStackFrameLink = await devToolsPage.$('.devtools-link', containerEl);
assert.isOk(topStackFrameLink);
assert.strictEqual(await topStackFrameLink.evaluate(el => el.textContent), expectedSourceLocation);
await topStackFrameLink.click();
// Sometimes (mostly in CI) clicking does nothing. We have no idea why. Wait a
// bit and try again.
for (let i = 0; i < 100; i++) {
await devToolsPage.raf();
await devToolsPage.raf();
const isVisible = await topStackFrameLink.evaluate(node => node.checkVisibility());
if (!isVisible) {
break;
}
await devToolsPage.timeout(500);
await topStackFrameLink.click();
}
// Now we're in the Sources panel.
await devToolsPage.waitFor('.cm-content');
await devToolsPage.waitFor('.cm-highlightedLine');
assert.include(await devToolsPage.getTextContent('.cm-highlightedLine'), expectedHighlightedContent);
}
describe('trace_app.html', function() {
setup({dockingMode: 'undocked'});
if (this.timeout() > 0) {
this.timeout(60000);
}
it('linkifies source mapped function calls', async ({devToolsPage, inspectedPage}) => {
await loadTrace(devToolsPage, inspectedPage, 'performance/timeline/enhanced-trace.json.gz');
// This is a function on a firebase script that has sourcemaps.
await searchAndClickOnStackTrace(
devToolsPage, 'createUserTimingTrace', 'createUserTimingTrace', 'oob_resources_service.ts:83:10');
});
it('linkifies function calls from inline scripts in HTML', async ({devToolsPage, inspectedPage}) => {
await loadTrace(devToolsPage, inspectedPage, 'performance/timeline/enhanced-trace.json.gz');
// This is a function from an inline script in the HTML. Please excuse the Paul humor.
await searchAndClickOnStackTrace(devToolsPage, 'pooopInTheTrace', 'pooopInTheTrace', '(index):399:26');
});
it('linkifies to CSS resources', async ({devToolsPage, inspectedPage}) => {
await loadTrace(devToolsPage, inspectedPage, 'performance/timeline/enhanced-trace.json.gz');
await searchAndClickOnStackTrace(
devToolsPage, 'fonts.googleapis.com', '/* latin */',
'css?family=PT+Serif:regular,italic,bold|PT+Sans:regular,italic,bold|Droid+Sans:400,700|Lato:700,900');
});
});