blob: 681ccdf2194b0aa78cc640911668c6b64462aa7a [file] [log] [blame]
// 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 {assert} from 'chai';
import {expectError} from '../../conductor/events.js';
import {
$textContent,
getBrowserAndPages,
setDevToolsSettings,
waitFor,
waitForElementWithTextContent,
} from '../../shared/helper.js';
import {describe, it} from '../../shared/mocha-extensions.js';
import {
clickStartButton,
getAuditsBreakdown,
getServiceWorkerCount,
interceptNextFileSave,
navigateToLighthouseTab,
registerServiceWorker,
renderHtmlInIframe,
selectCategories,
selectDevice,
setLegacyNavigation,
setThrottlingMethod,
setToolbarCheckboxWithText,
unregisterAllServiceWorkers,
waitForResult,
} from '../helpers/lighthouse-helpers.js';
// This test will fail (by default) in headful mode, as the target page never gets painted.
// To resolve this when debugging, just make sure the target page is visible during the lighthouse run.
describe('Navigation', async function() {
// The tests in this suite are particularly slow
this.timeout(60_000);
beforeEach(() => {
// https://github.com/GoogleChrome/lighthouse/issues/14572
expectError(/Request CacheStorage\.requestCacheNames failed/);
// https://bugs.chromium.org/p/chromium/issues/detail?id=1357791
expectError(/Protocol Error: the message with wrong session id/);
expectError(/Protocol Error: the message with wrong session id/);
expectError(/Protocol Error: the message with wrong session id/);
expectError(/Protocol Error: the message with wrong session id/);
expectError(/Protocol Error: the message with wrong session id/);
});
afterEach(async () => {
await unregisterAllServiceWorkers();
});
const modes = ['legacy', 'FR'];
for (const mode of modes) {
describe(`in ${mode} mode`, () => {
it('successfully returns a Lighthouse report', async () => {
await navigateToLighthouseTab('lighthouse/hello.html');
await registerServiceWorker();
await setLegacyNavigation(mode === 'legacy');
await selectCategories([
'performance',
'accessibility',
'best-practices',
'seo',
'pwa',
'lighthouse-plugin-publisher-ads',
]);
let numNavigations = 0;
const {target} = await getBrowserAndPages();
target.on('framenavigated', () => ++numNavigations);
await clickStartButton();
const {lhr, artifacts, reportEl} = await waitForResult();
if (mode === 'legacy') {
// 1 initial about:blank jump
// 1 about:blank jump + 1 navigation for the default pass
// 1 about:blank jump + 1 navigation for the offline pass
// 2 navigations to go to chrome://terms and back testing bfcache
// 1 navigation after auditing to reset state
assert.strictEqual(numNavigations, 8);
} else {
// 1 initial about:blank jump
// 1 about:blank jump + 1 navigation for the default pass
// 2 navigations to go to chrome://terms and back testing bfcache
// 1 navigation after auditing to reset state
assert.strictEqual(numNavigations, 6);
}
assert.strictEqual(lhr.lighthouseVersion, '10.0.0');
assert.match(lhr.finalUrl, /^https:\/\/localhost:[0-9]+\/test\/e2e\/resources\/lighthouse\/hello.html/);
assert.strictEqual(lhr.configSettings.throttlingMethod, 'simulate');
assert.strictEqual(lhr.configSettings.disableStorageReset, false);
assert.strictEqual(lhr.configSettings.formFactor, 'mobile');
assert.strictEqual(lhr.configSettings.throttling.rttMs, 150);
assert.strictEqual(lhr.configSettings.screenEmulation.disabled, true);
assert.include(lhr.configSettings.emulatedUserAgent, 'Mobile');
assert.include(lhr.environment.networkUserAgent, 'Mobile');
assert.deepStrictEqual(artifacts.ViewportDimensions, {
innerHeight: 823,
innerWidth: 412,
outerHeight: 823,
outerWidth: 412,
devicePixelRatio: 1.75,
});
const {auditResults, erroredAudits, failedAudits} = getAuditsBreakdown(lhr);
assert.strictEqual(auditResults.length, 173);
assert.deepStrictEqual(erroredAudits, []);
assert.deepStrictEqual(failedAudits.map(audit => audit.id), [
'service-worker',
'installable-manifest',
'splash-screen',
'themed-omnibox',
'maskable-icon',
'document-title',
'html-has-lang',
'meta-description',
'bf-cache',
]);
const viewTraceButton = await $textContent('View Original Trace', reportEl);
if (!viewTraceButton) {
throw new Error('Could not find view trace button');
}
// Test view trace button behavior
await viewTraceButton.click();
let selectedTab = await waitFor('.tabbed-pane-header-tab.selected[aria-label="Performance"]');
let selectedTabText = await selectedTab.evaluate(selectedTabEl => {
return selectedTabEl.textContent;
});
assert.strictEqual(selectedTabText, 'Performance');
await navigateToLighthouseTab();
// Test element link behavior
const lcpElementAudit = await waitForElementWithTextContent('Largest Contentful Paint element', reportEl);
await lcpElementAudit.click();
const lcpElementLink = await waitForElementWithTextContent('button');
await lcpElementLink.click();
selectedTab = await waitFor('.tabbed-pane-header-tab.selected[aria-label="Elements"]');
selectedTabText = await selectedTab.evaluate(selectedTabEl => {
return selectedTabEl.textContent;
});
assert.strictEqual(selectedTabText, 'Elements');
const waitForJson = await interceptNextFileSave();
// For some reason the CDP click command doesn't work here even if the tools menu is open.
await reportEl.$eval(
'a[data-action="save-json"]:not(.hidden)', saveJsonEl => (saveJsonEl as HTMLElement).click());
const jsonContent = await waitForJson();
assert.strictEqual(jsonContent, JSON.stringify(lhr, null, 2));
const waitForHtml = await interceptNextFileSave();
// For some reason the CDP click command doesn't work here even if the tools menu is open.
await reportEl.$eval(
'a[data-action="save-html"]:not(.hidden)', saveHtmlEl => (saveHtmlEl as HTMLElement).click());
const htmlContent = await waitForHtml();
const iframeHandle = await renderHtmlInIframe(htmlContent);
const iframeAuditDivs = await iframeHandle.$$('.lh-audit');
const frontendAuditDivs = await reportEl.$$('.lh-audit');
assert.strictEqual(frontendAuditDivs.length, iframeAuditDivs.length);
// Ensure service worker was cleared.
assert.strictEqual(await getServiceWorkerCount(), 0);
});
it('successfully returns a Lighthouse report with DevTools throttling', async () => {
await navigateToLighthouseTab('lighthouse/hello.html');
await setThrottlingMethod('devtools');
await setLegacyNavigation(mode === 'legacy');
await clickStartButton();
const {lhr, reportEl} = await waitForResult();
assert.strictEqual(lhr.configSettings.throttlingMethod, 'devtools');
// [crbug.com/1347220] DevTools throttling can force resources to load slow enough for these audits to fail sometimes.
const flakyAudits = [
'server-response-time',
'render-blocking-resources',
];
const {auditResults, erroredAudits, failedAudits} = getAuditsBreakdown(lhr, flakyAudits);
assert.strictEqual(auditResults.length, 150);
assert.deepStrictEqual(erroredAudits, []);
assert.deepStrictEqual(failedAudits.map(audit => audit.id), [
'service-worker',
'installable-manifest',
'splash-screen',
'themed-omnibox',
'maskable-icon',
'document-title',
'html-has-lang',
'meta-description',
'bf-cache',
]);
const viewTraceButton = await $textContent('View Trace', reportEl);
assert.ok(viewTraceButton);
});
it('successfully returns a Lighthouse report when settings changed', async () => {
await setDevToolsSettings({language: 'es'});
await navigateToLighthouseTab('lighthouse/hello.html');
await registerServiceWorker();
await setToolbarCheckboxWithText(mode === 'legacy', 'Navegación antigua');
await setToolbarCheckboxWithText(false, 'Borrar almacenamiento');
await selectCategories(['performance', 'best-practices']);
await selectDevice('desktop');
await clickStartButton();
const {reportEl, lhr, artifacts} = await waitForResult();
const {innerWidth, innerHeight, devicePixelRatio} = artifacts.ViewportDimensions;
// TODO: Figure out why outerHeight can be different depending on OS
assert.strictEqual(innerHeight, 720);
assert.strictEqual(innerWidth, 1280);
assert.strictEqual(devicePixelRatio, 1);
const {erroredAudits} = getAuditsBreakdown(lhr);
assert.deepStrictEqual(erroredAudits, []);
assert.deepStrictEqual(Object.keys(lhr.categories), ['performance', 'best-practices']);
assert.strictEqual(lhr.configSettings.disableStorageReset, true);
assert.strictEqual(lhr.configSettings.formFactor, 'desktop');
assert.strictEqual(lhr.configSettings.throttling.rttMs, 40);
assert.strictEqual(lhr.configSettings.screenEmulation.disabled, true);
assert.notInclude(lhr.configSettings.emulatedUserAgent, 'Mobile');
assert.notInclude(lhr.environment.networkUserAgent, 'Mobile');
const viewTraceButton = await $textContent('Ver rastro original', reportEl);
assert.ok(viewTraceButton);
const footerIssueText = await reportEl.$eval('.lh-footer__version_issue', footerIssueEl => {
return footerIssueEl.textContent;
});
assert.strictEqual(lhr.i18n.rendererFormattedStrings.footerIssue, 'Notificar un problema');
assert.strictEqual(footerIssueText, 'Notificar un problema');
// Ensure service worker is not cleared because we disable the storage reset.
assert.strictEqual(await getServiceWorkerCount(), 1);
});
});
}
});