Skip to content

Commit

Permalink
Adding audit for theme-color in HTML and moving to jsdom for testing …
Browse files Browse the repository at this point in the history
…html elements
  • Loading branch information
Matt Gaunt committed Mar 24, 2016
1 parent eb9f9ea commit ff8affc
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 10 deletions.
47 changes: 47 additions & 0 deletions audits/html/theme-color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright 2016 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';

class ThemeColor {

static get tags() {
return ['HTML'];
}

static get description() {
return 'Site has a theme-color meta tag';
}

static audit(inputs) {
let hasThemeColor = false;
if (inputs.window) {
const themeColorElements =
inputs.window.document.querySelectorAll('head meta[name="theme-color"]');

if (themeColorElements.length === 1 && themeColorElements[0].content.length > 0) {
hasThemeColor = true;
}
}

return {
value: hasThemeColor,
tags: ThemeColor.tags,
description: ThemeColor.description
};
}
}

module.exports = ThemeColor;
15 changes: 11 additions & 4 deletions audits/mobile-friendly/viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,19 @@ class Viewport {
}

static audit(inputs) {
// TODO: This'll be a false positive if the body content has this string.
// Unless we want to parse the original HTML, we should query for `head > .meta[name=viewport]`
const viewportExpression = /<meta ([^c]+)content="width=/gim;
let hasViewport = false;
if (inputs.window) {
const viewportElements =
inputs.window.document.querySelectorAll('head meta[name="viewport"]');

if (viewportElements.length === 1 &&
viewportElements[0].content.indexOf('width=') !== -1) {
hasViewport = true;
}
}

return {
value: viewportExpression.test(inputs.html),
value: hasViewport,
tags: Viewport.tags,
description: Viewport.description
};
Expand Down
6 changes: 3 additions & 3 deletions extension/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"argsIgnorePattern": "(^reject$|^_$)"
}],
"quotes": [2, "single"],
"require-jsdoc": "off",
"valid-jsdoc": "off",
"comma-dangle": "off",
"require-jsdoc": 0,
"valid-jsdoc": 0,
"comma-dangle": 0
}
}
4 changes: 3 additions & 1 deletion extension/gulpfile.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ gulp.task('babel', () => {
.pipe($.babel({
presets: ['es2015']
}))
.pipe(browserify())
.pipe(browserify({
ignore: 'jsdom' // Ignore jsdom since it's only needed for node env
}))
.pipe(gulp.dest('app/scripts'))
.pipe(gulp.dest('dist/scripts'));
});
Expand Down
18 changes: 17 additions & 1 deletion gatherers/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
'use strict';

/* global window */

const Gather = require('./gather');

class HTML extends Gather {
Expand All @@ -27,7 +29,21 @@ class HTML extends Gather {
.then(nodeId => driver.sendCommand('DOM.getOuterHTML', {
nodeId: nodeId
}))
.then(nodeHTML => ({html: nodeHTML.outerHTML}));
.then(nodeHTML => {
if (typeof window !== 'undefined') {
return {
window: window,
html: nodeHTML
};
}

const jsdom = require('jsdom').jsdom;
const doc = jsdom(nodeHTML);
return {
window: doc.defaultView,
html: nodeHTML
};
});
}
}

Expand Down
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const audits = [
require('./audits/manifest/icons-192'),
require('./audits/manifest/name'),
require('./audits/manifest/short-name'),
require('./audits/manifest/start-url')
require('./audits/manifest/start-url'),
require('./audits/html/theme-color')
];

module.exports = function(opts) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"chrome-devtools-frontend": "1.0.381789",
"chrome-remote-interface": "^0.11.0",
"devtools-timeline-model": "1.0.16",
"jsdom": "^8.1.0",
"meow": "^3.7.0",
"npmlog": "^2.0.3",
"traceviewer": "^1.0.8"
Expand Down
88 changes: 88 additions & 0 deletions test/audits/html/theme-colors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Copyright 2016 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.
*/
const Audit = require('../../../audits/html/theme-color.js');
const assert = require('assert');

/* global describe, it*/

describe('HTML: theme-color audit', () => {
const getMockHtml = (headInsert, bodyInsert) => {
headInsert = headInsert || '';
bodyInsert = bodyInsert || '';

const htmlString = `<!doctype html>
<html>
<head>
${headInsert}
<title>Sample page</title>
</head>
<body>
${bodyInsert}
</body>
</html>`;

const jsdom = require('jsdom').jsdom;
const doc = jsdom(htmlString);

return {
window: doc.defaultView,
html: htmlString
};
};

it('fails when no window or html present', () => {
return assert.equal(Audit.audit({}).value, false);
});

it('fails when no theme-color is present in the html', () => {
return assert.equal(Audit.audit(getMockHtml()).value, false);
});

it('fails when theme-color has no content value', () => {
return assert.equal(Audit.audit(
getMockHtml('<meta name="theme-color" content="">')).value, false);
});

it('fails when multiple theme-colors exist', () => {
return assert.equal(Audit.audit(
getMockHtml(`<meta name="theme-color" content="#ffffff">
<meta name="theme-color" content="#ffffff">`)).value, false);
});

it('fails when theme-color exists in the body', () => {
return assert.equal(Audit.audit(
getMockHtml('', '<meta name="theme-color" content="#ffffff">')
).value, false);
});

it('succeeds when theme-color present in the html', () => {
return assert.equal(Audit.audit(
getMockHtml('<meta name="theme-color" content="#ffffff">')
).value, true);
});

it('succeeds when theme-color present in the html with id', () => {
return assert.equal(Audit.audit(
getMockHtml('<meta id="my-theme-color" name="theme-color" content="#ffffff">')
).value, true);
});

it('succeeds when theme-color has a CSS name content value', () => {
return assert.equal(Audit.audit(
getMockHtml('<meta id="my-theme-color" name="theme-color" content="red">')
).value, true);
});
});

0 comments on commit ff8affc

Please sign in to comment.