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 1bb6a09e3ba08..b6ceb758ed46a 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 278bb446a8363..3f2738a629487 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 aa7108c10c55f..c2d752d732203 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 0000000000000..fe68dac87ed44 --- /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 a41f7b4709e40..6dab0cff7a387 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 a537a7da6a707..3d02670aeafaf 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 2f8f2e7a1de66..3ae1af6337002 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 () => {