Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

audit: add apple-touch-icon audit #8857

Merged
merged 15 commits into from
May 7, 2019
8 changes: 8 additions & 0 deletions lighthouse-cli/test/cli/__snapshots__/index-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ Object {
Object {
"path": "installable-manifest",
},
Object {
"path": "apple-touch-icon",
},
Object {
"path": "splash-screen",
},
Expand Down Expand Up @@ -923,6 +926,11 @@ Object {
"id": "without-javascript",
"weight": 1,
},
Object {
"group": "pwa-optimized",
"id": "apple-touch-icon",
"weight": 1,
},
Object {
"id": "pwa-cross-browser",
"weight": 0,
Expand Down
6 changes: 6 additions & 0 deletions lighthouse-cli/test/smokehouse/pwa-expectations.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ module.exports = [
'content-width': {
score: 1,
},
'apple-touch-icon': {
score: 1,
},

// "manual" audits. Just verify in the results.
'pwa-cross-browser': {
Expand Down Expand Up @@ -128,6 +131,9 @@ module.exports = [
'content-width': {
score: 1,
},
'apple-touch-icon': {
score: 1,
},
exterkamp marked this conversation as resolved.
Show resolved Hide resolved

// "manual" audits. Just verify in the results.
'pwa-cross-browser': {
Expand Down
9 changes: 9 additions & 0 deletions lighthouse-cli/test/smokehouse/pwa2-expectations.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ module.exports = [
'content-width': {
score: 1,
},
'apple-touch-icon': {
score: 1,
warnings: [
/apple-touch-icon-precomposed/,
],
},
exterkamp marked this conversation as resolved.
Show resolved Hide resolved

// "manual" audits. Just verify in the results.
'pwa-cross-browser': {
Expand Down Expand Up @@ -123,6 +129,9 @@ module.exports = [
'content-width': {
score: 1,
},
'apple-touch-icon': {
score: 0,
},

// "manual" audits. Just verify in the results.
'pwa-cross-browser': {
Expand Down
3 changes: 3 additions & 0 deletions lighthouse-cli/test/smokehouse/pwa3-expectations.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ module.exports = [
'content-width': {
score: 1,
},
'apple-touch-icon': {
score: 1,
},

// "manual" audits. Just verify in the results.
'pwa-cross-browser': {
Expand Down
71 changes: 71 additions & 0 deletions lighthouse-core/audits/apple-touch-icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* @license Copyright 2019 Google Inc. 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.
*/
'use strict';

const Audit = require('./audit.js');
const i18n = require('../lib/i18n/i18n.js');

/**
* @fileoverview Audits if a page has an `apple-touch-icon` link element with a valid href.
*/

const UIStrings = {
/** Title of a Lighthouse audit that tells the user that their site contains a vaild touch icon. This descriptive title is shown when the page contains a valid iOS touch icon. "apple-touch-icon" is an HTML attribute value and should not be translated. */
title: 'Provides a valid `apple-touch-icon`',
/** Title of a Lighthouse audit that tells the user that their site contains a vaild touch icon. This descriptive title is shown when the page does not contain a valid iOS touch icon. "apple-touch-icon" is an HTML attribute value and should not be translated. */
failureTitle: 'Does not provide a valid `apple-touch-icon`',
/** Description of a Lighthouse audit that tells the user what having a valid apple-touch-icon does. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. "apple-touch-icon" is an HTML attribute value and should not be translated. */
description: 'For ideal appearance on iOS when users add to the home screen, define an ' +
'apple-touch-icon. It must point to a non-transparent 192px (or 180px) square PNG. ' +
'[Learn More](https://developers.google.com/web/fundamentals/design-and-ux/browser-customization/).',
/** Warning that HTML attribute `apple-touch-icon-precomposed` should not be used in favor of `apple-touch-icon`. "apple-touch-icon-precomposed" and "apple-touch-icon" are HTML attribute values and should not be translated. */
precomposedWarning: '`apple-touch-icon-precomposed` is out of date; ' +
'`apple-touch-icon` is preferred.',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

class AppleTouchIcon extends Audit {
/**
* @return {LH.Audit.Meta}
*/
static get meta() {
return {
id: 'apple-touch-icon',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['LinkElements'],
};
}

/**
* @param {LH.Artifacts} artifacts
* @return {LH.Audit.Product}
*/
static audit(artifacts) {
const appleTouchIcons = artifacts.LinkElements
.filter(el => el.rel === 'apple-touch-icon' || el.rel === 'apple-touch-icon-precomposed')
.filter(el => !!el.href);

// Audit passes if an `apple-touch-icon` exists.
const passed = appleTouchIcons.length !== 0;

const warnings = [];
if (appleTouchIcons.filter(el => el.rel === 'apple-touch-icon-precomposed').length !== 0
&& appleTouchIcons.filter(el => el.rel === 'apple-touch-icon').length === 0) {
warnings.push(str_(UIStrings.precomposedWarning));
}

return {
score: passed ? 1 : 0,
warnings,
};
}
}

module.exports = AppleTouchIcon;
module.exports.UIStrings = UIStrings;
2 changes: 2 additions & 0 deletions lighthouse-core/config/default-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ const defaultConfig = {
'critical-request-chains',
'redirects',
'installable-manifest',
'apple-touch-icon',
'splash-screen',
'themed-omnibox',
'content-width',
Expand Down Expand Up @@ -523,6 +524,7 @@ const defaultConfig = {
{id: 'content-width', weight: 1, group: 'pwa-optimized'},
{id: 'viewport', weight: 2, group: 'pwa-optimized'},
{id: 'without-javascript', weight: 1, group: 'pwa-optimized'},
{id: 'apple-touch-icon', weight: 1, group: 'pwa-optimized'},
// Manual audits
{id: 'pwa-cross-browser', weight: 0},
{id: 'pwa-page-transitions', weight: 0},
Expand Down
16 changes: 16 additions & 0 deletions lighthouse-core/lib/i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,22 @@
"message": "`<video>` elements contain a `<track>` element with `[kind=\"description\"]`",
"description": "Title of an accesibility audit that evaluates if all video elements have child track elements that contain a description of the video content. This title is descriptive of the successful state and is shown to users when no user action is required."
},
"lighthouse-core/audits/apple-touch-icon.js | description": {
"message": "For ideal appearance on iOS when users add to the home screen, define an apple-touch-icon. It must point to a non-transparent 192px (or 180px) square PNG. [Learn More](https://developers.google.com/web/fundamentals/design-and-ux/browser-customization/).",
"description": "Description of a Lighthouse audit that tells the user what having a valid apple-touch-icon does. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. \"apple-touch-icon\" is an HTML attribute value and should not be translated."
},
"lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
"message": "Does not provide a valid `apple-touch-icon`",
"description": "Title of a Lighthouse audit that tells the user that their site contains a vaild touch icon. This descriptive title is shown when the page does not contain a valid iOS touch icon. \"apple-touch-icon\" is an HTML attribute value and should not be translated."
},
"lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
"message": "`apple-touch-icon-precomposed` is out of date; `apple-touch-icon` is preferred.",
"description": "Warning that HTML attribute `apple-touch-icon-precomposed` should not be used in favor of `apple-touch-icon`. \"apple-touch-icon-precomposed\" and \"apple-touch-icon\" are HTML attribute values and should not be translated."
},
"lighthouse-core/audits/apple-touch-icon.js | title": {
"message": "Provides a valid `apple-touch-icon`",
"description": "Title of a Lighthouse audit that tells the user that their site contains a vaild touch icon. This descriptive title is shown when the page contains a valid iOS touch icon. \"apple-touch-icon\" is an HTML attribute value and should not be translated."
},
"lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
"message": "Chrome extensions negatively affected this page's load performance. Try auditing the page in incognito mode or from a Chrome profile without extensions.",
"description": "A message displayed in a Lighthouse audit result warning that Chrome extensions on the user's system substantially affected Lighthouse's measurements and instructs the user on how to run again without those extensions."
Expand Down
98 changes: 98 additions & 0 deletions lighthouse-core/test/audits/apple-touch-icon-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* @license Copyright 2019 Google Inc. 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.
*/
'use strict';

const AppleTouchIcon = require('../../audits/apple-touch-icon.js');

/* eslint-env jest */

describe('PWA: apple-touch-icon audit', () => {
it(`fails when apple-touch-icon is not present`, () => {
const artifacts = {
LinkElements: [
{rel: 'iOS-touch-thing', href: 'https://example.com/else.png'},
{rel: 'something else', href: 'https://example.com/else.png'},
],
};

const {score} = AppleTouchIcon.audit(artifacts);

expect(score).toBe(0);
});

it(`fails when apple-touch-icon does not have an href`, () => {
const artifacts = {
LinkElements: [{rel: 'apple-touch-icon'}],
};

const {score} = AppleTouchIcon.audit(artifacts);

expect(score).toBe(0);
});

it(`passes but warns when apple-touch-icon-precomposed only`, () => {
const artifacts = {
LinkElements: [{rel: 'apple-touch-icon-precomposed', href: 'https://example.com/touch-icon.png'}],
};

const {score, warnings} = AppleTouchIcon.audit(artifacts);

expect(score).toBe(1);
expect(warnings[0]).toBeDisplayString('`apple-touch-icon-precomposed` is ' +
'out of date; `apple-touch-icon` is preferred.');
});

it(`passes with no warning when precomposed with normal`, () => {
const artifacts = {
LinkElements: [
{rel: 'apple-touch-icon', href: 'https://example.com/touch-icon.png'},
{rel: 'apple-touch-icon-precomposed', href: 'https://example.com/touch-icon.png'},
],
};

const {score, warnings} = AppleTouchIcon.audit(artifacts);

expect(score).toBe(1);
expect(warnings).toEqual([]);
});

it(`passes when apple-touch-icon is on page`, () => {
const artifacts = {
LinkElements: [{rel: 'apple-touch-icon', href: 'https://example.com/touch-icon.png'}],
};

const {score} = AppleTouchIcon.audit(artifacts);

expect(score).toBe(1);
});

exterkamp marked this conversation as resolved.
Show resolved Hide resolved
it(`passes with multiple apple-touch-icons on page`, () => {
const artifacts = {
LinkElements: [
{rel: 'apple-touch-icon', sizes: '152x152', href: 'https://example.com/touch-icon.png'},
{rel: 'apple-touch-icon', sizes: '180x180', href: 'https://example.com/touch-icon.png'},
],
};

const {score} = AppleTouchIcon.audit(artifacts);

expect(score).toBe(1);
});

it(`passes when lots of LinkElements`, () => {
const artifacts = {
LinkElements: [
{rel: 'iOS-touch-thing', href: 'https://example.com/else.png'},
{rel: 'apple-touch-icon', href: 'https://example.com/touch-icon.png'},
{rel: 'something else', href: 'https://example.com/else.png'},
],
};

const {score} = AppleTouchIcon.audit(artifacts);

expect(score).toBe(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ describe('CategoryRenderer', () => {
const manualAudits = elem.querySelectorAll('.lh-clump--manual .lh-audit');

assert.equal(passedAudits.length, 2);
assert.equal(failedAudits.length, 8);
assert.equal(failedAudits.length, 9);
assert.equal(warningAudits.length, 2);
assert.equal(manualAudits.length, 3);
});
Expand All @@ -380,7 +380,7 @@ describe('CategoryRenderer', () => {
const failedAudits = elem.querySelectorAll('.lh-clump--failed .lh-audit');

assert.equal(passedAudits.length, 0);
assert.equal(failedAudits.length, 12);
assert.equal(failedAudits.length, 13);
});

it('expands warning audit group', () => {
Expand Down
27 changes: 26 additions & 1 deletion lighthouse-core/test/results/sample_v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,14 @@
]
}
},
"apple-touch-icon": {
"id": "apple-touch-icon",
"title": "Does not provide a valid `apple-touch-icon`",
"description": "For ideal appearance on iOS when users add to the home screen, define an apple-touch-icon. It must point to a non-transparent 192px (or 180px) square PNG. [Learn More](https://developers.google.com/web/fundamentals/design-and-ux/browser-customization/).",
"score": 0,
"scoreDisplayMode": "binary",
"warnings": []
},
"splash-screen": {
"id": "splash-screen",
"title": "Is not configured for a custom splash screen",
Expand Down Expand Up @@ -3690,6 +3698,11 @@
"weight": 1,
"group": "pwa-optimized"
},
{
"id": "apple-touch-icon",
"weight": 1,
"group": "pwa-optimized"
},
{
"id": "pwa-cross-browser",
"weight": 0
Expand All @@ -3704,7 +3717,7 @@
}
],
"id": "pwa",
"score": 0.42
"score": 0.41
}
},
"categoryGroups": {
Expand Down Expand Up @@ -4073,6 +4086,12 @@
"duration": 100,
"entryType": "measure"
},
{
"startTime": 0,
"name": "lh:audit:apple-touch-icon",
"duration": 100,
"entryType": "measure"
},
{
"startTime": 0,
"name": "lh:audit:splash-screen",
Expand Down Expand Up @@ -4911,6 +4930,12 @@
"lighthouse-core/audits/redirects.js | description": [
"audits.redirects.description"
],
"lighthouse-core/audits/apple-touch-icon.js | failureTitle": [
"audits[apple-touch-icon].title"
],
"lighthouse-core/audits/apple-touch-icon.js | description": [
"audits[apple-touch-icon].description"
],
"lighthouse-core/audits/mainthread-work-breakdown.js | title": [
"audits[mainthread-work-breakdown].title"
],
Expand Down
Loading