diff --git a/core/audits/origin-isolation.js b/core/audits/origin-isolation.js index 52db9155246d..bcabacd218bd 100644 --- a/core/audits/origin-isolation.js +++ b/core/audits/origin-isolation.js @@ -10,7 +10,7 @@ import * as i18n from '../lib/i18n/i18n.js'; import {Audit} from './audit.js'; const UIStrings = { - /** Title of a Lighthouse audit that evaluates the security of a page's COOP header for origin isolation. "COOP" stands for "Cross-Origin-Opener-Policy". */ + /** Title of a Lighthouse audit that evaluates the security of a page's COOP header for origin isolation. "COOP" stands for "Cross-Origin-Opener-Policy". */ title: 'Ensure the proper usage of the COOP header to isolate the origin.', /** Description of a Lighthouse audit that evaluates the security of a page's COOP header for origin isolation. This is displayed after a user expands the section to see more. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. "COOP" stands for "Cross-Origin-Opener-Policy". */ description: 'Deployment of the COOP header allows isolation of the top-level document to not share a browsing context group with cross-origin documents. ' + @@ -45,14 +45,14 @@ class OriginIsolation extends Audit { /** * @param {LH.Artifacts} artifacts * @param {LH.Audit.Context} context - * @return {Promise<{coopHeaders: string[]}>} + * @return {Promise} */ static async getRawCoop(artifacts, context) { const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; const mainResource = await MainResource.request({devtoolsLog, URL: artifacts.URL}, context); - var coopHeaders = + let coopHeaders = mainResource.responseHeaders .filter(h => { return h.name.toLowerCase() === 'cross-origin-opener-policy'; @@ -62,7 +62,7 @@ class OriginIsolation extends Audit { // Sanitize the header value. coopHeaders = coopHeaders.map(v => v.toLowerCase().replace(/\s/g, '')); - return {coopHeaders}; + return coopHeaders; } /** @@ -95,7 +95,7 @@ class OriginIsolation extends Audit { severity: str_(i18n.UIStrings.itemSeverityHigh), description: str_(UIStrings.noCoop), directive: undefined, - }) + }); } for (const actualDirective of coopHeaders) { @@ -104,8 +104,8 @@ class OriginIsolation extends Audit { syntax.push({ severity: str_(i18n.UIStrings.itemSeverityLow), description: str_(UIStrings.invalidSyntax), - directive: actualDirective - }) + directive: actualDirective, + }); } } @@ -120,7 +120,7 @@ class OriginIsolation extends Audit { str_(i18n.UIStrings.itemSeverityLow))), ]; - return {score: violations.length ? 0 : 1, results}; + return {score: violations.length || syntax.length > 1 ? 0 : 1, results}; } /** @@ -129,15 +129,15 @@ class OriginIsolation extends Audit { * @return {Promise} */ static async audit(artifacts, context) { - const {coopHeaders} = await this.getRawCoop(artifacts, context); + const coopHeaders = await this.getRawCoop(artifacts, context); const {score, results} = this.constructResults(coopHeaders); /** @type {LH.Audit.Details.Table['headings']} */ const headings = [ /* eslint-disable max-len */ - { key: 'description', valueType: 'text', subItemsHeading: {key: 'description'}, label: str_(i18n.UIStrings.columnDescription)}, - { key: 'directive', valueType: 'code', subItemsHeading: {key: 'directive'}, label: str_(UIStrings.columnDirective)}, - { key: 'severity', valueType: 'text', subItemsHeading: {key: 'severity'}, label: str_(UIStrings.columnSeverity)}, + {key: 'description', valueType: 'text', subItemsHeading: {key: 'description'}, label: str_(i18n.UIStrings.columnDescription)}, + {key: 'directive', valueType: 'code', subItemsHeading: {key: 'directive'}, label: str_(UIStrings.columnDirective)}, + {key: 'severity', valueType: 'text', subItemsHeading: {key: 'severity'}, label: str_(UIStrings.columnSeverity)}, /* eslint-enable max-len */ ]; const details = Audit.makeTableDetails(headings, results); diff --git a/core/config/default-config.js b/core/config/default-config.js index abba05f618b6..f614c3631426 100644 --- a/core/config/default-config.js +++ b/core/config/default-config.js @@ -544,7 +544,7 @@ const defaultConfig = { {id: 'notification-on-start', weight: 1, group: 'best-practices-trust-safety'}, {id: 'csp-xss', weight: 0, group: 'best-practices-trust-safety'}, {id: 'has-hsts', weight: 0, group: 'best-practices-trust-safety'}, - {id: 'origin-isolation', weight: 0, group: 'best-practices-trust-safety'}, + {id: 'origin-isolation', weight: 0}, // User Experience {id: 'paste-preventing-inputs', weight: 3, group: 'best-practices-ux'}, {id: 'image-aspect-ratio', weight: 1, group: 'best-practices-ux'}, diff --git a/core/test/audits/origin-isolation-test.js b/core/test/audits/origin-isolation-test.js index 39a8061352ea..0103046388e5 100644 --- a/core/test/audits/origin-isolation-test.js +++ b/core/test/audits/origin-isolation-test.js @@ -25,7 +25,8 @@ it('marked N/A if no violations found', async () => { ]), }, }; - const results = await OriginIsolation.audit(artifacts, {computedCache: new Map()}); + const results = + await OriginIsolation.audit(artifacts, {computedCache: new Map()}); expect(results.details.items).toHaveLength(0); expect(results.notApplicable).toBeTruthy(); }); @@ -49,20 +50,14 @@ it('No COOP header found', async () => { }, }; - const results = await OriginIsolation.audit(artifacts, {computedCache: new Map()}); + const results = + await OriginIsolation.audit(artifacts, {computedCache: new Map()}); expect(results.notApplicable).toBeFalsy(); + expect(results.details.items[0].severity).toBeDisplayString('High'); + expect(results.details.items[0].description) + .toBeDisplayString('No COOP header found'); expect(results.details.items).toMatchObject([ { - severity: { - i18nId: "core/lib/i18n/i18n.js | itemSeverityHigh", - values: undefined, - formattedDefault: 'High' - }, - description: { - i18nId: "core/audits/origin-isolation.js | noCoop", - values: undefined, - formattedDefault: 'No COOP header found' - }, directive: undefined, }, ]); @@ -87,21 +82,15 @@ it('Messed up directive.', async () => { }, }; - const results = await OriginIsolation.audit(artifacts, {computedCache: new Map()}); + const results = + await OriginIsolation.audit(artifacts, {computedCache: new Map()}); expect(results.notApplicable).toBeFalsy(); + expect(results.details.items[0].severity).toBeDisplayString('Low'); + expect(results.details.items[0].description) + .toBeDisplayString('Invalid syntax'); expect(results.details.items).toMatchObject([ { - severity: { - i18nId: "core/lib/i18n/i18n.js | itemSeverityLow", - values: undefined, - formattedDefault: 'Low' - }, - description: { - i18nId: "core/audits/origin-isolation.js | invalidSyntax", - values: undefined, - formattedDefault: 'Invalid syntax' - }, - directive: "foodirective", + directive: 'foodirective', }, ]); }); @@ -128,7 +117,7 @@ describe('getRawCoop', () => { ]), }, }; - const {coopHeaders} = + const coopHeaders = await OriginIsolation.getRawCoop(artifacts, {computedCache: new Map()}); expect(coopHeaders).toEqual([ `same-origin`, @@ -156,7 +145,7 @@ describe('getRawCoop', () => { ]), }, }; - const {coopHeaders} = + const coopHeaders = await OriginIsolation.getRawCoop(artifacts, {computedCache: new Map()}); expect(coopHeaders).toEqual([ ``, @@ -184,7 +173,7 @@ describe('getRawCoop', () => { ]), }, }; - const {coopHeaders} = + const coopHeaders = await OriginIsolation.getRawCoop(artifacts, {computedCache: new Map()}); expect(coopHeaders).toEqual([ ``, @@ -194,27 +183,21 @@ describe('getRawCoop', () => { describe('constructResults', () => { it('passes with no findings', () => { - const {score, results} = OriginIsolation.constructResults([ 'same-origin' ]); + const {score, results} = OriginIsolation.constructResults(['same-origin']); expect(score).toEqual(1); expect(results).toEqual([]); }); it('constructs result based on misconfigured COOP header', () => { - const {score, results} = OriginIsolation.constructResults([ 'foo-directive' ]); + const {score, results} = + OriginIsolation.constructResults(['foo-directive']); expect(score).toEqual(1); + expect(results[0].severity).toBeDisplayString('Low'); + expect(results[0].description) + .toBeDisplayString('Invalid syntax'); expect(results).toMatchObject([ { - description: { - formattedDefault: 'Invalid syntax', - i18nId: 'core/audits/origin-isolation.js | invalidSyntax', - values: undefined, - }, directive: 'foo-directive', - severity: { - formattedDefault: 'Low', - i18nId: 'core/lib/i18n/i18n.js | itemSeverityLow', - values: undefined, - }, }, ]); }); @@ -222,20 +205,12 @@ describe('constructResults', () => { it('returns single item for no COOP', () => { const {score, results} = OriginIsolation.constructResults([]); expect(score).toEqual(0); + expect(results[0].severity).toBeDisplayString('High'); + expect(results[0].description) + .toBeDisplayString('No COOP header found'); expect(results).toMatchObject([ { - description: { - formattedDefault: 'No COOP header found', - i18nId: 'core/audits/origin-isolation.js | noCoop', - values: undefined, - }, directive: undefined, - severity: { - formattedDefault: 'High', - i18nId: 'core/lib/i18n/i18n.js | itemSeverityHigh', - values: undefined, - }, - }, ]); });