From a032583b6c9b469bda699bca200b180206d61247 Mon Sep 17 00:00:00 2001 From: smithc <954720+smithc@users.noreply.github.com> Date: Thu, 6 Oct 2022 17:22:44 -0400 Subject: [PATCH] feat: add ability to collect JS code coverage at the function level (#9027) --- .../api/puppeteer.coverage.startjscoverage.md | 6 ++--- docs/api/puppeteer.jscoverage.start.md | 7 +++--- docs/api/puppeteer.jscoverageoptions.md | 11 +++++----- ...teer.jscoverageoptions.useblockcoverage.md | 15 +++++++++++++ .../puppeteer-core/src/common/Coverage.ts | 13 +++++++++-- test/assets/jscoverage/ranges.html | 2 +- test/src/coverage.spec.ts | 22 ++++++++++++++++++- 7 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 docs/api/puppeteer.jscoverageoptions.useblockcoverage.md diff --git a/docs/api/puppeteer.coverage.startjscoverage.md b/docs/api/puppeteer.coverage.startjscoverage.md index 1bb6a09e..b6ceb758 100644 --- a/docs/api/puppeteer.coverage.startjscoverage.md +++ b/docs/api/puppeteer.coverage.startjscoverage.md @@ -14,9 +14,9 @@ class Coverage { ## Parameters -| Parameter | Type | Description | -| --------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| options | [JSCoverageOptions](./puppeteer.jscoverageoptions.md) | (Optional) Set of configurable options for coverage defaults to resetOnNavigation : true, reportAnonymousScripts : false | +| Parameter | Type | Description | +| --------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| options | [JSCoverageOptions](./puppeteer.jscoverageoptions.md) | (Optional) Set of configurable options for coverage defaults to resetOnNavigation : true, reportAnonymousScripts : false, includeRawScriptCoverage : false, useBlockCoverage : true | **Returns:** diff --git a/docs/api/puppeteer.jscoverage.start.md b/docs/api/puppeteer.jscoverage.start.md index 278bb446..3f2738a6 100644 --- a/docs/api/puppeteer.jscoverage.start.md +++ b/docs/api/puppeteer.jscoverage.start.md @@ -12,15 +12,16 @@ class JSCoverage { resetOnNavigation?: boolean; reportAnonymousScripts?: boolean; includeRawScriptCoverage?: boolean; + useBlockCoverage?: boolean; }): Promise; } ``` ## Parameters -| Parameter | Type | Description | -| --------- | ------------------------------------------------------------------------------------------------------ | ----------------- | -| options | { resetOnNavigation?: boolean; reportAnonymousScripts?: boolean; includeRawScriptCoverage?: boolean; } | (Optional) | +| Parameter | Type | Description | +| --------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------- | +| options | { resetOnNavigation?: boolean; reportAnonymousScripts?: boolean; includeRawScriptCoverage?: boolean; useBlockCoverage?: boolean; } | (Optional) | **Returns:** diff --git a/docs/api/puppeteer.jscoverageoptions.md b/docs/api/puppeteer.jscoverageoptions.md index aa7108c1..c2d752d7 100644 --- a/docs/api/puppeteer.jscoverageoptions.md +++ b/docs/api/puppeteer.jscoverageoptions.md @@ -14,8 +14,9 @@ export interface JSCoverageOptions ## Properties -| Property | Modifiers | Type | Description | -| -------------------------------------------------------------------------------------- | --------- | ------- | ------------------------------------------------------------------------------------- | -| [includeRawScriptCoverage?](./puppeteer.jscoverageoptions.includerawscriptcoverage.md) | | boolean | (Optional) Whether the result includes raw V8 script coverage entries. | -| [reportAnonymousScripts?](./puppeteer.jscoverageoptions.reportanonymousscripts.md) | | boolean | (Optional) Whether anonymous scripts generated by the page should be reported. | -| [resetOnNavigation?](./puppeteer.jscoverageoptions.resetonnavigation.md) | | boolean | (Optional) Whether to reset coverage on every navigation. | +| Property | Modifiers | Type | Description | +| -------------------------------------------------------------------------------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [includeRawScriptCoverage?](./puppeteer.jscoverageoptions.includerawscriptcoverage.md) | | boolean | (Optional) Whether the result includes raw V8 script coverage entries. | +| [reportAnonymousScripts?](./puppeteer.jscoverageoptions.reportanonymousscripts.md) | | boolean | (Optional) Whether anonymous scripts generated by the page should be reported. | +| [resetOnNavigation?](./puppeteer.jscoverageoptions.resetonnavigation.md) | | boolean | (Optional) Whether to reset coverage on every navigation. | +| [useBlockCoverage?](./puppeteer.jscoverageoptions.useblockcoverage.md) | | boolean | (Optional) Whether to collect coverage information at the block level. If true, coverage will be collected at the block level (this is the default). If false, coverage will be collected at the function level. | diff --git a/docs/api/puppeteer.jscoverageoptions.useblockcoverage.md b/docs/api/puppeteer.jscoverageoptions.useblockcoverage.md new file mode 100644 index 00000000..fe68dac8 --- /dev/null +++ b/docs/api/puppeteer.jscoverageoptions.useblockcoverage.md @@ -0,0 +1,15 @@ +--- +sidebar_label: JSCoverageOptions.useBlockCoverage +--- + +# JSCoverageOptions.useBlockCoverage property + +Whether to collect coverage information at the block level. If true, coverage will be collected at the block level (this is the default). If false, coverage will be collected at the function level. + +**Signature:** + +```typescript +interface JSCoverageOptions { + useBlockCoverage?: boolean; +} +``` diff --git a/packages/puppeteer-core/src/common/Coverage.ts b/packages/puppeteer-core/src/common/Coverage.ts index a41f7b47..6dab0cff 100644 --- a/packages/puppeteer-core/src/common/Coverage.ts +++ b/packages/puppeteer-core/src/common/Coverage.ts @@ -74,6 +74,12 @@ export interface JSCoverageOptions { * Whether the result includes raw V8 script coverage entries. */ includeRawScriptCoverage?: boolean; + /** + * Whether to collect coverage information at the block level. + * If true, coverage will be collected at the block level (this is the default). + * If false, coverage will be collected at the function level. + */ + useBlockCoverage?: boolean; } /** @@ -135,7 +141,8 @@ export class Coverage { /** * @param options - Set of configurable options for coverage defaults to - * `resetOnNavigation : true, reportAnonymousScripts : false` + * `resetOnNavigation : true, reportAnonymousScripts : false,` + * `includeRawScriptCoverage : false, useBlockCoverage : true` * @returns Promise that resolves when coverage is started. * * @remarks @@ -204,6 +211,7 @@ export class JSCoverage { resetOnNavigation?: boolean; reportAnonymousScripts?: boolean; includeRawScriptCoverage?: boolean; + useBlockCoverage?: boolean; } = {} ): Promise { assert(!this.#enabled, 'JSCoverage is already enabled'); @@ -211,6 +219,7 @@ export class JSCoverage { resetOnNavigation = true, reportAnonymousScripts = false, includeRawScriptCoverage = false, + useBlockCoverage = true, } = options; this.#resetOnNavigation = resetOnNavigation; this.#reportAnonymousScripts = reportAnonymousScripts; @@ -234,7 +243,7 @@ export class JSCoverage { this.#client.send('Profiler.enable'), this.#client.send('Profiler.startPreciseCoverage', { callCount: this.#includeRawScriptCoverage, - detailed: true, + detailed: useBlockCoverage, }), this.#client.send('Debugger.enable'), this.#client.send('Debugger.setSkipAllPauses', {skip: true}), diff --git a/test/assets/jscoverage/ranges.html b/test/assets/jscoverage/ranges.html index a537a7da..3d02670a 100644 --- a/test/assets/jscoverage/ranges.html +++ b/test/assets/jscoverage/ranges.html @@ -1,2 +1,2 @@ +function unused(){}console.log('used!');if(true===false)console.log('unused!'); diff --git a/test/src/coverage.spec.ts b/test/src/coverage.spec.ts index 2f8f2e7a..3ae1af63 100644 --- a/test/src/coverage.spec.ts +++ b/test/src/coverage.spec.ts @@ -108,7 +108,27 @@ describe('Coverage specs', function () { expect(entry.text.substring(range1.start, range1.end)).toBe('\n'); const range2 = entry.ranges[1]!; expect(entry.text.substring(range2.start, range2.end)).toBe( - `console.log('used!');` + `console.log('used!');if(true===false)` + ); + }); + it('should report right ranges for "per function" scope', async () => { + const {page, server} = getTestState(); + + const coverageOptions = { + useBlockCoverage: false, + }; + + await page.coverage.startJSCoverage(coverageOptions); + await page.goto(server.PREFIX + '/jscoverage/ranges.html'); + const coverage = await page.coverage.stopJSCoverage(); + expect(coverage.length).toBe(1); + const entry = coverage[0]!; + expect(entry.ranges.length).toBe(2); + const range1 = entry.ranges[0]!; + expect(entry.text.substring(range1.start, range1.end)).toBe('\n'); + const range2 = entry.ranges[1]!; + expect(entry.text.substring(range2.start, range2.end)).toBe( + `console.log('used!');if(true===false)console.log('unused!');` ); }); it('should report scripts that have no coverage', async () => {