misc: split lhr compat code to lib/lighthouse-compatibility.js (#14701)
This commit is contained in:
Родитель
2f6ed6fb2c
Коммит
ddf48a9315
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* @license Copyright 2023 The Lighthouse Authors. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
import {Util} from '../../shared/util.js';
|
||||
|
||||
const SCREENSHOT_PREFIX = 'data:image/jpeg;base64,';
|
||||
|
||||
/** @typedef {import('../../types/lhr/audit-details').default.ItemValueType} ItemValueType */
|
||||
|
||||
/**
|
||||
* Upgrades an lhr object in-place to account for changes in the data structure over major versions.
|
||||
* @param {LH.Result} lhr
|
||||
*/
|
||||
function upgradeLhrForCompatibility(lhr) {
|
||||
// If LHR is older (≤3.0.3), it has no locale setting. Set default.
|
||||
if (!lhr.configSettings.locale) {
|
||||
lhr.configSettings.locale = 'en';
|
||||
}
|
||||
if (!lhr.configSettings.formFactor) {
|
||||
// @ts-expect-error fallback handling for emulatedFormFactor
|
||||
lhr.configSettings.formFactor = lhr.configSettings.emulatedFormFactor;
|
||||
}
|
||||
|
||||
lhr.finalDisplayedUrl = Util.getFinalDisplayedUrl(lhr);
|
||||
lhr.mainDocumentUrl = Util.getMainDocumentUrl(lhr);
|
||||
|
||||
for (const audit of Object.values(lhr.audits)) {
|
||||
// Turn 'not-applicable' (LHR <4.0) and 'not_applicable' (older proto versions)
|
||||
// into 'notApplicable' (LHR ≥4.0).
|
||||
// @ts-expect-error tsc rightly flags that these values shouldn't occur.
|
||||
// eslint-disable-next-line max-len
|
||||
if (audit.scoreDisplayMode === 'not_applicable' || audit.scoreDisplayMode === 'not-applicable') {
|
||||
audit.scoreDisplayMode = 'notApplicable';
|
||||
}
|
||||
|
||||
if (audit.details) {
|
||||
// Turn `auditDetails.type` of undefined (LHR <4.2) and 'diagnostic' (LHR <5.0)
|
||||
// into 'debugdata' (LHR ≥5.0).
|
||||
// @ts-expect-error tsc rightly flags that these values shouldn't occur.
|
||||
if (audit.details.type === undefined || audit.details.type === 'diagnostic') {
|
||||
// @ts-expect-error details is of type never.
|
||||
audit.details.type = 'debugdata';
|
||||
}
|
||||
|
||||
// Add the jpg data URL prefix to filmstrip screenshots without them (LHR <5.0).
|
||||
if (audit.details.type === 'filmstrip') {
|
||||
for (const screenshot of audit.details.items) {
|
||||
if (!screenshot.data.startsWith(SCREENSHOT_PREFIX)) {
|
||||
screenshot.data = SCREENSHOT_PREFIX + screenshot.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Circa 10.0, table items were refactored.
|
||||
if (audit.details.type === 'table') {
|
||||
for (const heading of audit.details.headings) {
|
||||
/** @type {{itemType: ItemValueType|undefined, text: string|undefined}} */
|
||||
// @ts-expect-error
|
||||
const {itemType, text} = heading;
|
||||
if (itemType !== undefined) {
|
||||
heading.valueType = itemType;
|
||||
// @ts-expect-error
|
||||
delete heading.itemType;
|
||||
}
|
||||
if (text !== undefined) {
|
||||
heading.label = text;
|
||||
// @ts-expect-error
|
||||
delete heading.text;
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
const subItemsItemType = heading.subItemsHeading?.itemType;
|
||||
if (heading.subItemsHeading && subItemsItemType !== undefined) {
|
||||
heading.subItemsHeading.valueType = subItemsItemType;
|
||||
// @ts-expect-error
|
||||
delete heading.subItemsHeading.itemType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: convert printf-style displayValue.
|
||||
// Added: #5099, v3
|
||||
// Removed: #6767, v4
|
||||
}
|
||||
}
|
||||
|
||||
// This backcompat converts old LHRs (<9.0.0) to use the new "hidden" group.
|
||||
// Old LHRs used "no group" to identify audits that should be hidden in performance instead of the "hidden" group.
|
||||
// Newer LHRs use "no group" to identify opportunities and diagnostics whose groups are assigned by details type.
|
||||
const [majorVersion] = lhr.lighthouseVersion.split('.').map(Number);
|
||||
const perfCategory = lhr.categories['performance'];
|
||||
if (majorVersion < 9 && perfCategory) {
|
||||
if (!lhr.categoryGroups) lhr.categoryGroups = {};
|
||||
lhr.categoryGroups['hidden'] = {title: ''};
|
||||
for (const auditRef of perfCategory.auditRefs) {
|
||||
if (!auditRef.group) {
|
||||
auditRef.group = 'hidden';
|
||||
} else if (['load-opportunities', 'diagnostics'].includes(auditRef.group)) {
|
||||
delete auditRef.group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add some minimal stuff so older reports still work.
|
||||
if (!lhr.environment) {
|
||||
// @ts-expect-error
|
||||
lhr.environment = {benchmarkIndex: 0};
|
||||
}
|
||||
if (!lhr.configSettings.screenEmulation) {
|
||||
// @ts-expect-error
|
||||
lhr.configSettings.screenEmulation = {};
|
||||
}
|
||||
if (!lhr.i18n) {
|
||||
// @ts-expect-error
|
||||
lhr.i18n = {};
|
||||
}
|
||||
|
||||
// In 10.0, full-page-screenshot became a top-level property on the LHR.
|
||||
if (lhr.audits['full-page-screenshot']) {
|
||||
const details = /** @type {LH.Result.FullPageScreenshot=} */ (
|
||||
lhr.audits['full-page-screenshot'].details);
|
||||
if (details) {
|
||||
lhr.fullPageScreenshot = {
|
||||
screenshot: details.screenshot,
|
||||
nodes: details.nodes,
|
||||
};
|
||||
} else {
|
||||
lhr.fullPageScreenshot = null;
|
||||
}
|
||||
delete lhr.audits['full-page-screenshot'];
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
upgradeLhrForCompatibility,
|
||||
};
|
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
* @license Copyright 2023 The Lighthouse Authors. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
import assert from 'assert/strict';
|
||||
|
||||
import {upgradeLhrForCompatibility} from '../../lib/lighthouse-compatibility.js';
|
||||
import {readJson} from '../../../core/test/test-utils.js';
|
||||
|
||||
/** @type {LH.Result} */
|
||||
const sampleResult = readJson('../../../core/test/results/sample_v2.json', import.meta);
|
||||
|
||||
/**
|
||||
* @param {LH.Result} original
|
||||
* @return {LH.Result}
|
||||
*/
|
||||
function cloneLhr(original) {
|
||||
const cloned = JSON.parse(JSON.stringify(original));
|
||||
return cloned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper function to avoid needing to rewrite tests.
|
||||
* @param {LH.Result} original
|
||||
* @return {LH.Result}
|
||||
*/
|
||||
function upgradeLhr(original) {
|
||||
const cloned = cloneLhr(original);
|
||||
upgradeLhrForCompatibility(cloned);
|
||||
return cloned;
|
||||
}
|
||||
|
||||
describe('backward compatibility', () => {
|
||||
it('corrects underscored `notApplicable` scoreDisplayMode', () => {
|
||||
const clonedSampleResult = cloneLhr(sampleResult);
|
||||
|
||||
let notApplicableCount = 0;
|
||||
Object.values(clonedSampleResult.audits).forEach(audit => {
|
||||
if (audit.scoreDisplayMode === 'notApplicable') {
|
||||
notApplicableCount++;
|
||||
audit.scoreDisplayMode = 'not_applicable';
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(notApplicableCount > 20); // Make sure something's being tested.
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = upgradeLhr(clonedSampleResult);
|
||||
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
});
|
||||
|
||||
it('corrects undefined auditDetails.type to `debugdata`', () => {
|
||||
const clonedSampleResult = cloneLhr(sampleResult);
|
||||
|
||||
// Delete debugdata details types.
|
||||
let undefinedCount = 0;
|
||||
for (const audit of Object.values(clonedSampleResult.audits)) {
|
||||
if (audit.details && audit.details.type === 'debugdata') {
|
||||
undefinedCount++;
|
||||
delete audit.details.type;
|
||||
}
|
||||
}
|
||||
assert.ok(undefinedCount > 4); // Make sure something's being tested.
|
||||
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = upgradeLhr(clonedSampleResult);
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
});
|
||||
|
||||
it('corrects `diagnostic` auditDetails.type to `debugdata`', () => {
|
||||
const clonedSampleResult = cloneLhr(sampleResult);
|
||||
|
||||
// Change debugdata details types.
|
||||
let diagnosticCount = 0;
|
||||
for (const audit of Object.values(clonedSampleResult.audits)) {
|
||||
if (audit.details && audit.details.type === 'debugdata') {
|
||||
diagnosticCount++;
|
||||
audit.details.type = 'diagnostic';
|
||||
}
|
||||
}
|
||||
assert.ok(diagnosticCount > 4); // Make sure something's being tested.
|
||||
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = upgradeLhr(clonedSampleResult);
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
});
|
||||
|
||||
it('corrects screenshots in the `filmstrip` auditDetails.type', () => {
|
||||
const clonedSampleResult = cloneLhr(sampleResult);
|
||||
|
||||
// Strip filmstrip screenshots of data URL prefix.
|
||||
let filmstripCount = 0;
|
||||
for (const audit of Object.values(clonedSampleResult.audits)) {
|
||||
if (audit.details && audit.details.type === 'filmstrip') {
|
||||
filmstripCount++;
|
||||
for (const screenshot of audit.details.items) {
|
||||
screenshot.data = screenshot.data.slice('data:image/jpeg;base64,'.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.ok(filmstripCount > 0); // Make sure something's being tested.
|
||||
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = upgradeLhr(clonedSampleResult);
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
});
|
||||
|
||||
it('moves full-page-screenshot audit', () => {
|
||||
const clonedSampleResult = cloneLhr(sampleResult);
|
||||
|
||||
clonedSampleResult.audits['full-page-screenshot'] = {
|
||||
details: {
|
||||
type: 'full-page-screenshot',
|
||||
...sampleResult.fullPageScreenshot,
|
||||
},
|
||||
};
|
||||
delete clonedSampleResult.fullPageScreenshot;
|
||||
|
||||
assert.ok(clonedSampleResult.audits['full-page-screenshot'].details.nodes); // Make sure something's being tested.
|
||||
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = upgradeLhr(clonedSampleResult);
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
assert.deepStrictEqual(preparedResult.fullPageScreenshot, sampleResult.fullPageScreenshot);
|
||||
});
|
||||
|
||||
it('corrects performance category without hidden group', () => {
|
||||
const clonedSampleResult = cloneLhr(sampleResult);
|
||||
|
||||
clonedSampleResult.lighthouseVersion = '8.6.0';
|
||||
delete clonedSampleResult.categoryGroups['hidden'];
|
||||
for (const auditRef of clonedSampleResult.categories['performance'].auditRefs) {
|
||||
if (auditRef.group === 'hidden') {
|
||||
delete auditRef.group;
|
||||
} else if (!auditRef.group) {
|
||||
auditRef.group = 'diagnostics';
|
||||
}
|
||||
}
|
||||
assert.notDeepStrictEqual(clonedSampleResult.categories, sampleResult.categories);
|
||||
assert.notDeepStrictEqual(clonedSampleResult.categoryGroups, sampleResult.categoryGroups);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const clonedPreparedResult = upgradeLhr(clonedSampleResult);
|
||||
const preparedResult = upgradeLhr(sampleResult);
|
||||
assert.deepStrictEqual(clonedPreparedResult.categories, preparedResult.categories);
|
||||
assert.deepStrictEqual(clonedPreparedResult.categoryGroups, preparedResult.categoryGroups);
|
||||
});
|
||||
|
||||
it('converts old opportunity table column headings to consolidated table headings', () => {
|
||||
const clonedSampleResult = cloneLhr(sampleResult);
|
||||
|
||||
const auditsWithTableDetails = Object.values(clonedSampleResult.audits)
|
||||
.filter(audit => audit.details?.type === 'table');
|
||||
assert.notEqual(auditsWithTableDetails.length, 0);
|
||||
for (const audit of auditsWithTableDetails) {
|
||||
for (const heading of audit.details.headings) {
|
||||
heading.itemType = heading.valueType;
|
||||
heading.text = heading.label;
|
||||
delete heading.valueType;
|
||||
delete heading.label;
|
||||
|
||||
if (heading.subItemsHeading) {
|
||||
heading.subItemsHeading.itemType = heading.subItemsHeading.valueType;
|
||||
// @ts-expect-error
|
||||
delete heading.subItemsHeading.valueType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const preparedResult = upgradeLhr(clonedSampleResult);
|
||||
assert.deepStrictEqual(sampleResult.audits, preparedResult.audits);
|
||||
});
|
||||
});
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
import {Util} from '../../shared/util.js';
|
||||
import {Globals} from './report-globals.js';
|
||||
import {upgradeLhrForCompatibility} from '../../core/lib/lighthouse-compatibility.js';
|
||||
|
||||
const SCREENSHOT_PREFIX = 'data:image/jpeg;base64,';
|
||||
const RATINGS = Util.RATINGS;
|
||||
|
||||
class ReportUtils {
|
||||
|
@ -17,86 +17,17 @@ class ReportUtils {
|
|||
* compatible with current renderer.
|
||||
* The LHR passed in is not mutated.
|
||||
* TODO(team): we all agree the LHR shape change is technical debt we should fix
|
||||
* @param {LH.Result} result
|
||||
* @param {LH.Result} lhr
|
||||
* @return {LH.ReportResult}
|
||||
*/
|
||||
static prepareReportResult(result) {
|
||||
static prepareReportResult(lhr) {
|
||||
// If any mutations happen to the report within the renderers, we want the original object untouched
|
||||
const clone = /** @type {LH.ReportResult} */ (JSON.parse(JSON.stringify(result)));
|
||||
|
||||
// If LHR is older (≤3.0.3), it has no locale setting. Set default.
|
||||
if (!clone.configSettings.locale) {
|
||||
clone.configSettings.locale = 'en';
|
||||
}
|
||||
if (!clone.configSettings.formFactor) {
|
||||
// @ts-expect-error fallback handling for emulatedFormFactor
|
||||
clone.configSettings.formFactor = clone.configSettings.emulatedFormFactor;
|
||||
}
|
||||
|
||||
clone.finalDisplayedUrl = Util.getFinalDisplayedUrl(clone);
|
||||
clone.mainDocumentUrl = Util.getMainDocumentUrl(clone);
|
||||
const clone = /** @type {LH.ReportResult} */ (JSON.parse(JSON.stringify(lhr)));
|
||||
upgradeLhrForCompatibility(clone);
|
||||
|
||||
for (const audit of Object.values(clone.audits)) {
|
||||
// Turn 'not-applicable' (LHR <4.0) and 'not_applicable' (older proto versions)
|
||||
// into 'notApplicable' (LHR ≥4.0).
|
||||
// @ts-expect-error tsc rightly flags that these values shouldn't occur.
|
||||
// eslint-disable-next-line max-len
|
||||
if (audit.scoreDisplayMode === 'not_applicable' || audit.scoreDisplayMode === 'not-applicable') {
|
||||
audit.scoreDisplayMode = 'notApplicable';
|
||||
}
|
||||
|
||||
if (audit.details) {
|
||||
// Turn `auditDetails.type` of undefined (LHR <4.2) and 'diagnostic' (LHR <5.0)
|
||||
// into 'debugdata' (LHR ≥5.0).
|
||||
// @ts-expect-error tsc rightly flags that these values shouldn't occur.
|
||||
if (audit.details.type === undefined || audit.details.type === 'diagnostic') {
|
||||
// @ts-expect-error details is of type never.
|
||||
audit.details.type = 'debugdata';
|
||||
}
|
||||
|
||||
// Add the jpg data URL prefix to filmstrip screenshots without them (LHR <5.0).
|
||||
if (audit.details.type === 'filmstrip') {
|
||||
for (const screenshot of audit.details.items) {
|
||||
if (!screenshot.data.startsWith(SCREENSHOT_PREFIX)) {
|
||||
screenshot.data = SCREENSHOT_PREFIX + screenshot.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Circa 10.0, table items were refactored.
|
||||
if (audit.details.type === 'table') {
|
||||
for (const heading of audit.details.headings) {
|
||||
/** @type {{itemType: LH.Audit.Details.ItemValueType|undefined, text: string|undefined}} */
|
||||
// @ts-expect-error
|
||||
const {itemType, text} = heading;
|
||||
if (itemType !== undefined) {
|
||||
heading.valueType = itemType;
|
||||
// @ts-expect-error
|
||||
delete heading.itemType;
|
||||
}
|
||||
if (text !== undefined) {
|
||||
heading.label = text;
|
||||
// @ts-expect-error
|
||||
delete heading.text;
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
const subItemsItemType = heading.subItemsHeading?.itemType;
|
||||
if (heading.subItemsHeading && subItemsItemType !== undefined) {
|
||||
heading.subItemsHeading.valueType = subItemsItemType;
|
||||
// @ts-expect-error
|
||||
delete heading.subItemsHeading.itemType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attach table/opportunity items with entity information.
|
||||
ReportUtils.classifyEntities(result.entities, audit);
|
||||
|
||||
// TODO: convert printf-style displayValue.
|
||||
// Added: #5099, v3
|
||||
// Removed: #6767, v4
|
||||
}
|
||||
// Attach table/opportunity items with entity information.
|
||||
ReportUtils.classifyEntities(clone.entities, audit);
|
||||
}
|
||||
|
||||
// For convenience, smoosh all AuditResults into their auditRef (which has just weight & group)
|
||||
|
@ -105,23 +36,6 @@ class ReportUtils {
|
|||
/** @type {Map<string, Array<LH.ReportResult.AuditRef>>} */
|
||||
const relevantAuditToMetricsMap = new Map();
|
||||
|
||||
// This backcompat converts old LHRs (<9.0.0) to use the new "hidden" group.
|
||||
// Old LHRs used "no group" to identify audits that should be hidden in performance instead of the "hidden" group.
|
||||
// Newer LHRs use "no group" to identify opportunities and diagnostics whose groups are assigned by details type.
|
||||
const [majorVersion] = clone.lighthouseVersion.split('.').map(Number);
|
||||
const perfCategory = clone.categories['performance'];
|
||||
if (majorVersion < 9 && perfCategory) {
|
||||
if (!clone.categoryGroups) clone.categoryGroups = {};
|
||||
clone.categoryGroups['hidden'] = {title: ''};
|
||||
for (const auditRef of perfCategory.auditRefs) {
|
||||
if (!auditRef.group) {
|
||||
auditRef.group = 'hidden';
|
||||
} else if (['load-opportunities', 'diagnostics'].includes(auditRef.group)) {
|
||||
delete auditRef.group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const category of Object.values(clone.categories)) {
|
||||
// Make basic lookup table for relevantAudits
|
||||
category.auditRefs.forEach(metricRef => {
|
||||
|
@ -158,35 +72,6 @@ class ReportUtils {
|
|||
});
|
||||
}
|
||||
|
||||
// Add some minimal stuff so older reports still work.
|
||||
if (!clone.environment) {
|
||||
// @ts-expect-error
|
||||
clone.environment = {benchmarkIndex: 0};
|
||||
}
|
||||
if (!clone.configSettings.screenEmulation) {
|
||||
// @ts-expect-error
|
||||
clone.configSettings.screenEmulation = {};
|
||||
}
|
||||
if (!clone.i18n) {
|
||||
// @ts-expect-error
|
||||
clone.i18n = {};
|
||||
}
|
||||
|
||||
// In 10.0, full-page-screenshot became a top-level property on the LHR.
|
||||
if (clone.audits['full-page-screenshot']) {
|
||||
const details = /** @type {LH.Result.FullPageScreenshot=} */ (
|
||||
clone.audits['full-page-screenshot'].details);
|
||||
if (details) {
|
||||
clone.fullPageScreenshot = {
|
||||
screenshot: details.screenshot,
|
||||
nodes: details.nodes,
|
||||
};
|
||||
} else {
|
||||
clone.fullPageScreenshot = null;
|
||||
}
|
||||
delete clone.audits['full-page-screenshot'];
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,176 +94,6 @@ describe('util helpers', () => {
|
|||
});
|
||||
|
||||
describe('#prepareReportResult', () => {
|
||||
describe('backward compatibility', () => {
|
||||
it('corrects underscored `notApplicable` scoreDisplayMode', () => {
|
||||
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
||||
|
||||
// Avoid injecting entity names into audits that would would
|
||||
// make the diff at the end of this test difficult.
|
||||
delete clonedSampleResult.entities;
|
||||
|
||||
let notApplicableCount = 0;
|
||||
Object.values(clonedSampleResult.audits).forEach(audit => {
|
||||
if (audit.scoreDisplayMode === 'notApplicable') {
|
||||
notApplicableCount++;
|
||||
audit.scoreDisplayMode = 'not_applicable';
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(notApplicableCount > 20); // Make sure something's being tested.
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = ReportUtils.prepareReportResult(clonedSampleResult);
|
||||
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
});
|
||||
|
||||
it('corrects undefined auditDetails.type to `debugdata`', () => {
|
||||
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
||||
|
||||
// Avoid injecting entity names into audits that would would
|
||||
// make the diff at the end of this test difficult.
|
||||
delete clonedSampleResult.entities;
|
||||
|
||||
// Delete debugdata details types.
|
||||
let undefinedCount = 0;
|
||||
for (const audit of Object.values(clonedSampleResult.audits)) {
|
||||
if (audit.details && audit.details.type === 'debugdata') {
|
||||
undefinedCount++;
|
||||
delete audit.details.type;
|
||||
}
|
||||
}
|
||||
assert.ok(undefinedCount > 4); // Make sure something's being tested.
|
||||
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = ReportUtils.prepareReportResult(clonedSampleResult);
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
});
|
||||
|
||||
it('corrects `diagnostic` auditDetails.type to `debugdata`', () => {
|
||||
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
||||
|
||||
// Avoid injecting entity names into audits that would would
|
||||
// make the diff at the end of this test difficult.
|
||||
delete clonedSampleResult.entities;
|
||||
|
||||
// Change debugdata details types.
|
||||
let diagnosticCount = 0;
|
||||
for (const audit of Object.values(clonedSampleResult.audits)) {
|
||||
if (audit.details && audit.details.type === 'debugdata') {
|
||||
diagnosticCount++;
|
||||
audit.details.type = 'diagnostic';
|
||||
}
|
||||
}
|
||||
assert.ok(diagnosticCount > 4); // Make sure something's being tested.
|
||||
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = ReportUtils.prepareReportResult(clonedSampleResult);
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
});
|
||||
|
||||
it('corrects screenshots in the `filmstrip` auditDetails.type', () => {
|
||||
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
||||
|
||||
// Avoid injecting entity names into audits that would would
|
||||
// make the diff at the end of this test difficult.
|
||||
delete clonedSampleResult.entities;
|
||||
|
||||
// Strip filmstrip screenshots of data URL prefix.
|
||||
let filmstripCount = 0;
|
||||
for (const audit of Object.values(clonedSampleResult.audits)) {
|
||||
if (audit.details && audit.details.type === 'filmstrip') {
|
||||
filmstripCount++;
|
||||
for (const screenshot of audit.details.items) {
|
||||
screenshot.data = screenshot.data.slice('data:image/jpeg;base64,'.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.ok(filmstripCount > 0); // Make sure something's being tested.
|
||||
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = ReportUtils.prepareReportResult(clonedSampleResult);
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
});
|
||||
|
||||
it('moves full-page-screenshot audit', () => {
|
||||
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
||||
|
||||
clonedSampleResult.audits['full-page-screenshot'] = {
|
||||
details: {
|
||||
type: 'full-page-screenshot',
|
||||
...sampleResult.fullPageScreenshot,
|
||||
},
|
||||
};
|
||||
delete clonedSampleResult.fullPageScreenshot;
|
||||
// Avoid injecting entity names into audits that would would
|
||||
// make the diff at the end of this test difficult.
|
||||
delete clonedSampleResult.entities;
|
||||
|
||||
assert.ok(clonedSampleResult.audits['full-page-screenshot'].details.nodes); // Make sure something's being tested.
|
||||
assert.notDeepStrictEqual(clonedSampleResult.audits, sampleResult.audits);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const preparedResult = ReportUtils.prepareReportResult(clonedSampleResult);
|
||||
assert.deepStrictEqual(preparedResult.audits, sampleResult.audits);
|
||||
assert.deepStrictEqual(preparedResult.fullPageScreenshot, sampleResult.fullPageScreenshot);
|
||||
});
|
||||
|
||||
it('corrects performance category without hidden group', () => {
|
||||
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
||||
|
||||
clonedSampleResult.lighthouseVersion = '8.6.0';
|
||||
delete clonedSampleResult.categoryGroups['hidden'];
|
||||
for (const auditRef of clonedSampleResult.categories['performance'].auditRefs) {
|
||||
if (auditRef.group === 'hidden') {
|
||||
delete auditRef.group;
|
||||
} else if (!auditRef.group) {
|
||||
auditRef.group = 'diagnostics';
|
||||
}
|
||||
}
|
||||
assert.notDeepStrictEqual(clonedSampleResult.categories, sampleResult.categories);
|
||||
assert.notDeepStrictEqual(clonedSampleResult.categoryGroups, sampleResult.categoryGroups);
|
||||
|
||||
// Original audit results should be restored.
|
||||
const clonedPreparedResult = ReportUtils.prepareReportResult(clonedSampleResult);
|
||||
const preparedResult = ReportUtils.prepareReportResult(sampleResult);
|
||||
assert.deepStrictEqual(clonedPreparedResult.categories, preparedResult.categories);
|
||||
assert.deepStrictEqual(clonedPreparedResult.categoryGroups, preparedResult.categoryGroups);
|
||||
});
|
||||
|
||||
it('converts old opportunity table column headings to consolidated table headings', () => {
|
||||
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
||||
|
||||
// Avoid injecting entity names into audits that would would
|
||||
// make the diff at the end of this test difficult.
|
||||
delete clonedSampleResult.entities;
|
||||
|
||||
const auditsWithTableDetails = Object.values(clonedSampleResult.audits)
|
||||
.filter(audit => audit.details?.type === 'table');
|
||||
assert.notEqual(auditsWithTableDetails.length, 0);
|
||||
for (const audit of auditsWithTableDetails) {
|
||||
for (const heading of audit.details.headings) {
|
||||
heading.itemType = heading.valueType;
|
||||
heading.text = heading.label;
|
||||
delete heading.valueType;
|
||||
delete heading.label;
|
||||
|
||||
if (heading.subItemsHeading) {
|
||||
heading.subItemsHeading.itemType = heading.subItemsHeading.valueType;
|
||||
// @ts-expect-error
|
||||
delete heading.subItemsHeading.valueType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const preparedResult = ReportUtils.prepareReportResult(clonedSampleResult);
|
||||
assert.deepStrictEqual(sampleResult.audits, preparedResult.audits);
|
||||
});
|
||||
});
|
||||
|
||||
it('appends stack pack descriptions to auditRefs', () => {
|
||||
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
||||
const iconDataURL = 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg"%3E%3C/svg%3E';
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"include": [
|
||||
"**/*.js",
|
||||
"types/**/*.d.ts",
|
||||
"../core/lib/lighthouse-compatibility.js",
|
||||
],
|
||||
"exclude": [
|
||||
"generator/**/*.js",
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
"core/test/lib/i18n/i18n-test.js",
|
||||
"core/test/lib/icons-test.js",
|
||||
"core/test/lib/lh-element-test.js",
|
||||
"core/test/lib/lighthouse-compatibility-test.js",
|
||||
"core/test/lib/manifest-parser-test.js",
|
||||
"core/test/lib/median-run-test.js",
|
||||
"core/test/lib/minification-estimator-test.js",
|
||||
|
|
Загрузка…
Ссылка в новой задаче