lighthouse 9.5.0-dev.20221019 → 9.5.0-dev.20221020
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/audits/accessibility/axe-audit.js +1 -1
- package/core/audits/autocomplete.js +3 -3
- package/core/audits/bootup-time.js +5 -5
- package/core/audits/byte-efficiency/duplicated-javascript.js +1 -1
- package/core/audits/byte-efficiency/legacy-javascript.js +1 -1
- package/core/audits/byte-efficiency/total-byte-weight.js +2 -2
- package/core/audits/byte-efficiency/uses-long-cache-ttl.js +3 -3
- package/core/audits/byte-efficiency/uses-responsive-images-snapshot.js +4 -4
- package/core/audits/csp-xss.js +3 -3
- package/core/audits/deprecations.js +2 -2
- package/core/audits/dobetterweb/dom-size.js +3 -3
- package/core/audits/dobetterweb/geolocation-on-start.js +1 -1
- package/core/audits/dobetterweb/inspector-issues.js +1 -1
- package/core/audits/dobetterweb/js-libraries.js +2 -2
- package/core/audits/dobetterweb/no-document-write.js +1 -1
- package/core/audits/dobetterweb/notification-on-start.js +1 -1
- package/core/audits/dobetterweb/password-inputs-can-be-pasted-into.js +1 -1
- package/core/audits/dobetterweb/uses-http2.js +2 -2
- package/core/audits/dobetterweb/uses-passive-event-listeners.js +1 -1
- package/core/audits/errors-in-console.js +4 -2
- package/core/audits/font-display.js +2 -2
- package/core/audits/image-aspect-ratio.js +4 -4
- package/core/audits/image-size-responsive.js +5 -5
- package/core/audits/installable-manifest.js +1 -1
- package/core/audits/is-on-https.js +2 -2
- package/core/audits/largest-contentful-paint-element.js +1 -1
- package/core/audits/layout-shift-elements.js +3 -3
- package/core/audits/lcp-lazy-loaded.js +1 -1
- package/core/audits/long-tasks.js +3 -3
- package/core/audits/main-thread-tasks.js +2 -2
- package/core/audits/mainthread-work-breakdown.js +4 -2
- package/core/audits/network-requests.js +11 -11
- package/core/audits/network-rtt.js +2 -2
- package/core/audits/network-server-latency.js +3 -3
- package/core/audits/no-unload-listeners.js +1 -1
- package/core/audits/non-composited-animations.js +2 -2
- package/core/audits/performance-budget.js +5 -5
- package/core/audits/preload-fonts.js +1 -1
- package/core/audits/resource-summary.js +3 -3
- package/core/audits/seo/crawlable-anchors.js +2 -2
- package/core/audits/seo/font-size.js +4 -4
- package/core/audits/seo/hreflang.js +3 -3
- package/core/audits/seo/is-crawlable.js +1 -1
- package/core/audits/seo/link-text.js +2 -2
- package/core/audits/seo/plugins.js +1 -1
- package/core/audits/seo/robots-txt.js +3 -3
- package/core/audits/seo/tap-targets.js +3 -3
- package/core/audits/themed-omnibox.js +6 -14
- package/core/audits/third-party-facades.js +3 -3
- package/core/audits/third-party-summary.js +3 -3
- package/core/audits/timing-budget.js +3 -3
- package/core/audits/unsized-images.js +2 -2
- package/core/audits/user-timings.js +6 -6
- package/core/audits/valid-source-maps.js +3 -3
- package/core/audits/work-during-interaction.js +6 -6
- package/core/lib/bfcache-strings.js +655 -0
- package/core/lib/deprecations-strings.js +3 -2
- package/core/lib/manifest-parser.js +0 -16
- package/core/user-flow.js +64 -8
- package/core/util.cjs +27 -0
- package/dist/report/bundle.esm.js +38 -73
- package/dist/report/flow.js +2 -2
- package/dist/report/standalone.js +2 -2
- package/package.json +2 -3
- package/report/renderer/details-renderer.js +12 -73
- package/report/renderer/util.js +27 -0
- package/report/test/renderer/details-renderer-test.js +38 -38
- package/report/test/renderer/util-test.js +25 -0
- package/shared/localization/locales/en-US.json +352 -1
- package/shared/localization/locales/en-XL.json +352 -1
- package/types/lhr/audit-details.d.ts +4 -34
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
|
-
*/const e="…",t="data:image/jpeg;base64,",n={label:"pass",minScore:.9},r={label:"average",minScore:.5},o={label:"fail"},i={label:"error"},a=["com","co","gov","edu","ac","org","go","gob","or","net","in","ne","nic","gouv","web","spb","blog","jus","kiev","mil","wi","qc","ca","bel","on"];class l{static i18n=null;static get PASS_THRESHOLD(){return.9}static get MS_DISPLAY_VALUE(){return"%10d ms"}static getFinalDisplayedUrl(e){if(e.finalDisplayedUrl)return e.finalDisplayedUrl;if(e.finalUrl)return e.finalUrl;throw new Error("Could not determine final displayed URL")}static getMainDocumentUrl(e){return e.mainDocumentUrl||e.finalUrl}static prepareReportResult(e){const n=JSON.parse(JSON.stringify(e));n.configSettings.locale||(n.configSettings.locale="en"),n.configSettings.formFactor||(n.configSettings.formFactor=n.configSettings.emulatedFormFactor),n.finalDisplayedUrl=this.getFinalDisplayedUrl(n),n.mainDocumentUrl=this.getMainDocumentUrl(n);for(const e of Object.values(n.audits))if("not_applicable"!==e.scoreDisplayMode&&"not-applicable"!==e.scoreDisplayMode||(e.scoreDisplayMode="notApplicable"),e.details
|
|
17
|
+
*/const e="…",t="data:image/jpeg;base64,",n={label:"pass",minScore:.9},r={label:"average",minScore:.5},o={label:"fail"},i={label:"error"},a=["com","co","gov","edu","ac","org","go","gob","or","net","in","ne","nic","gouv","web","spb","blog","jus","kiev","mil","wi","qc","ca","bel","on"];class l{static i18n=null;static get PASS_THRESHOLD(){return.9}static get MS_DISPLAY_VALUE(){return"%10d ms"}static getFinalDisplayedUrl(e){if(e.finalDisplayedUrl)return e.finalDisplayedUrl;if(e.finalUrl)return e.finalUrl;throw new Error("Could not determine final displayed URL")}static getMainDocumentUrl(e){return e.mainDocumentUrl||e.finalUrl}static prepareReportResult(e){const n=JSON.parse(JSON.stringify(e));n.configSettings.locale||(n.configSettings.locale="en"),n.configSettings.formFactor||(n.configSettings.formFactor=n.configSettings.emulatedFormFactor),n.finalDisplayedUrl=this.getFinalDisplayedUrl(n),n.mainDocumentUrl=this.getMainDocumentUrl(n);for(const e of Object.values(n.audits))if("not_applicable"!==e.scoreDisplayMode&&"not-applicable"!==e.scoreDisplayMode||(e.scoreDisplayMode="notApplicable"),e.details){if(void 0!==e.details.type&&"diagnostic"!==e.details.type||(e.details.type="debugdata"),"filmstrip"===e.details.type)for(const n of e.details.items)n.data.startsWith(t)||(n.data=t+n.data);if("table"===e.details.type)for(const t of e.details.headings){const{itemType:e,text:n}=t;void 0!==e&&(t.valueType=e,delete t.itemType),void 0!==n&&(t.label=n,delete t.text);const r=t.subItemsHeading?.itemType;t.subItemsHeading&&void 0!==r&&(t.subItemsHeading.valueType=r,delete t.subItemsHeading.itemType)}}if("object"!=typeof n.categories)throw new Error("No categories provided.");const r=new Map,[o]=n.lighthouseVersion.split(".").map(Number),i=n.categories.performance;if(o<9&&i){n.categoryGroups||(n.categoryGroups={}),n.categoryGroups.hidden={title:""};for(const e of i.auditRefs)e.group?["load-opportunities","diagnostics"].includes(e.group)&&delete e.group:e.group="hidden"}for(const e of Object.values(n.categories))e.auditRefs.forEach((e=>{e.relevantAudits&&e.relevantAudits.forEach((t=>{const n=r.get(t)||[];n.push(e),r.set(t,n)}))})),e.auditRefs.forEach((e=>{const t=n.audits[e.id];e.result=t,r.has(e.id)&&(e.relevantMetrics=r.get(e.id)),n.stackPacks&&n.stackPacks.forEach((t=>{t.descriptions[e.id]&&(e.stackPacks=e.stackPacks||[],e.stackPacks.push({title:t.title,iconDataURL:t.iconDataURL,description:t.descriptions[e.id]}))}))}));return n}static showAsPassed(e){switch(e.scoreDisplayMode){case"manual":case"notApplicable":return!0;case"error":case"informative":return!1;case"numeric":case"binary":default:return Number(e.score)>=n.minScore}}static calculateRating(e,t){if("manual"===t||"notApplicable"===t)return n.label;if("error"===t)return i.label;if(null===e)return o.label;let a=o.label;return e>=n.minScore?a=n.label:e>=r.minScore&&(a=r.label),a}static splitMarkdownCodeSpans(e){const t=[],n=e.split(/`(.*?)`/g);for(let e=0;e<n.length;e++){const r=n[e];if(!r)continue;const o=e%2!=0;t.push({isCode:o,text:r})}return t}static splitMarkdownLink(e){const t=[],n=e.split(/\[([^\]]+?)\]\((https?:\/\/.*?)\)/g);for(;n.length;){const[e,r,o]=n.splice(0,3);e&&t.push({isLink:!1,text:e}),r&&o&&t.push({isLink:!0,text:r,linkHref:o})}return t}static getURLDisplayName(t,n){const r=void 0!==(n=n||{numPathParts:void 0,preserveQuery:void 0,preserveHost:void 0}).numPathParts?n.numPathParts:2,o=void 0===n.preserveQuery||n.preserveQuery,i=n.preserveHost||!1;let a;if("about:"===t.protocol||"data:"===t.protocol)a=t.href;else{a=t.pathname;const n=a.split("/").filter((e=>e.length));r&&n.length>r&&(a=e+n.slice(-1*r).join("/")),i&&(a=`${t.host}/${a.replace(/^\//,"")}`),o&&(a=`${a}${t.search}`)}if("data:"!==t.protocol&&(a=a.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g,"$1…"),a=a.replace(/([a-zA-Z0-9-_]{9})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9-_]{10,}/g,"$1…"),a=a.replace(/(\d{3})\d{6,}/g,"$1…"),a=a.replace(/\u2026+/g,e),a.length>64&&a.includes("?")&&(a=a.replace(/\?([^=]*)(=)?.*/,"?$1$2…"),a.length>64&&(a=a.replace(/\?.*/,"?…")))),a.length>64){const t=a.lastIndexOf(".");a=t>=0?a.slice(0,63-(a.length-t))+`…${a.slice(t)}`:a.slice(0,63)+e}return a}static parseURL(e){const t=new URL(e);return{file:l.getURLDisplayName(t),hostname:t.hostname,origin:t.origin}}static createOrReturnURL(e){return e instanceof URL?e:new URL(e)}static getTld(e){const t=e.split(".").slice(-2);return a.includes(t[0])?`.${t.join(".")}`:`.${t[t.length-1]}`}static getRootDomain(e){const t=l.createOrReturnURL(e).hostname,n=l.getTld(t).split(".");return t.split(".").slice(-n.length).join(".")}static getEmulationDescriptions(e){let t,n,r;const o=e.throttling;switch(e.throttlingMethod){case"provided":r=n=t=l.i18n.strings.throttlingProvided;break;case"devtools":{const{cpuSlowdownMultiplier:e,requestLatencyMs:i}=o;t=`${l.i18n.formatNumber(e)}x slowdown (DevTools)`,n=`${l.i18n.formatMilliseconds(i)} HTTP RTT, ${l.i18n.formatKbps(o.downloadThroughputKbps)} down, ${l.i18n.formatKbps(o.uploadThroughputKbps)} up (DevTools)`;r=(()=>562.5===i&&o.downloadThroughputKbps===1638.4*.9&&675===o.uploadThroughputKbps)()?l.i18n.strings.runtimeSlow4g:l.i18n.strings.runtimeCustom;break}case"simulate":{const{cpuSlowdownMultiplier:e,rttMs:i,throughputKbps:a}=o;t=`${l.i18n.formatNumber(e)}x slowdown (Simulated)`,n=`${l.i18n.formatMilliseconds(i)} TCP RTT, ${l.i18n.formatKbps(a)} throughput (Simulated)`;r=(()=>150===i&&1638.4===a)()?l.i18n.strings.runtimeSlow4g:l.i18n.strings.runtimeCustom;break}default:r=t=n=l.i18n.strings.runtimeUnknown}return{deviceEmulation:{mobile:l.i18n.strings.runtimeMobileEmulation,desktop:l.i18n.strings.runtimeDesktopEmulation}[e.formFactor]||l.i18n.strings.runtimeNoEmulation,cpuThrottling:t,networkThrottling:n,summary:r}}static filterRelevantLines(e,t,n){if(0===t.length)return e.slice(0,2*n+1);const r=new Set;return(t=t.sort(((e,t)=>(e.lineNumber||0)-(t.lineNumber||0)))).forEach((({lineNumber:e})=>{let t=e-n,o=e+n;for(;t<1;)t++,o++;r.has(t-3-1)&&(t-=3);for(let e=t;e<=o;e++){const t=e;r.add(t)}})),e.filter((e=>r.has(e.lineNumber)))}static isPluginCategory(e){return e.startsWith("lighthouse-plugin-")}static shouldDisplayAsFraction(e){return"timespan"===e||"snapshot"===e}static calculateCategoryFraction(e){let t=0,n=0,r=0,o=0;for(const i of e.auditRefs){const e=l.showAsPassed(i.result);"hidden"!==i.group&&"manual"!==i.result.scoreDisplayMode&&"notApplicable"!==i.result.scoreDisplayMode&&("informative"!==i.result.scoreDisplayMode?(++t,o+=i.weight,e&&n++):e||++r)}return{numPassed:n,numPassableAudits:t,numInformative:r,totalWeight:o}}}l.reportJson=null;let s=0;l.getUniqueSuffix=()=>s++,l.resetUniqueSuffix=()=>{s=0};l.UIStrings={varianceDisclaimer:"Values are estimated and may vary. The [performance score is calculated](https://web.dev/performance-scoring/) directly from these metrics.",calculatorLink:"See calculator.",showRelevantAudits:"Show audits relevant to:",opportunityResourceColumnLabel:"Opportunity",opportunitySavingsColumnLabel:"Estimated Savings",errorMissingAuditInfo:"Report error: no audit information",errorLabel:"Error!",warningHeader:"Warnings: ",warningAuditsGroupTitle:"Passed audits but with warnings",passedAuditsGroupTitle:"Passed audits",notApplicableAuditsGroupTitle:"Not applicable",manualAuditsGroupTitle:"Additional items to manually check",toplevelWarningsMessage:"There were issues affecting this run of Lighthouse:",crcInitialNavigation:"Initial Navigation",crcLongestDurationLabel:"Maximum critical path latency:",snippetExpandButtonLabel:"Expand snippet",snippetCollapseButtonLabel:"Collapse snippet",lsPerformanceCategoryDescription:"[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary.",labDataTitle:"Lab Data",thirdPartyResourcesLabel:"Show 3rd-party resources",viewTreemapLabel:"View Treemap",viewTraceLabel:"View Trace",viewOriginalTraceLabel:"View Original Trace",dropdownPrintSummary:"Print Summary",dropdownPrintExpanded:"Print Expanded",dropdownCopyJSON:"Copy JSON",dropdownSaveHTML:"Save as HTML",dropdownSaveJSON:"Save as JSON",dropdownViewer:"Open in Viewer",dropdownSaveGist:"Save as Gist",dropdownDarkTheme:"Toggle Dark Theme",runtimeSettingsDevice:"Device",runtimeSettingsNetworkThrottling:"Network throttling",runtimeSettingsCPUThrottling:"CPU throttling",runtimeSettingsUANetwork:"User agent (network)",runtimeSettingsBenchmark:"CPU/Memory Power",runtimeSettingsAxeVersion:"Axe version",footerIssue:"File an issue",runtimeNoEmulation:"No emulation",runtimeMobileEmulation:"Emulated Moto G4",runtimeDesktopEmulation:"Emulated Desktop",runtimeUnknown:"Unknown",runtimeSingleLoad:"Single page load",runtimeAnalysisWindow:"Initial page load",runtimeSingleLoadTooltip:"This data is taken from a single page load, as opposed to field data summarizing many sessions.",throttlingProvided:"Provided by environment",show:"Show",hide:"Hide",expandView:"Expand view",collapseView:"Collapse view",runtimeSlow4g:"Slow 4G throttling",runtimeCustom:"Custom throttling"};
|
|
18
18
|
/**
|
|
19
19
|
* @license
|
|
20
20
|
* Copyright 2017 The Lighthouse Authors. All Rights Reserved.
|
|
@@ -84,7 +84,7 @@ class c{constructor(e,t){this._document=e,this._lighthouseChannel="unknown",this
|
|
|
84
84
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
85
85
|
* See the License for the specific language governing permissions and
|
|
86
86
|
* limitations under the License.
|
|
87
|
-
*/const m=["http://","https://","data:"];class f{constructor(e,t={}){this._dom=e,this._fullPageScreenshot=t.fullPageScreenshot}render(e){switch(e.type){case"filmstrip":return this._renderFilmstrip(e);case"list":return this._renderList(e);case"table":return this._renderTable(e);case"criticalrequestchain":return h.render(this._dom,e,this);case"
|
|
87
|
+
*/const m=["http://","https://","data:"];class f{constructor(e,t={}){this._dom=e,this._fullPageScreenshot=t.fullPageScreenshot}render(e){switch(e.type){case"filmstrip":return this._renderFilmstrip(e);case"list":return this._renderList(e);case"table":case"opportunity":return this._renderTable(e);case"criticalrequestchain":return h.render(this._dom,e,this);case"screenshot":case"debugdata":case"full-page-screenshot":case"treemap-data":return null;default:return this._renderUnknown(e.type,e)}}_renderBytes(e){const t=l.i18n.formatBytesToKiB(e.value,e.granularity||.1),n=this._renderText(t);return n.title=l.i18n.formatBytes(e.value),n}_renderMilliseconds(e){let t;return t="duration"===e.displayUnit?l.i18n.formatDuration(e.value):l.i18n.formatMilliseconds(e.value,e.granularity||10),this._renderText(t)}renderTextURL(e){const t=e;let n,r,o;try{const e=l.parseURL(t);n="/"===e.file?e.origin:e.file,r="/"===e.file||""===e.hostname?"":`(${e.hostname})`,o=t}catch(e){n=t}const i=this._dom.createElement("div","lh-text__url");if(i.append(this._renderLink({text:n,url:t})),r){const e=this._renderText(r);e.classList.add("lh-text__url-host"),i.append(e)}return o&&(i.title=t,i.dataset.url=t),i}_renderLink(e){const t=this._dom.createElement("a");if(this._dom.safelySetHref(t,e.url),!t.href){const t=this._renderText(e.text);return t.classList.add("lh-link"),t}return t.rel="noopener",t.target="_blank",t.textContent=e.text,t.classList.add("lh-link"),t}_renderText(e){const t=this._dom.createElement("div","lh-text");return t.textContent=e,t}_renderNumeric(e){const t=l.i18n.formatNumber(e.value,e.granularity||.1),n=this._dom.createElement("div","lh-numeric");return n.textContent=t,n}_renderThumbnail(e){const t=this._dom.createElement("img","lh-thumbnail"),n=e;return t.src=n,t.title=n,t.alt="",t}_renderUnknown(e,t){console.error(`Unknown details type: ${e}`,t);const n=this._dom.createElement("details","lh-unknown");return this._dom.createChildOf(n,"summary").textContent=`We don't know how to render audit details of type \`${e}\`. The Lighthouse version that collected this data is likely newer than the Lighthouse version of the report renderer. Expand for the raw JSON.`,this._dom.createChildOf(n,"pre").textContent=JSON.stringify(t,null,2),n}_renderTableValue(e,t){if(null==e)return null;if("object"==typeof e)switch(e.type){case"code":return this._renderCode(e.value);case"link":return this._renderLink(e);case"node":return this.renderNode(e);case"numeric":return this._renderNumeric(e);case"source-location":return this.renderSourceLocation(e);case"url":return this.renderTextURL(e.value);default:return this._renderUnknown(e.type,e)}switch(t.valueType){case"bytes":{const n=Number(e);return this._renderBytes({value:n,granularity:t.granularity})}case"code":{const t=String(e);return this._renderCode(t)}case"ms":{const n={value:Number(e),granularity:t.granularity,displayUnit:t.displayUnit};return this._renderMilliseconds(n)}case"numeric":{const n=Number(e);return this._renderNumeric({value:n,granularity:t.granularity})}case"text":{const t=String(e);return this._renderText(t)}case"thumbnail":{const t=String(e);return this._renderThumbnail(t)}case"timespanMs":{const t=Number(e);return this._renderMilliseconds({value:t})}case"url":{const t=String(e);return m.some((e=>t.startsWith(e)))?this.renderTextURL(t):this._renderCode(t)}default:return this._renderUnknown(t.valueType,e)}}_getDerivedSubItemsHeading(e){return e.subItemsHeading?{key:e.subItemsHeading.key||"",valueType:e.subItemsHeading.valueType||e.valueType,granularity:e.subItemsHeading.granularity||e.granularity,displayUnit:e.subItemsHeading.displayUnit||e.displayUnit,label:""}:null}_renderTableRow(e,t){const n=this._dom.createElement("tr");for(const r of t){if(!r||!r.key){this._dom.createChildOf(n,"td","lh-table-column--empty");continue}const t=e[r.key];let o;if(null!=t&&(o=this._renderTableValue(t,r)),o){const e=`lh-table-column--${r.valueType}`;this._dom.createChildOf(n,"td",e).append(o)}else this._dom.createChildOf(n,"td","lh-table-column--empty")}return n}_renderTableRowsFromItem(e,t){const n=this._dom.createFragment();if(n.append(this._renderTableRow(e,t)),!e.subItems)return n;const r=t.map(this._getDerivedSubItemsHeading);if(!r.some(Boolean))return n;for(const t of e.subItems.items){const e=this._renderTableRow(t,r);e.classList.add("lh-sub-item-row"),n.append(e)}return n}_renderTable(e){if(!e.items.length)return this._dom.createElement("span");const t=this._dom.createElement("table","lh-table"),n=this._dom.createChildOf(t,"thead"),r=this._dom.createChildOf(n,"tr");for(const t of e.headings){const e=`lh-table-column--${t.valueType||"text"}`,n=this._dom.createElement("div","lh-text");n.textContent=t.label,this._dom.createChildOf(r,"th",e).append(n)}const o=this._dom.createChildOf(t,"tbody");let i=!0;for(const t of e.items){const n=this._renderTableRowsFromItem(t,e.headings);for(const e of this._dom.findAll("tr",n))e.classList.add(i?"lh-row--even":"lh-row--odd");i=!i,o.append(n)}return t}_renderList(e){const t=this._dom.createElement("div","lh-list");return e.items.forEach((e=>{const n=this.render(e);n&&t.append(n)})),t}renderNode(e){const t=this._dom.createElement("span","lh-node");if(e.nodeLabel){const n=this._dom.createElement("div");n.textContent=e.nodeLabel,t.append(n)}if(e.snippet){const n=this._dom.createElement("div");n.classList.add("lh-node__snippet"),n.textContent=e.snippet,t.append(n)}if(e.selector&&(t.title=e.selector),e.path&&t.setAttribute("data-path",e.path),e.selector&&t.setAttribute("data-selector",e.selector),e.snippet&&t.setAttribute("data-snippet",e.snippet),!this._fullPageScreenshot)return t;const n=e.lhId&&this._fullPageScreenshot.nodes[e.lhId];if(!n||0===n.width||0===n.height)return t;const r=g.render(this._dom,this._fullPageScreenshot.screenshot,n,{width:147,height:100});return r&&t.prepend(r),t}renderSourceLocation(e){if(!e.url)return null;const t=`${e.url}:${e.line+1}:${e.column}`;let n,r;if(e.original){n=`${e.original.file||"<unmapped>"}:${e.original.line+1}:${e.original.column}`}if("network"===e.urlProvider&&n)r=this._renderLink({url:e.url,text:n}),r.title=`maps to generated location ${t}`;else if("network"!==e.urlProvider||n)if("comment"===e.urlProvider&&n)r=this._renderText(`${n} (from source map)`),r.title=`${t} (from sourceURL)`;else{if("comment"!==e.urlProvider||n)return null;r=this._renderText(`${t} (from sourceURL)`)}else r=this.renderTextURL(e.url),this._dom.find(".lh-link",r).textContent+=`:${e.line+1}:${e.column}`;return r.classList.add("lh-source-location"),r.setAttribute("data-source-url",e.url),r.setAttribute("data-source-line",String(e.line)),r.setAttribute("data-source-column",String(e.column)),r}_renderFilmstrip(e){const t=this._dom.createElement("div","lh-filmstrip");for(const n of e.items){const e=this._dom.createChildOf(t,"div","lh-filmstrip__frame"),r=this._dom.createChildOf(e,"img","lh-filmstrip__thumbnail");r.src=n.data,r.alt="Screenshot"}return t}_renderCode(e){const t=this._dom.createElement("pre","lh-code");return t.textContent=e,t}}
|
|
88
88
|
/**
|
|
89
89
|
* @license Copyright 2020 The Lighthouse Authors. All Rights Reserved.
|
|
90
90
|
* 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
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "9.5.0-dev.
|
|
4
|
+
"version": "9.5.0-dev.20221020",
|
|
5
5
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
6
6
|
"main": "./core/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
"archiver": "^3.0.0",
|
|
135
135
|
"c8": "^7.11.3",
|
|
136
136
|
"chalk": "^2.4.1",
|
|
137
|
-
"chrome-devtools-frontend": "1.0.
|
|
137
|
+
"chrome-devtools-frontend": "1.0.1040857",
|
|
138
138
|
"concurrently": "^6.4.0",
|
|
139
139
|
"conventional-changelog-cli": "^2.1.1",
|
|
140
140
|
"cpy": "^8.1.2",
|
|
@@ -188,7 +188,6 @@
|
|
|
188
188
|
"chrome-launcher": "^0.15.1",
|
|
189
189
|
"configstore": "^5.0.1",
|
|
190
190
|
"csp_evaluator": "1.1.1",
|
|
191
|
-
"cssstyle": "1.2.1",
|
|
192
191
|
"enquirer": "^2.3.6",
|
|
193
192
|
"http-link-header": "^0.8.0",
|
|
194
193
|
"intl-messageformat": "^4.4.0",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
/** @typedef {LH.FormattedIcu<LH.Audit.Details.Table>} Table */
|
|
24
24
|
/** @typedef {LH.FormattedIcu<LH.Audit.Details.TableItem>} TableItem */
|
|
25
25
|
/** @typedef {LH.FormattedIcu<LH.Audit.Details.ItemValue>} TableItemValue */
|
|
26
|
+
/** @typedef {LH.FormattedIcu<LH.Audit.Details.TableColumnHeading>} TableColumnHeading */
|
|
26
27
|
|
|
27
28
|
import {Util} from './util.js';
|
|
28
29
|
import {CriticalRequestChainRenderer} from './crc-details-renderer.js';
|
|
@@ -51,11 +52,10 @@ export class DetailsRenderer {
|
|
|
51
52
|
case 'list':
|
|
52
53
|
return this._renderList(details);
|
|
53
54
|
case 'table':
|
|
55
|
+
case 'opportunity':
|
|
54
56
|
return this._renderTable(details);
|
|
55
57
|
case 'criticalrequestchain':
|
|
56
58
|
return CriticalRequestChainRenderer.render(this._dom, details, this);
|
|
57
|
-
case 'opportunity':
|
|
58
|
-
return this._renderTable(details);
|
|
59
59
|
|
|
60
60
|
// Internal-only details, not for rendering.
|
|
61
61
|
case 'screenshot':
|
|
@@ -213,7 +213,7 @@ export class DetailsRenderer {
|
|
|
213
213
|
* based on the heading's valueType, unless the value itself has a `type`
|
|
214
214
|
* property to override it.
|
|
215
215
|
* @param {TableItemValue} value
|
|
216
|
-
* @param {LH.Audit.Details.
|
|
216
|
+
* @param {LH.Audit.Details.TableColumnHeading} heading
|
|
217
217
|
* @return {Element|null}
|
|
218
218
|
*/
|
|
219
219
|
_renderTableValue(value, heading) {
|
|
@@ -298,73 +298,14 @@ export class DetailsRenderer {
|
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
/**
|
|
302
|
-
* Get the headings of a table-like details object, converted into the
|
|
303
|
-
* OpportunityColumnHeading type until we have all details use the same
|
|
304
|
-
* heading format.
|
|
305
|
-
* @param {Table|OpportunityTable} tableLike
|
|
306
|
-
* @return {OpportunityTable['headings']}
|
|
307
|
-
*/
|
|
308
|
-
_getCanonicalizedHeadingsFromTable(tableLike) {
|
|
309
|
-
if (tableLike.type === 'opportunity') {
|
|
310
|
-
return tableLike.headings;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return tableLike.headings.map(heading => this._getCanonicalizedHeading(heading));
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Get the headings of a table-like details object, converted into the
|
|
318
|
-
* OpportunityColumnHeading type until we have all details use the same
|
|
319
|
-
* heading format.
|
|
320
|
-
* @param {Table['headings'][number]} heading
|
|
321
|
-
* @return {OpportunityTable['headings'][number]}
|
|
322
|
-
*/
|
|
323
|
-
_getCanonicalizedHeading(heading) {
|
|
324
|
-
let subItemsHeading;
|
|
325
|
-
if (heading.subItemsHeading) {
|
|
326
|
-
subItemsHeading = this._getCanonicalizedsubItemsHeading(heading.subItemsHeading, heading);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return {
|
|
330
|
-
key: heading.key,
|
|
331
|
-
valueType: heading.itemType,
|
|
332
|
-
subItemsHeading,
|
|
333
|
-
label: heading.text,
|
|
334
|
-
displayUnit: heading.displayUnit,
|
|
335
|
-
granularity: heading.granularity,
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* @param {Exclude<LH.Audit.Details.TableColumnHeading['subItemsHeading'], undefined>} subItemsHeading
|
|
341
|
-
* @param {LH.Audit.Details.TableColumnHeading} parentHeading
|
|
342
|
-
* @return {LH.Audit.Details.OpportunityColumnHeading['subItemsHeading']}
|
|
343
|
-
*/
|
|
344
|
-
_getCanonicalizedsubItemsHeading(subItemsHeading, parentHeading) {
|
|
345
|
-
// Low-friction way to prevent committing a falsy key (which is never allowed for
|
|
346
|
-
// a subItemsHeading) from passing in CI.
|
|
347
|
-
if (!subItemsHeading.key) {
|
|
348
|
-
// eslint-disable-next-line no-console
|
|
349
|
-
console.warn('key should not be null');
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
return {
|
|
353
|
-
key: subItemsHeading.key || '',
|
|
354
|
-
valueType: subItemsHeading.itemType || parentHeading.itemType,
|
|
355
|
-
granularity: subItemsHeading.granularity || parentHeading.granularity,
|
|
356
|
-
displayUnit: subItemsHeading.displayUnit || parentHeading.displayUnit,
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
|
|
360
301
|
/**
|
|
361
302
|
* Returns a new heading where the values are defined first by `heading.subItemsHeading`,
|
|
362
303
|
* and secondly by `heading`. If there is no subItemsHeading, returns null, which will
|
|
363
304
|
* be rendered as an empty column.
|
|
364
|
-
* @param {LH.Audit.Details.
|
|
365
|
-
* @return {LH.Audit.Details.
|
|
305
|
+
* @param {LH.Audit.Details.TableColumnHeading} heading
|
|
306
|
+
* @return {LH.Audit.Details.TableColumnHeading | null}
|
|
366
307
|
*/
|
|
367
|
-
|
|
308
|
+
_getDerivedSubItemsHeading(heading) {
|
|
368
309
|
if (!heading.subItemsHeading) return null;
|
|
369
310
|
return {
|
|
370
311
|
key: heading.subItemsHeading.key || '',
|
|
@@ -377,7 +318,7 @@ export class DetailsRenderer {
|
|
|
377
318
|
|
|
378
319
|
/**
|
|
379
320
|
* @param {TableItem} item
|
|
380
|
-
* @param {(LH.Audit.Details.
|
|
321
|
+
* @param {(LH.Audit.Details.TableColumnHeading | null)[]} headings
|
|
381
322
|
*/
|
|
382
323
|
_renderTableRow(item, headings) {
|
|
383
324
|
const rowElem = this._dom.createElement('tr');
|
|
@@ -414,7 +355,7 @@ export class DetailsRenderer {
|
|
|
414
355
|
* Renders one or more rows from a details table item. A single table item can
|
|
415
356
|
* expand into multiple rows, if there is a subItemsHeading.
|
|
416
357
|
* @param {TableItem} item
|
|
417
|
-
* @param {LH.Audit.Details.
|
|
358
|
+
* @param {LH.Audit.Details.TableColumnHeading[]} headings
|
|
418
359
|
*/
|
|
419
360
|
_renderTableRowsFromItem(item, headings) {
|
|
420
361
|
const fragment = this._dom.createFragment();
|
|
@@ -422,7 +363,7 @@ export class DetailsRenderer {
|
|
|
422
363
|
|
|
423
364
|
if (!item.subItems) return fragment;
|
|
424
365
|
|
|
425
|
-
const subItemsHeadings = headings.map(this.
|
|
366
|
+
const subItemsHeadings = headings.map(this._getDerivedSubItemsHeading);
|
|
426
367
|
if (!subItemsHeadings.some(Boolean)) return fragment;
|
|
427
368
|
|
|
428
369
|
for (const subItem of item.subItems.items) {
|
|
@@ -435,7 +376,7 @@ export class DetailsRenderer {
|
|
|
435
376
|
}
|
|
436
377
|
|
|
437
378
|
/**
|
|
438
|
-
* @param {
|
|
379
|
+
* @param {{headings: TableColumnHeading[], items: TableItem[]}} details
|
|
439
380
|
* @return {Element}
|
|
440
381
|
*/
|
|
441
382
|
_renderTable(details) {
|
|
@@ -445,9 +386,7 @@ export class DetailsRenderer {
|
|
|
445
386
|
const theadElem = this._dom.createChildOf(tableElem, 'thead');
|
|
446
387
|
const theadTrElem = this._dom.createChildOf(theadElem, 'tr');
|
|
447
388
|
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
for (const heading of headings) {
|
|
389
|
+
for (const heading of details.headings) {
|
|
451
390
|
const valueType = heading.valueType || 'text';
|
|
452
391
|
const classes = `lh-table-column--${valueType}`;
|
|
453
392
|
const labelEl = this._dom.createElement('div', 'lh-text');
|
|
@@ -458,7 +397,7 @@ export class DetailsRenderer {
|
|
|
458
397
|
const tbodyElem = this._dom.createChildOf(tableElem, 'tbody');
|
|
459
398
|
let even = true;
|
|
460
399
|
for (const item of details.items) {
|
|
461
|
-
const rowsFragment = this._renderTableRowsFromItem(item, headings);
|
|
400
|
+
const rowsFragment = this._renderTableRowsFromItem(item, details.headings);
|
|
462
401
|
for (const rowEl of this._dom.findAll('tr', rowsFragment)) {
|
|
463
402
|
// For zebra styling.
|
|
464
403
|
rowEl.classList.add(even ? 'lh-row--even' : 'lh-row--odd');
|
package/report/renderer/util.js
CHANGED
|
@@ -123,6 +123,33 @@ class Util {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
+
|
|
127
|
+
// Circa 10.0, table items were refactored.
|
|
128
|
+
if (audit.details.type === 'table') {
|
|
129
|
+
for (const heading of audit.details.headings) {
|
|
130
|
+
/** @type {{itemType: LH.Audit.Details.ItemValueType|undefined, text: string|undefined}} */
|
|
131
|
+
// @ts-expect-error
|
|
132
|
+
const {itemType, text} = heading;
|
|
133
|
+
if (itemType !== undefined) {
|
|
134
|
+
heading.valueType = itemType;
|
|
135
|
+
// @ts-expect-error
|
|
136
|
+
delete heading.itemType;
|
|
137
|
+
}
|
|
138
|
+
if (text !== undefined) {
|
|
139
|
+
heading.label = text;
|
|
140
|
+
// @ts-expect-error
|
|
141
|
+
delete heading.text;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// @ts-expect-error
|
|
145
|
+
const subItemsItemType = heading.subItemsHeading?.itemType;
|
|
146
|
+
if (heading.subItemsHeading && subItemsItemType !== undefined) {
|
|
147
|
+
heading.subItemsHeading.valueType = subItemsItemType;
|
|
148
|
+
// @ts-expect-error
|
|
149
|
+
delete heading.subItemsHeading.itemType;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
126
153
|
}
|
|
127
154
|
}
|
|
128
155
|
|
|
@@ -57,9 +57,9 @@ describe('DetailsRenderer', () => {
|
|
|
57
57
|
const el = renderer.render({
|
|
58
58
|
type: 'table',
|
|
59
59
|
headings: [
|
|
60
|
-
{text: 'First', key: 'a',
|
|
61
|
-
{text: 'Second', key: 'b',
|
|
62
|
-
{text: 'Preview', key: 'c',
|
|
60
|
+
{text: 'First', key: 'a', valueType: 'text'},
|
|
61
|
+
{text: 'Second', key: 'b', valueType: 'text'},
|
|
62
|
+
{text: 'Preview', key: 'c', valueType: 'thumbnail'},
|
|
63
63
|
],
|
|
64
64
|
items: [
|
|
65
65
|
{
|
|
@@ -88,11 +88,11 @@ describe('DetailsRenderer', () => {
|
|
|
88
88
|
const el = renderer.render({
|
|
89
89
|
type: 'table',
|
|
90
90
|
headings: [
|
|
91
|
-
{text: '', key: 'bytes',
|
|
92
|
-
{text: '', key: 'numeric',
|
|
93
|
-
{text: '', key: 'ms',
|
|
91
|
+
{text: '', key: 'bytes', valueType: 'bytes'},
|
|
92
|
+
{text: '', key: 'numeric', valueType: 'numeric'},
|
|
93
|
+
{text: '', key: 'ms', valueType: 'ms'},
|
|
94
94
|
// Verify that 0 is ignored.
|
|
95
|
-
{text: '', key: 'ms',
|
|
95
|
+
{text: '', key: 'ms', valueType: 'ms', granularity: 0},
|
|
96
96
|
],
|
|
97
97
|
items: [
|
|
98
98
|
{
|
|
@@ -114,9 +114,9 @@ describe('DetailsRenderer', () => {
|
|
|
114
114
|
const el = renderer.render({
|
|
115
115
|
type: 'table',
|
|
116
116
|
headings: [
|
|
117
|
-
{text: '', key: 'bytes',
|
|
118
|
-
{text: '', key: 'numeric',
|
|
119
|
-
{text: '', key: 'ms',
|
|
117
|
+
{text: '', key: 'bytes', valueType: 'bytes', granularity: 0.01},
|
|
118
|
+
{text: '', key: 'numeric', valueType: 'numeric', granularity: 100},
|
|
119
|
+
{text: '', key: 'ms', valueType: 'ms', granularity: 1},
|
|
120
120
|
],
|
|
121
121
|
items: [
|
|
122
122
|
{
|
|
@@ -190,7 +190,7 @@ describe('DetailsRenderer', () => {
|
|
|
190
190
|
it('renders lists', () => {
|
|
191
191
|
const table = {
|
|
192
192
|
type: 'table',
|
|
193
|
-
headings: [{text: '', key: 'numeric',
|
|
193
|
+
headings: [{text: '', key: 'numeric', valueType: 'numeric'}],
|
|
194
194
|
items: [{numeric: 1234.567}],
|
|
195
195
|
};
|
|
196
196
|
|
|
@@ -264,7 +264,7 @@ describe('DetailsRenderer', () => {
|
|
|
264
264
|
it('renders text values', () => {
|
|
265
265
|
const details = {
|
|
266
266
|
type: 'table',
|
|
267
|
-
headings: [{key: 'content',
|
|
267
|
+
headings: [{key: 'content', valueType: 'text', label: 'Heading'}],
|
|
268
268
|
items: [{content: 'My text content'}],
|
|
269
269
|
};
|
|
270
270
|
|
|
@@ -277,7 +277,7 @@ describe('DetailsRenderer', () => {
|
|
|
277
277
|
it('renders not much if items are empty', () => {
|
|
278
278
|
const details = {
|
|
279
279
|
type: 'table',
|
|
280
|
-
headings: [{key: 'content',
|
|
280
|
+
headings: [{key: 'content', valueType: 'text', label: 'Heading'}],
|
|
281
281
|
items: [],
|
|
282
282
|
};
|
|
283
283
|
|
|
@@ -288,7 +288,7 @@ describe('DetailsRenderer', () => {
|
|
|
288
288
|
it('renders an empty cell if item is missing a property', () => {
|
|
289
289
|
const details = {
|
|
290
290
|
type: 'table',
|
|
291
|
-
headings: [{key: 'content',
|
|
291
|
+
headings: [{key: 'content', valueType: 'text', label: 'Heading'}],
|
|
292
292
|
items: [
|
|
293
293
|
{},
|
|
294
294
|
{content: undefined},
|
|
@@ -316,7 +316,7 @@ describe('DetailsRenderer', () => {
|
|
|
316
316
|
it('renders code values from a string', () => {
|
|
317
317
|
const details = {
|
|
318
318
|
type: 'table',
|
|
319
|
-
headings: [{key: 'content',
|
|
319
|
+
headings: [{key: 'content', valueType: 'code', label: 'Heading'}],
|
|
320
320
|
items: [{content: 'code snippet'}],
|
|
321
321
|
};
|
|
322
322
|
|
|
@@ -334,7 +334,7 @@ describe('DetailsRenderer', () => {
|
|
|
334
334
|
|
|
335
335
|
const details = {
|
|
336
336
|
type: 'table',
|
|
337
|
-
headings: [{key: 'content',
|
|
337
|
+
headings: [{key: 'content', valueType: 'code', label: 'Heading'}],
|
|
338
338
|
items: [{content: code}],
|
|
339
339
|
};
|
|
340
340
|
|
|
@@ -347,7 +347,7 @@ describe('DetailsRenderer', () => {
|
|
|
347
347
|
it('renders thumbnail values', () => {
|
|
348
348
|
const details = {
|
|
349
349
|
type: 'table',
|
|
350
|
-
headings: [{key: 'content',
|
|
350
|
+
headings: [{key: 'content', valueType: 'thumbnail', label: 'Heading'}],
|
|
351
351
|
items: [{content: 'http://example.com/my-image.jpg'}],
|
|
352
352
|
};
|
|
353
353
|
|
|
@@ -369,7 +369,7 @@ describe('DetailsRenderer', () => {
|
|
|
369
369
|
};
|
|
370
370
|
const details = {
|
|
371
371
|
type: 'table',
|
|
372
|
-
headings: [{key: 'content',
|
|
372
|
+
headings: [{key: 'content', valueType: 'link', label: 'Heading'}],
|
|
373
373
|
items: [{content: link}],
|
|
374
374
|
};
|
|
375
375
|
|
|
@@ -391,7 +391,7 @@ describe('DetailsRenderer', () => {
|
|
|
391
391
|
};
|
|
392
392
|
const details = {
|
|
393
393
|
type: 'table',
|
|
394
|
-
headings: [{key: 'content',
|
|
394
|
+
headings: [{key: 'content', valueType: 'link', label: 'Heading'}],
|
|
395
395
|
items: [{content: link}],
|
|
396
396
|
};
|
|
397
397
|
|
|
@@ -411,7 +411,7 @@ describe('DetailsRenderer', () => {
|
|
|
411
411
|
};
|
|
412
412
|
const details = {
|
|
413
413
|
type: 'table',
|
|
414
|
-
headings: [{key: 'content',
|
|
414
|
+
headings: [{key: 'content', valueType: 'link', label: 'Heading'}],
|
|
415
415
|
items: [{content: link}],
|
|
416
416
|
};
|
|
417
417
|
|
|
@@ -431,7 +431,7 @@ describe('DetailsRenderer', () => {
|
|
|
431
431
|
};
|
|
432
432
|
const details = {
|
|
433
433
|
type: 'table',
|
|
434
|
-
headings: [{key: 'content',
|
|
434
|
+
headings: [{key: 'content', valueType: 'node', label: 'Heading'}],
|
|
435
435
|
items: [{content: node}],
|
|
436
436
|
};
|
|
437
437
|
|
|
@@ -466,7 +466,7 @@ describe('DetailsRenderer', () => {
|
|
|
466
466
|
};
|
|
467
467
|
const details = {
|
|
468
468
|
type: 'table',
|
|
469
|
-
headings: [{key: 'content',
|
|
469
|
+
headings: [{key: 'content', valueType: 'node', label: 'Heading'}],
|
|
470
470
|
items: [{content: node}],
|
|
471
471
|
};
|
|
472
472
|
|
|
@@ -498,7 +498,7 @@ describe('DetailsRenderer', () => {
|
|
|
498
498
|
};
|
|
499
499
|
const details = {
|
|
500
500
|
type: 'table',
|
|
501
|
-
headings: [{key: 'content',
|
|
501
|
+
headings: [{key: 'content', valueType: 'node', label: 'Heading'}],
|
|
502
502
|
items: [{content: node}],
|
|
503
503
|
};
|
|
504
504
|
|
|
@@ -519,7 +519,7 @@ describe('DetailsRenderer', () => {
|
|
|
519
519
|
};
|
|
520
520
|
const details = {
|
|
521
521
|
type: 'table',
|
|
522
|
-
headings: [{key: 'content',
|
|
522
|
+
headings: [{key: 'content', valueType: 'source-location', label: 'Heading'}],
|
|
523
523
|
items: [{content: sourceLocation}],
|
|
524
524
|
};
|
|
525
525
|
|
|
@@ -549,7 +549,7 @@ describe('DetailsRenderer', () => {
|
|
|
549
549
|
};
|
|
550
550
|
const details = {
|
|
551
551
|
type: 'table',
|
|
552
|
-
headings: [{key: 'content',
|
|
552
|
+
headings: [{key: 'content', valueType: 'source-location', label: 'Heading'}],
|
|
553
553
|
items: [{content: sourceLocation}],
|
|
554
554
|
};
|
|
555
555
|
|
|
@@ -575,7 +575,7 @@ describe('DetailsRenderer', () => {
|
|
|
575
575
|
};
|
|
576
576
|
const details = {
|
|
577
577
|
type: 'table',
|
|
578
|
-
headings: [{key: 'content',
|
|
578
|
+
headings: [{key: 'content', valueType: 'source-location', label: 'Heading'}],
|
|
579
579
|
items: [{content: sourceLocation}],
|
|
580
580
|
};
|
|
581
581
|
|
|
@@ -600,7 +600,7 @@ describe('DetailsRenderer', () => {
|
|
|
600
600
|
};
|
|
601
601
|
const details = {
|
|
602
602
|
type: 'table',
|
|
603
|
-
headings: [{key: 'content',
|
|
603
|
+
headings: [{key: 'content', valueType: 'source-location', label: 'Heading'}],
|
|
604
604
|
items: [{content: sourceLocation}],
|
|
605
605
|
};
|
|
606
606
|
|
|
@@ -625,7 +625,7 @@ describe('DetailsRenderer', () => {
|
|
|
625
625
|
};
|
|
626
626
|
const details = {
|
|
627
627
|
type: 'table',
|
|
628
|
-
headings: [{key: 'content',
|
|
628
|
+
headings: [{key: 'content', valueType: 'source-location', label: 'Heading'}],
|
|
629
629
|
items: [{content: sourceLocation}],
|
|
630
630
|
};
|
|
631
631
|
|
|
@@ -646,7 +646,7 @@ describe('DetailsRenderer', () => {
|
|
|
646
646
|
|
|
647
647
|
const details = {
|
|
648
648
|
type: 'table',
|
|
649
|
-
headings: [{key: 'content',
|
|
649
|
+
headings: [{key: 'content', valueType: 'url', label: 'Heading'}],
|
|
650
650
|
items: [{content: urlText}],
|
|
651
651
|
};
|
|
652
652
|
|
|
@@ -673,7 +673,7 @@ describe('DetailsRenderer', () => {
|
|
|
673
673
|
|
|
674
674
|
const details = {
|
|
675
675
|
type: 'table',
|
|
676
|
-
headings: [{key: 'content',
|
|
676
|
+
headings: [{key: 'content', valueType: 'url', label: 'Heading'}],
|
|
677
677
|
items: [{content: url}],
|
|
678
678
|
overallSavingsMs: 100,
|
|
679
679
|
};
|
|
@@ -693,7 +693,7 @@ describe('DetailsRenderer', () => {
|
|
|
693
693
|
|
|
694
694
|
const details = {
|
|
695
695
|
type: 'table',
|
|
696
|
-
headings: [{key: 'content',
|
|
696
|
+
headings: [{key: 'content', valueType: 'url', label: 'Heading'}],
|
|
697
697
|
items: [{content: urlText}],
|
|
698
698
|
};
|
|
699
699
|
|
|
@@ -712,11 +712,11 @@ describe('DetailsRenderer', () => {
|
|
|
712
712
|
console.error = consoleError;
|
|
713
713
|
});
|
|
714
714
|
|
|
715
|
-
it('renders an unknown heading
|
|
715
|
+
it('renders an unknown heading valueType', () => {
|
|
716
716
|
// Disallowed by type system, but test that we get an error message out just in case.
|
|
717
717
|
const details = {
|
|
718
718
|
type: 'table',
|
|
719
|
-
headings: [{key: 'content',
|
|
719
|
+
headings: [{key: 'content', valueType: 'notRealValueType', label: 'Heading'}],
|
|
720
720
|
items: [{content: 'some string'}],
|
|
721
721
|
};
|
|
722
722
|
|
|
@@ -737,7 +737,7 @@ describe('DetailsRenderer', () => {
|
|
|
737
737
|
|
|
738
738
|
const details = {
|
|
739
739
|
type: 'table',
|
|
740
|
-
headings: [{key: 'content',
|
|
740
|
+
headings: [{key: 'content', valueType: 'url', label: 'Heading'}],
|
|
741
741
|
items: [{content: item}],
|
|
742
742
|
};
|
|
743
743
|
|
|
@@ -753,8 +753,8 @@ describe('DetailsRenderer', () => {
|
|
|
753
753
|
it('uses the item\'s type over the heading type', () => {
|
|
754
754
|
const details = {
|
|
755
755
|
type: 'table',
|
|
756
|
-
//
|
|
757
|
-
headings: [{key: 'content',
|
|
756
|
+
// valueType is overriden by code object
|
|
757
|
+
headings: [{key: 'content', valueType: 'url', label: 'Heading'}],
|
|
758
758
|
items: [
|
|
759
759
|
{content: {type: 'code', value: 'https://codeobject.com'}},
|
|
760
760
|
{content: 'https://example.com'},
|
|
@@ -790,7 +790,7 @@ describe('DetailsRenderer', () => {
|
|
|
790
790
|
const details = {
|
|
791
791
|
type: 'table',
|
|
792
792
|
headings: [
|
|
793
|
-
{key: 'url',
|
|
793
|
+
{key: 'url', valueType: 'url', subItemsHeading: {key: 'source', valueType: 'code'}},
|
|
794
794
|
],
|
|
795
795
|
items: [
|
|
796
796
|
{
|
|
@@ -832,7 +832,7 @@ describe('DetailsRenderer', () => {
|
|
|
832
832
|
it('renders, uses heading properties as fallback', () => {
|
|
833
833
|
const details = {
|
|
834
834
|
type: 'table',
|
|
835
|
-
headings: [{key: 'url',
|
|
835
|
+
headings: [{key: 'url', valueType: 'url', subItemsHeading: {key: 'source'}}],
|
|
836
836
|
items: [
|
|
837
837
|
{
|
|
838
838
|
url: 'https://www.example.com',
|
|
@@ -176,6 +176,31 @@ describe('util helpers', () => {
|
|
|
176
176
|
assert.deepStrictEqual(clonedPreparedResult.categories, preparedResult.categories);
|
|
177
177
|
assert.deepStrictEqual(clonedPreparedResult.categoryGroups, preparedResult.categoryGroups);
|
|
178
178
|
});
|
|
179
|
+
|
|
180
|
+
it('converts old opportunity table column headings to consolidated table headings', () => {
|
|
181
|
+
const clonedSampleResult = JSON.parse(JSON.stringify(sampleResult));
|
|
182
|
+
|
|
183
|
+
const auditsWithTableDetails = Object.values(clonedSampleResult.audits)
|
|
184
|
+
.filter(audit => audit.details?.type === 'table');
|
|
185
|
+
assert.notEqual(auditsWithTableDetails.length, 0);
|
|
186
|
+
for (const audit of auditsWithTableDetails) {
|
|
187
|
+
for (const heading of audit.details.headings) {
|
|
188
|
+
heading.itemType = heading.valueType;
|
|
189
|
+
heading.text = heading.label;
|
|
190
|
+
delete heading.valueType;
|
|
191
|
+
delete heading.label;
|
|
192
|
+
|
|
193
|
+
if (heading.subItemsHeading) {
|
|
194
|
+
heading.subItemsHeading.itemType = heading.subItemsHeading.valueType;
|
|
195
|
+
// @ts-expect-error
|
|
196
|
+
delete heading.subItemsHeading.valueType;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const preparedResult = Util.prepareReportResult(clonedSampleResult);
|
|
202
|
+
assert.deepStrictEqual(sampleResult.audits, preparedResult.audits);
|
|
203
|
+
});
|
|
179
204
|
});
|
|
180
205
|
|
|
181
206
|
it('appends stack pack descriptions to auditRefs', () => {
|