From 24354a4879849c8cb4e50cfcae83d78f65938a93 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Wed, 3 Jan 2018 18:21:40 -0800 Subject: [PATCH] feat: implement CSS Coverage (#1714) This patch adds two new methods to the `page.coverage` namespace: - `page.coverage.startCSSCoverage()` - to initiate css coverage - `page.coverage.stopCSSCoverage()` - to stop css coverage The coverage format is consistent with the JavaScript coverage. --- docs/api.md | 63 ++++++++--- lib/Coverage.js | 125 +++++++++++++++++++++- test/assets/csscoverage/Dosis-Regular.ttf | Bin 0 -> 136940 bytes test/assets/csscoverage/OFL.txt | 95 ++++++++++++++++ test/assets/csscoverage/involved.html | 26 +++++ test/assets/csscoverage/media.html | 4 + test/assets/csscoverage/multiple.html | 8 ++ test/assets/csscoverage/simple.html | 6 ++ test/assets/csscoverage/sourceurl.html | 7 ++ test/assets/csscoverage/stylesheet1.css | 3 + test/assets/csscoverage/stylesheet2.css | 4 + test/assets/csscoverage/unused.html | 7 ++ test/golden/csscoverage-involved.txt | 16 +++ test/test.js | 79 ++++++++++++++ utils/doclint/check_public_api/index.js | 1 + 15 files changed, 427 insertions(+), 17 deletions(-) create mode 100644 test/assets/csscoverage/Dosis-Regular.ttf create mode 100644 test/assets/csscoverage/OFL.txt create mode 100644 test/assets/csscoverage/involved.html create mode 100644 test/assets/csscoverage/media.html create mode 100644 test/assets/csscoverage/multiple.html create mode 100644 test/assets/csscoverage/simple.html create mode 100644 test/assets/csscoverage/sourceurl.html create mode 100644 test/assets/csscoverage/stylesheet1.css create mode 100644 test/assets/csscoverage/stylesheet2.css create mode 100644 test/assets/csscoverage/unused.html create mode 100644 test/golden/csscoverage-involved.txt diff --git a/docs/api.md b/docs/api.md index 6e4c0240..167b2d9d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -199,7 +199,9 @@ * [target.type()](#targettype) * [target.url()](#targeturl) - [class: Coverage](#class-coverage) + * [coverage.startCSSCoverage(options)](#coveragestartcsscoverageoptions) * [coverage.startJSCoverage(options)](#coveragestartjscoverageoptions) + * [coverage.stopCSSCoverage()](#coveragestopcsscoverage) * [coverage.stopJSCoverage()](#coveragestopjscoverage) @@ -2155,11 +2157,56 @@ Identifies what kind of target this is. Can be `"page"`, `"service_worker"`, or ### class: Coverage +Coverage gathers information about parts of JavaScript and CSS that were used by the page. + +An example of using JavaScript and CSS coverage to get percentage of initially +executed code: + +```js +// Enable both JavaScript and CSS coverage +await Promise.all([ + page.startJSCoverage(), + page.startCSSCoverage() +]); +// Navigate to page +await page.goto('https://example.com'); +// Disable both JavaScript and CSS coverage +const [jsCoverage, cssCoverage] = await Promise.all([ + page.stopJSCoverage(), + page.stopCSSCoverage(), +]); +let totalBytes = 0; +let usedBytes = 0; +const coverage = [].concat(jsCoverage, cssCoverage); +for (const entry of coverage) { + totalBytes += entry.text.length; + for (const range of entry.ranges) + usedBytes += range.end - range.start - 1; +} +console.log(`Bytes used: ${usedBytes / totalBytes * 100}%`); +``` + +#### coverage.startCSSCoverage(options) +- `options` <[Object]> Set of configurable options for coverage + - `resetOnNavigation` <[boolean]> Whether to reset coverage on every navigation. Defaults to `true`. +- returns: <[Promise]> Promise that resolves when coverage is started + #### coverage.startJSCoverage(options) - `options` <[Object]> Set of configurable options for coverage - `resetOnNavigation` <[boolean]> Whether to reset coverage on every navigation. Defaults to `true`. - returns: <[Promise]> Promise that resolves when coverage is started +#### coverage.stopCSSCoverage() +- returns: <[Promise]<[Array]<[Object]>>> Promise that resolves to the array of coverage reports for all stylesheets + - `url` <[string]> StyleSheet URL + - `text` <[string]> StyleSheet content + - `ranges` <[Array]<[Object]>> StyleSheet ranges that were used. Ranges are sorted and non-overlapping. + - `start` <[number]> A start offset in text, inclusive + - `end` <[number]> An end offset in text, exclusive + +> **NOTE** CSS Coverage doesn't include dynamically injected style tags without sourceURLs. + + #### coverage.stopJSCoverage() - returns: <[Promise]<[Array]<[Object]>>> Promise that resolves to the array of coverage reports for all non-anonymous scripts - `url` <[string]> Script URL @@ -2171,22 +2218,6 @@ Identifies what kind of target this is. Can be `"page"`, `"service_worker"`, or > **NOTE** JavaScript Coverage doesn't include anonymous scripts; however, scripts with sourceURLs are reported. -An example of using JavaScript coverage to get percentage of executed -code: - -```js -await page.startJSCoverage(); -await page.goto('https://example.com'); -const coverage = await page.stopJSCoverage(); -let totalBytes = 0; -let usedBytes = 0; -for (const entry of coverage) { - totalBytes += entry.text.length; - for (const range of entry.ranges) - usedBytes += range.end - range.start - 1; -} -console.log(`Coverage is ${usedBytes / totalBytes * 100}%`); -``` [Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array "Array" [boolean]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type "Boolean" diff --git a/lib/Coverage.js b/lib/Coverage.js index 195dd4ad..0a513d8b 100644 --- a/lib/Coverage.js +++ b/lib/Coverage.js @@ -16,12 +16,20 @@ const {helper, debugError} = require('./helper'); +/** + * @typedef {Object} CoverageEntry + * @property {string} url + * @property {string} text + * @property {!Array} ranges + */ + class Coverage { /** * @param {!Puppeteer.Session} client */ constructor(client) { this._jsCoverage = new JSCoverage(client); + this._cssCoverage = new CSSCoverage(client); } /** @@ -31,9 +39,26 @@ class Coverage { return await this._jsCoverage.start(options); } + /** + * @return {!Promise>} + */ async stopJSCoverage() { return await this._jsCoverage.stop(); } + + /** + * @param {!Object} options + */ + async startCSSCoverage(options) { + return await this._cssCoverage.start(options); + } + + /** + * @return {!Promise>} + */ + async stopCSSCoverage() { + return await this._cssCoverage.stop(); + } } module.exports = {Coverage}; @@ -98,7 +123,7 @@ class JSCoverage { } /** - * @return {!Promise}>>} + * @return {!Promise>} */ async stop() { console.assert(this._enabled, 'JSCoverage is not enabled'); @@ -127,6 +152,104 @@ class JSCoverage { } } +class CSSCoverage { + /** + * @param {!Puppeteer.Session} client + */ + constructor(client) { + this._client = client; + this._enabled = false; + this._stylesheetURLs = new Map(); + this._stylesheetSources = new Map(); + this._eventListeners = []; + this._resetOnNavigation = false; + } + + /** + * @param {!Object} options + */ + async start(options = {}) { + console.assert(!this._enabled, 'CSSCoverage is already enabled'); + this._resetOnNavigation = options.resetOnNavigation === undefined ? true : !!options.resetOnNavigation; + this._enabled = true; + this._stylesheetURLs.clear(); + this._stylesheetSources.clear(); + this._eventListeners = [ + helper.addEventListener(this._client, 'CSS.styleSheetAdded', this._onStyleSheet.bind(this)), + helper.addEventListener(this._client, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)), + ]; + await Promise.all([ + this._client.send('DOM.enable'), + this._client.send('CSS.enable'), + this._client.send('CSS.startRuleUsageTracking'), + ]); + } + + _onExecutionContextsCleared() { + if (!this._resetOnNavigation) + return; + this._stylesheetURLs.clear(); + this._stylesheetSources.clear(); + } + + /** + * @param {!Object} event + */ + async _onStyleSheet(event) { + const header = event.header; + // Ignore anonymous scripts + if (!header.sourceURL) + return; + try { + const response = await this._client.send('CSS.getStyleSheetText', {styleSheetId: header.styleSheetId}); + this._stylesheetURLs.set(header.styleSheetId, header.sourceURL); + this._stylesheetSources.set(header.styleSheetId, response.text); + } catch (e) { + // This might happen if the page has already navigated away. + debugError(e); + } + } + + /** + * @return {!Promise>} + */ + async stop() { + console.assert(this._enabled, 'CSSCoverage is not enabled'); + this._enabled = false; + const [ruleTrackingResponse] = await Promise.all([ + this._client.send('CSS.stopRuleUsageTracking'), + this._client.send('CSS.disable'), + this._client.send('DOM.disable'), + ]); + helper.removeEventListeners(this._eventListeners); + + // aggregarte by styleSheetId + const styleSheetIdToCoverage = new Map(); + for (const entry of ruleTrackingResponse.ruleUsage) { + let ranges = styleSheetIdToCoverage.get(entry.styleSheetId); + if (!ranges) { + ranges = []; + styleSheetIdToCoverage.set(entry.styleSheetId, ranges); + } + ranges.push({ + startOffset: entry.startOffset, + endOffset: entry.endOffset, + count: entry.used ? 1 : 0, + }); + } + + const coverage = []; + for (const styleSheetId of this._stylesheetURLs.keys()) { + const url = this._stylesheetURLs.get(styleSheetId); + const text = this._stylesheetSources.get(styleSheetId); + const ranges = convertToDisjointRanges(styleSheetIdToCoverage.get(styleSheetId) || []); + coverage.push({url, ranges, text}); + } + + return coverage; + } +} + /** * @param {!Array} nestedRanges * @return {!Array} diff --git a/test/assets/csscoverage/Dosis-Regular.ttf b/test/assets/csscoverage/Dosis-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4b208624e8c69294152da06af90f878cb91e05e9 GIT binary patch literal 136940 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 O8fzM)coqDmlKl&Wz|SiH literal 0 HcmV?d00001 diff --git a/test/assets/csscoverage/OFL.txt b/test/assets/csscoverage/OFL.txt new file mode 100644 index 00000000..35a72818 --- /dev/null +++ b/test/assets/csscoverage/OFL.txt @@ -0,0 +1,95 @@ +Copyright (c) 2011, Edgar Tolentino and Pablo Impallari (www.impallari.com|impallari@gmail.com), +Copyright (c) 2011, Igino Marini. (www.ikern.com|mail@iginomarini.com), +with Reserved Font Names "Dosis". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/test/assets/csscoverage/involved.html b/test/assets/csscoverage/involved.html new file mode 100644 index 00000000..bcd9845b --- /dev/null +++ b/test/assets/csscoverage/involved.html @@ -0,0 +1,26 @@ + +
woof!
+fancy text + diff --git a/test/assets/csscoverage/media.html b/test/assets/csscoverage/media.html new file mode 100644 index 00000000..bfb89f8f --- /dev/null +++ b/test/assets/csscoverage/media.html @@ -0,0 +1,4 @@ + +
hello, world
+ diff --git a/test/assets/csscoverage/multiple.html b/test/assets/csscoverage/multiple.html new file mode 100644 index 00000000..0fd97e96 --- /dev/null +++ b/test/assets/csscoverage/multiple.html @@ -0,0 +1,8 @@ + + + diff --git a/test/assets/csscoverage/simple.html b/test/assets/csscoverage/simple.html new file mode 100644 index 00000000..3beae218 --- /dev/null +++ b/test/assets/csscoverage/simple.html @@ -0,0 +1,6 @@ + +
hello, world
+ diff --git a/test/assets/csscoverage/sourceurl.html b/test/assets/csscoverage/sourceurl.html new file mode 100644 index 00000000..df4e9c27 --- /dev/null +++ b/test/assets/csscoverage/sourceurl.html @@ -0,0 +1,7 @@ + + diff --git a/test/assets/csscoverage/stylesheet1.css b/test/assets/csscoverage/stylesheet1.css new file mode 100644 index 00000000..60f1eab9 --- /dev/null +++ b/test/assets/csscoverage/stylesheet1.css @@ -0,0 +1,3 @@ +body { + color: red; +} diff --git a/test/assets/csscoverage/stylesheet2.css b/test/assets/csscoverage/stylesheet2.css new file mode 100644 index 00000000..a87defb0 --- /dev/null +++ b/test/assets/csscoverage/stylesheet2.css @@ -0,0 +1,4 @@ +html { + margin: 0; + padding: 0; +} diff --git a/test/assets/csscoverage/unused.html b/test/assets/csscoverage/unused.html new file mode 100644 index 00000000..5b8186a3 --- /dev/null +++ b/test/assets/csscoverage/unused.html @@ -0,0 +1,7 @@ + + diff --git a/test/golden/csscoverage-involved.txt b/test/golden/csscoverage-involved.txt new file mode 100644 index 00000000..33103e01 --- /dev/null +++ b/test/golden/csscoverage-involved.txt @@ -0,0 +1,16 @@ +[ + { + "url": "http://localhost:8907/csscoverage/involved.html", + "ranges": [ + { + "start": 149, + "end": 297 + }, + { + "start": 327, + "end": 433 + } + ], + "text": "\n@charset \"utf-8\";\n@namespace svg url(http://www.w3.org/2000/svg);\n@font-face {\n font-family: \"Example Font\";\n src: url(\"./Dosis-Regular.ttf\");\n}\n\n#fluffy {\n border: 1px solid black;\n z-index: 1;\n /* -webkit-disabled-property: rgb(1, 2, 3) */\n -lol-cats: \"dogs\" /* non-existing property */\n}\n\n@media (min-width: 1px) {\n span {\n -webkit-border-radius: 10px;\n font-family: \"Example Font\";\n animation: 1s identifier;\n }\n}\n" + } +] \ No newline at end of file diff --git a/test/test.js b/test/test.js index 4c58fdb6..1febcc41 100644 --- a/test/test.js +++ b/test/test.js @@ -3495,6 +3495,85 @@ describe('Page', function() { }); }); }); + describe('CSSCoverage', function() { + it('should work', async function({page, server}) { + await page.coverage.startCSSCoverage(); + await page.goto(server.PREFIX + '/csscoverage/simple.html'); + const coverage = await page.coverage.stopCSSCoverage(); + expect(coverage.length).toBe(1); + expect(coverage[0].url).toContain('/csscoverage/simple.html'); + expect(coverage[0].ranges).toEqual([ + {start: 1, end: 22} + ]); + const range = coverage[0].ranges[0]; + expect(coverage[0].text.substring(range.start, range.end)).toBe('div { color: green; }'); + }); + it('should report sourceURLs', async function({page, server}) { + await page.coverage.startCSSCoverage(); + await page.goto(server.PREFIX + '/csscoverage/sourceurl.html'); + const coverage = await page.coverage.stopCSSCoverage(); + expect(coverage.length).toBe(1); + expect(coverage[0].url).toBe('nicename.css'); + }); + it('should report multiple stylesheets', async function({page, server}) { + await page.coverage.startCSSCoverage(); + await page.goto(server.PREFIX + '/csscoverage/multiple.html'); + const coverage = await page.coverage.stopCSSCoverage(); + expect(coverage.length).toBe(2); + coverage.sort((a, b) => a.url.localeCompare(b.url)); + expect(coverage[0].url).toContain('/csscoverage/stylesheet1.css'); + expect(coverage[1].url).toContain('/csscoverage/stylesheet2.css'); + }); + it('should report stylesheets that have no coverage', async function({page, server}) { + await page.coverage.startCSSCoverage(); + await page.goto(server.PREFIX + '/csscoverage/unused.html'); + const coverage = await page.coverage.stopCSSCoverage(); + expect(coverage.length).toBe(1); + expect(coverage[0].url).toBe('unused.css'); + expect(coverage[0].ranges.length).toBe(0); + }); + it('should work with media queries', async function({page, server}) { + await page.coverage.startCSSCoverage(); + await page.goto(server.PREFIX + '/csscoverage/media.html'); + const coverage = await page.coverage.stopCSSCoverage(); + expect(coverage.length).toBe(1); + expect(coverage[0].url).toContain('/csscoverage/media.html'); + expect(coverage[0].ranges).toEqual([ + {start: 17, end: 38} + ]); + }); + it('should work with complicated usecases', async function({page, server}) { + await page.coverage.startCSSCoverage(); + await page.goto(server.PREFIX + '/csscoverage/involved.html'); + const coverage = await page.coverage.stopCSSCoverage(); + expect(JSON.stringify(coverage, null, 2)).toBeGolden('csscoverage-involved.txt'); + }); + it('should ignore injected stylesheets', async function({page, server}) { + await page.coverage.startCSSCoverage(); + await page.addStyleTag({content: 'body { margin: 10px;}'}); + // trigger style recalc + const margin = await page.evaluate(() => window.getComputedStyle(document.body).margin); + expect(margin).toBe('10px'); + const coverage = await page.coverage.stopCSSCoverage(); + expect(coverage.length).toBe(0); + }); + describe('resetOnNavigation', function() { + it('should report stylesheets across navigations', async function({page, server}) { + await page.coverage.startCSSCoverage({resetOnNavigation: false}); + await page.goto(server.PREFIX + '/csscoverage/multiple.html'); + await page.goto(server.EMPTY_PAGE); + const coverage = await page.coverage.stopCSSCoverage(); + expect(coverage.length).toBe(2); + }); + it('should NOT report scripts across navigations', async function({page, server}) { + await page.coverage.startCSSCoverage(); // Enabled by default. + await page.goto(server.PREFIX + '/csscoverage/multiple.html'); + await page.goto(server.EMPTY_PAGE); + const coverage = await page.coverage.stopCSSCoverage(); + expect(coverage.length).toBe(0); + }); + }); + }); }); if (process.env.COVERAGE) { diff --git a/utils/doclint/check_public_api/index.js b/utils/doclint/check_public_api/index.js index da2949f2..3c2eb577 100644 --- a/utils/doclint/check_public_api/index.js +++ b/utils/doclint/check_public_api/index.js @@ -20,6 +20,7 @@ const Documentation = require('./Documentation'); const Message = require('../Message'); const EXCLUDE_CLASSES = new Set([ + 'CSSCoverage', 'Connection', 'Downloader', 'EmulationManager',