@wdio/lighthouse-service 9.0.0-alpha.321

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE-MIT +20 -0
  2. package/README.md +258 -0
  3. package/build/auditor.d.ts +54 -0
  4. package/build/auditor.d.ts.map +1 -0
  5. package/build/auditor.js +147 -0
  6. package/build/commands.d.ts +86 -0
  7. package/build/commands.d.ts.map +1 -0
  8. package/build/commands.js +212 -0
  9. package/build/constants.d.ts +95 -0
  10. package/build/constants.d.ts.map +1 -0
  11. package/build/constants.js +150 -0
  12. package/build/gatherer/devtools.d.ts +19 -0
  13. package/build/gatherer/devtools.d.ts.map +1 -0
  14. package/build/gatherer/devtools.js +12 -0
  15. package/build/gatherer/pwa.d.ts +28 -0
  16. package/build/gatherer/pwa.d.ts.map +1 -0
  17. package/build/gatherer/pwa.js +66 -0
  18. package/build/gatherer/trace.d.ts +61 -0
  19. package/build/gatherer/trace.d.ts.map +1 -0
  20. package/build/gatherer/trace.js +233 -0
  21. package/build/handler/network.d.ts +45 -0
  22. package/build/handler/network.d.ts.map +1 -0
  23. package/build/handler/network.js +133 -0
  24. package/build/index.d.ts +50 -0
  25. package/build/index.d.ts.map +1 -0
  26. package/build/index.js +126 -0
  27. package/build/lighthouse/cri.d.ts +23 -0
  28. package/build/lighthouse/cri.d.ts.map +1 -0
  29. package/build/lighthouse/cri.js +29 -0
  30. package/build/scripts/collectMetaElements.d.ts +8 -0
  31. package/build/scripts/collectMetaElements.d.ts.map +1 -0
  32. package/build/scripts/collectMetaElements.js +37 -0
  33. package/build/scripts/registerPerformanceObserverInPage.d.ts +12 -0
  34. package/build/scripts/registerPerformanceObserverInPage.d.ts.map +1 -0
  35. package/build/scripts/registerPerformanceObserverInPage.js +23 -0
  36. package/build/types.d.ts +168 -0
  37. package/build/types.d.ts.map +1 -0
  38. package/build/types.js +1 -0
  39. package/build/utils.d.ts +23 -0
  40. package/build/utils.d.ts.map +1 -0
  41. package/build/utils.js +64 -0
  42. package/package.json +66 -0
package/LICENSE-MIT ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) OpenJS Foundation and other contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,258 @@
1
+ WebdriverIO Lighthouse Service
2
+ ==============================
3
+
4
+ > A WebdriverIO service that allows you to run accessibility and performance tests with [Google Lighthouse](https://developer.chrome.com/docs/lighthouse/overview).
5
+
6
+ **Note:** this service currently only supports tests running on Google Chrome or Chromium! Given that most cloud vendors don't expose access to the Chrome DevTools Protocol this service also usually only works when running tests locally or through a [Selenium Grid](https://www.selenium.dev/documentation/grid/) v4 or higher.
7
+
8
+ ## Installation
9
+
10
+ The easiest way is to keep `@wdio/lighthouse-service` as a dev dependency in your `package.json`, via:
11
+
12
+ ```sh
13
+ npm install @wdio/lighthouse-service --save-dev
14
+ ```
15
+
16
+ Instructions on how to install `WebdriverIO` can be found [here](https://webdriver.io/docs/gettingstarted).
17
+
18
+ ## Configuration
19
+
20
+ In order to use the service you just need to add the service to your service list in your `wdio.conf.js`, like:
21
+
22
+ ```js
23
+ // wdio.conf.js
24
+ export const config = {
25
+ // ...
26
+ services: ['devtools'],
27
+ // ...
28
+ };
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ The `@wdio/lighthouse-service` allows you to run Google Lighthouse accessibility and performance tests through WebdriverIO.
34
+
35
+ ### Performance Testing
36
+
37
+ The Lighthouse service allows you to capture performance data from every page load or page transition that was caused by a click. To enable it call `browser.enablePerformanceAudits(<options>)`. After you are done capturing all necessary performance data disable it to revert the throttling settings, e.g.:
38
+
39
+ ```js
40
+ import assert from 'node:assert'
41
+
42
+ describe('JSON.org page', () => {
43
+ before(async () => {
44
+ await browser.enablePerformanceAudits()
45
+ })
46
+
47
+ it('should load within performance budget', async () => {
48
+ /**
49
+ * this page load will take a bit longer as the DevTools service will
50
+ * capture all metrics in the background
51
+ */
52
+ await browser.url('http://json.org')
53
+
54
+ let metrics = await browser.getMetrics()
55
+ assert.ok(metrics.speedIndex < 1500) // check that speedIndex is below 1.5ms
56
+
57
+ let score = await browser.getPerformanceScore() // get Lighthouse Performance score
58
+ assert.ok(score >= .99) // Lighthouse Performance score is at 99% or higher
59
+
60
+ $('=Esperanto').click()
61
+
62
+ metrics = await browser.getMetrics()
63
+ assert.ok(metrics.speedIndex < 1500)
64
+ score = await browser.getPerformanceScore()
65
+ assert.ok(score >= .99)
66
+ })
67
+
68
+ after(async () => {
69
+ await browser.disablePerformanceAudits()
70
+ })
71
+ })
72
+ ```
73
+
74
+ You can emulate a mobile device by using the `emulateDevice` command, throttling CPU and network as well as setting `mobile` as form factor:
75
+
76
+ ```js
77
+ await browser.emulateDevice('iPhone X')
78
+ await browser.enablePerformanceAudits({
79
+ networkThrottling: 'Good 3G',
80
+ cpuThrottling: 4,
81
+ formFactor: 'mobile'
82
+ })
83
+ ```
84
+
85
+ The following commands with their results are available:
86
+
87
+ #### `getMetrics`
88
+
89
+ Gets the most commonly used performance metrics, e.g.:
90
+
91
+ ```js
92
+ console.log(await browser.getMetrics())
93
+ /**
94
+ * { timeToFirstByte: 566,
95
+ * serverResponseTime: 566,
96
+ * domContentLoaded: 3397,
97
+ * firstVisualChange: 2610,
98
+ * firstPaint: 2822,
99
+ * firstContentfulPaint: 2822,
100
+ * firstMeaningfulPaint: 2822,
101
+ * largestContentfulPaint: 2822,
102
+ * lastVisualChange: 15572,
103
+ * interactive: 6135,
104
+ * load: 8429,
105
+ * speedIndex: 3259,
106
+ * totalBlockingTime: 31,
107
+ * maxPotentialFID: 161,
108
+ * cumulativeLayoutShift: 2822 }
109
+ */
110
+ ```
111
+
112
+ #### `getDiagnostics`
113
+
114
+ Get some useful diagnostics about the page load.
115
+
116
+ ```js
117
+ console.log(await browser.getDiagnostics())
118
+ /**
119
+ * { numRequests: 8,
120
+ * numScripts: 0,
121
+ * numStylesheets: 0,
122
+ * numFonts: 0,
123
+ * numTasks: 237,
124
+ * numTasksOver10ms: 5,
125
+ * numTasksOver25ms: 2,
126
+ * numTasksOver50ms: 2,
127
+ * numTasksOver100ms: 0,
128
+ * numTasksOver500ms: 0,
129
+ * rtt: 147.20600000000002,
130
+ * throughput: 47729.68474448835,
131
+ * maxRtt: 176.085,
132
+ * maxServerLatency: 1016.813,
133
+ * totalByteWeight: 62929,
134
+ * totalTaskTime: 254.07899999999978,
135
+ * mainDocumentTransferSize: 8023 }
136
+ */
137
+ ```
138
+
139
+ #### getMainThreadWorkBreakdown
140
+
141
+ Returns a list with a breakdown of all main thread tasks and their total duration.
142
+
143
+ ```js
144
+ console.log(await browser.getMainThreadWorkBreakdown())
145
+ /**
146
+ * [ { group: 'styleLayout', duration: 130.59099999999998 },
147
+ * { group: 'other', duration: 44.819 },
148
+ * { group: 'paintCompositeRender', duration: 13.732000000000005 },
149
+ * { group: 'parseHTML', duration: 3.9080000000000004 },
150
+ * { group: 'scriptEvaluation', duration: 2.437999999999999 },
151
+ * { group: 'scriptParseCompile', duration: 0.20800000000000002 } ]
152
+ */
153
+ ```
154
+
155
+ #### getPerformanceScore
156
+
157
+ Returns the [Lighthouse Performance Score](https://developers.google.com/web/tools/lighthouse/scoring) which is a weighted mean of the following metrics: `firstContentfulPaint`, `speedIndex`, `largestContentfulPaint`, `cumulativeLayoutShift`, `totalBlockingTime`, `interactive`, `maxPotentialFID` or `cumulativeLayoutShift`.
158
+
159
+ ```js
160
+ console.log(await browser.getPerformanceScore())
161
+ /**
162
+ * 0.897826278457836
163
+ */
164
+ ```
165
+
166
+ #### enablePerformanceAudits
167
+
168
+ Enables auto performance audits for all page loads that are caused by calling the `url` command or clicking on a link or anything that causes a page load. You can pass in a config object to determine some throttling options. The default throttling profile is `Good 3G` network with a 4x CPU throttling.
169
+
170
+ ```js
171
+ await browser.enablePerformanceAudits({
172
+ networkThrottling: 'Good 3G',
173
+ cpuThrottling: 4,
174
+ cacheEnabled: true,
175
+ formFactor: 'mobile'
176
+ })
177
+ ```
178
+
179
+ The following network throttling profiles are available: `offline`, `GPRS`, `Regular 2G`, `Good 2G`, `Regular 3G`, `Good 3G`, `Regular 4G`, `DSL`, `Wifi` and `online` (no throttling).
180
+
181
+ ### PWA Testing
182
+
183
+ With the `checkPWA` command, you can validate if your web app is compliant to the latest web standards when it comes to progressive web apps. It checks:
184
+
185
+ - whether your app is installable
186
+ - provides a service worker
187
+ - has a splash screen
188
+ - provides Apple Touch and Maskable Icons
189
+ - can be served on mobile devices
190
+
191
+ If you are not interested in one of these checks you can pass in a list of checks you like to run. The `passed` property will return `true` if all checks pass. If they fail you can use the `details` property to enrich your failure message with details of the failure.
192
+
193
+ ```js
194
+ // open page first
195
+ await browser.url('https://webdriver.io')
196
+ // validate PWA
197
+ const result = await browser.checkPWA()
198
+ expect(result.passed).toBe(true)
199
+ ```
200
+
201
+ ### `startTracing(categories, samplingFrequency)` Command
202
+
203
+ Start tracing the browser. You can optionally pass in custom tracing categories (defaults to [this list](https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-lighthouse-service/src/constants.js#L1-L9)) and the sampling frequency (defaults to `10000`).
204
+
205
+ ```js
206
+ await browser.startTracing()
207
+ ```
208
+
209
+ ### `endTracing` Command
210
+
211
+ Stop tracing the browser.
212
+
213
+ ```js
214
+ await browser.endTracing()
215
+ ```
216
+
217
+ ### `getTraceLogs` Command
218
+
219
+ Returns the trace-logs that were captured within the tracing period. You can use this command to store the trace logs on the file system to analyse the trace via Chrome DevTools interface.
220
+
221
+ ```js
222
+ import fs from 'node:fs/promises'
223
+
224
+ await browser.startTracing()
225
+ await browser.url('http://json.org')
226
+ await browser.endTracing()
227
+
228
+ await fs.writeFile('/path/to/tracelog.json', JSON.stringify(browser.getTraceLogs()))
229
+ ```
230
+
231
+ ### `getPageWeight` Command
232
+
233
+ Returns page weight information of the last page load.
234
+
235
+ ```js
236
+ await browser.startTracing()
237
+ await browser.url('https://webdriver.io')
238
+ await browser.endTracing()
239
+
240
+ console.log(await browser.getPageWeight())
241
+ // outputs:
242
+ // { pageWeight: 2438485,
243
+ // transferred: 1139136,
244
+ // requestCount: 72,
245
+ // details: {
246
+ // Document: { size: 221705, encoded: 85386, count: 11 },
247
+ // Stylesheet: { size: 52712, encoded: 50130, count: 2 },
248
+ // Image: { size: 495023, encoded: 482433, count: 36 },
249
+ // Script: { size: 1073597, encoded: 322854, count: 15 },
250
+ // Font: { size: 84412, encoded: 84412, count: 5 },
251
+ // Other: { size: 1790, encoded: 1790, count: 2 },
252
+ // XHR: { size: 509246, encoded: 112131, count: 1 } }
253
+ // }
254
+ ```
255
+
256
+ ----
257
+
258
+ For more information on WebdriverIO see the [homepage](https://webdriver.io).
@@ -0,0 +1,54 @@
1
+ import type { CustomInstanceCommands } from 'webdriverio';
2
+ import type { FormFactor, Audit, AuditResult, LHAuditResult, ErrorAudit } from './types.js';
3
+ import type { Trace } from './gatherer/trace.js';
4
+ import type { CDPSessionOnMessageObject } from './gatherer/devtools.js';
5
+ export default class Auditor {
6
+ private _traceLogs?;
7
+ private _devtoolsLogs?;
8
+ private _formFactor?;
9
+ private _url?;
10
+ constructor(_traceLogs?: Trace | undefined, _devtoolsLogs?: CDPSessionOnMessageObject[] | undefined, _formFactor?: FormFactor | undefined);
11
+ _audit(AUDIT: Audit, params?: {}): Promise<LHAuditResult> | ErrorAudit;
12
+ /**
13
+ * an Auditor instance is created for every trace so provide an updateCommands
14
+ * function to receive the latest performance metrics with the browser instance
15
+ */
16
+ updateCommands(browser: WebdriverIO.Browser, customFn?: CustomInstanceCommands<WebdriverIO.Browser>['addCommand']): void;
17
+ /**
18
+ * Returns a list with a breakdown of all main thread task and their total duration
19
+ */
20
+ getMainThreadWorkBreakdown(): Promise<{
21
+ group: string;
22
+ duration: number;
23
+ }[]>;
24
+ /**
25
+ * Get some useful diagnostics about the page load
26
+ */
27
+ getDiagnostics(): Promise<any>;
28
+ /**
29
+ * Get most common used performance metrics
30
+ */
31
+ getMetrics(): Promise<{
32
+ timeToFirstByte: number;
33
+ serverResponseTime: number;
34
+ domContentLoaded: number;
35
+ firstVisualChange: number;
36
+ firstPaint: number;
37
+ firstContentfulPaint: number;
38
+ firstMeaningfulPaint: number;
39
+ largestContentfulPaint: number;
40
+ lastVisualChange: number;
41
+ interactive: number;
42
+ load: number;
43
+ speedIndex: number;
44
+ totalBlockingTime: number;
45
+ maxPotentialFID: number;
46
+ cumulativeLayoutShift: number;
47
+ }>;
48
+ /**
49
+ * Returns the Lighthouse Performance Score which is a weighted mean of the following metrics: firstMeaningfulPaint, interactive, speedIndex
50
+ */
51
+ getPerformanceScore(): Promise<any>;
52
+ _auditPWA(params: any, auditsToBeRun?: ("isInstallable" | "serviceWorker" | "splashScreen" | "themedOmnibox" | "contentWith" | "viewport" | "appleTouchIcon" | "maskableIcon")[]): Promise<AuditResult>;
53
+ }
54
+ //# sourceMappingURL=auditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auditor.d.ts","sourceRoot":"","sources":["../src/auditor.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAGzD,OAAO,KAAK,EACR,UAAU,EAAE,KAAK,EAEjB,WAAW,EAAE,aAAa,EAAE,UAAU,EACzC,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAMvE,MAAM,CAAC,OAAO,OAAO,OAAO;IAIpB,OAAO,CAAC,UAAU,CAAC;IACnB,OAAO,CAAC,aAAa,CAAC;IACtB,OAAO,CAAC,WAAW,CAAC;IALxB,OAAO,CAAC,IAAI,CAAC,CAAQ;gBAGT,UAAU,CAAC,mBAAO,EAClB,aAAa,CAAC,yCAA6B,EAC3C,WAAW,CAAC,wBAAY;IAOpC,MAAM,CAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,UAAU;IA8BvE;;;OAGG;IACH,cAAc,CAAE,OAAO,EAAE,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,sBAAsB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC;IAMlH;;OAEG;IACG,0BAA0B;;;;IAOhC;;OAEG;IACG,cAAc;IAapB;;OAEG;IACG,UAAU;;;;;;;;;;;;;;;;;IAwBhB;;OAEG;IACG,mBAAmB;IAuBnB,SAAS,CACX,MAAM,EAAE,GAAG,EACX,aAAa,4IAAyC,GACvD,OAAO,CAAC,WAAW,CAAC;CAgB1B"}
@@ -0,0 +1,147 @@
1
+ import Diagnostics from 'lighthouse/lighthouse-core/audits/diagnostics.js';
2
+ import MainThreadWorkBreakdown from 'lighthouse/lighthouse-core/audits/mainthread-work-breakdown.js';
3
+ import Metrics from 'lighthouse/lighthouse-core/audits/metrics.js';
4
+ import ServerResponseTime from 'lighthouse/lighthouse-core/audits/server-response-time.js';
5
+ import CumulativeLayoutShift from 'lighthouse/lighthouse-core/audits/metrics/cumulative-layout-shift.js';
6
+ import FirstContentfulPaint from 'lighthouse/lighthouse-core/audits/metrics/first-contentful-paint.js';
7
+ import LargestContentfulPaint from 'lighthouse/lighthouse-core/audits/metrics/largest-contentful-paint.js';
8
+ import SpeedIndex from 'lighthouse/lighthouse-core/audits/metrics/speed-index.js';
9
+ import InteractiveMetric from 'lighthouse/lighthouse-core/audits/metrics/interactive.js';
10
+ import TotalBlockingTime from 'lighthouse/lighthouse-core/audits/metrics/total-blocking-time.js';
11
+ import ReportScoring from 'lighthouse/lighthouse-core/scoring.js';
12
+ import defaultConfig from 'lighthouse/lighthouse-core/config/default-config.js';
13
+ import logger from '@wdio/logger';
14
+ import { DEFAULT_FORM_FACTOR, PWA_AUDITS } from './constants.js';
15
+ const log = logger('@wdio/lighthouse-service:Auditor');
16
+ export default class Auditor {
17
+ _traceLogs;
18
+ _devtoolsLogs;
19
+ _formFactor;
20
+ _url;
21
+ constructor(_traceLogs, _devtoolsLogs, _formFactor) {
22
+ this._traceLogs = _traceLogs;
23
+ this._devtoolsLogs = _devtoolsLogs;
24
+ this._formFactor = _formFactor;
25
+ if (_traceLogs) {
26
+ this._url = _traceLogs.pageUrl;
27
+ }
28
+ }
29
+ _audit(AUDIT, params = {}) {
30
+ const auditContext = {
31
+ options: {
32
+ ...AUDIT.defaultOptions
33
+ },
34
+ settings: {
35
+ throttlingMethod: 'devtools',
36
+ formFactor: this._formFactor || DEFAULT_FORM_FACTOR
37
+ },
38
+ LighthouseRunWarnings: false,
39
+ computedCache: new Map()
40
+ };
41
+ try {
42
+ return AUDIT.audit({
43
+ traces: { defaultPass: this._traceLogs },
44
+ devtoolsLogs: { defaultPass: this._devtoolsLogs },
45
+ TestedAsMobileDevice: true,
46
+ GatherContext: { gatherMode: 'navigation' },
47
+ ...params
48
+ }, auditContext);
49
+ }
50
+ catch (error) {
51
+ log.error(error);
52
+ return {
53
+ score: 0,
54
+ error
55
+ };
56
+ }
57
+ }
58
+ /**
59
+ * an Auditor instance is created for every trace so provide an updateCommands
60
+ * function to receive the latest performance metrics with the browser instance
61
+ */
62
+ updateCommands(browser, customFn) {
63
+ const commands = Object.getOwnPropertyNames(Object.getPrototypeOf(this)).filter(fnName => fnName !== 'constructor' && fnName !== 'updateCommands' && !fnName.startsWith('_'));
64
+ commands.forEach(fnName => browser.addCommand(fnName, customFn || this[fnName].bind(this)));
65
+ }
66
+ /**
67
+ * Returns a list with a breakdown of all main thread task and their total duration
68
+ */
69
+ async getMainThreadWorkBreakdown() {
70
+ const result = await this._audit(MainThreadWorkBreakdown);
71
+ return result.details.items.map(({ group, duration }) => ({ group, duration }));
72
+ }
73
+ /**
74
+ * Get some useful diagnostics about the page load
75
+ */
76
+ async getDiagnostics() {
77
+ const result = await this._audit(Diagnostics);
78
+ /**
79
+ * return null if Audit fails
80
+ */
81
+ if (!Object.prototype.hasOwnProperty.call(result, 'details')) {
82
+ return null;
83
+ }
84
+ return result.details.items[0];
85
+ }
86
+ /**
87
+ * Get most common used performance metrics
88
+ */
89
+ async getMetrics() {
90
+ const serverResponseTime = await this._audit(ServerResponseTime, { URL: this._url });
91
+ const cumulativeLayoutShift = await this._audit(CumulativeLayoutShift);
92
+ const result = await this._audit(Metrics);
93
+ const metrics = result.details.items[0] || {};
94
+ return {
95
+ timeToFirstByte: Math.round(serverResponseTime.numericValue),
96
+ serverResponseTime: Math.round(serverResponseTime.numericValue),
97
+ domContentLoaded: metrics.observedDomContentLoaded,
98
+ firstVisualChange: metrics.observedFirstVisualChange,
99
+ firstPaint: metrics.observedFirstPaint,
100
+ firstContentfulPaint: metrics.firstContentfulPaint,
101
+ firstMeaningfulPaint: metrics.firstMeaningfulPaint,
102
+ largestContentfulPaint: metrics.largestContentfulPaint,
103
+ lastVisualChange: metrics.observedLastVisualChange,
104
+ interactive: metrics.interactive,
105
+ load: metrics.observedLoad,
106
+ speedIndex: metrics.speedIndex,
107
+ totalBlockingTime: metrics.totalBlockingTime,
108
+ maxPotentialFID: metrics.maxPotentialFID,
109
+ cumulativeLayoutShift: cumulativeLayoutShift.numericValue,
110
+ };
111
+ }
112
+ /**
113
+ * Returns the Lighthouse Performance Score which is a weighted mean of the following metrics: firstMeaningfulPaint, interactive, speedIndex
114
+ */
115
+ async getPerformanceScore() {
116
+ const auditResults = {
117
+ 'speed-index': await this._audit(SpeedIndex),
118
+ 'first-contentful-paint': await this._audit(FirstContentfulPaint),
119
+ 'largest-contentful-paint': await this._audit(LargestContentfulPaint),
120
+ 'cumulative-layout-shift': await this._audit(CumulativeLayoutShift),
121
+ 'total-blocking-time': await this._audit(TotalBlockingTime),
122
+ interactive: await this._audit(InteractiveMetric)
123
+ };
124
+ if (!auditResults.interactive || !auditResults['cumulative-layout-shift'] || !auditResults['first-contentful-paint'] ||
125
+ !auditResults['largest-contentful-paint'] || !auditResults['speed-index'] || !auditResults['total-blocking-time']) {
126
+ log.info('One or multiple required metrics couldn\'t be found, setting performance score to: null');
127
+ return null;
128
+ }
129
+ const scores = defaultConfig.categories.performance.auditRefs.filter((auditRef) => auditRef.weight).map((auditRef) => ({
130
+ score: auditResults[auditRef.id].score,
131
+ weight: auditRef.weight,
132
+ }));
133
+ return ReportScoring.arithmeticMean(scores);
134
+ }
135
+ async _auditPWA(params, auditsToBeRun = Object.keys(PWA_AUDITS)) {
136
+ const audits = await Promise.all(Object.entries(PWA_AUDITS)
137
+ .filter(([name]) => auditsToBeRun.includes(name))
138
+ .map(async ([name, Audit]) => [name, await this._audit(Audit, params)]));
139
+ return {
140
+ passed: !audits.find(([, result]) => result.score < 1),
141
+ details: audits.reduce((details, [name, result]) => {
142
+ details[name] = result;
143
+ return details;
144
+ }, {})
145
+ };
146
+ }
147
+ }
@@ -0,0 +1,86 @@
1
+ import type { TraceEvent } from '@tracerbench/trace-event';
2
+ import type { CDPSession } from 'puppeteer-core/lib/esm/puppeteer/api/CDPSession.js';
3
+ import type { Page } from 'puppeteer-core/lib/esm/puppeteer/api/Page.js';
4
+ import type { TracingOptions } from 'puppeteer-core/lib/esm/puppeteer/cdp/Tracing.js';
5
+ import type { RequestPayload } from './handler/network.js';
6
+ import type { DevtoolsConfig, EnablePerformanceAuditsOptions, GathererDriver, PWAAudits } from './types.js';
7
+ export default class CommandHandler {
8
+ private _session;
9
+ private _page;
10
+ private _driver;
11
+ private _options;
12
+ private _browser;
13
+ private _isTracing;
14
+ private _networkHandler;
15
+ private _traceEvents?;
16
+ private _shouldRunPerformanceAudits;
17
+ private _cacheEnabled?;
18
+ private _cpuThrottling?;
19
+ private _networkThrottling?;
20
+ private _formFactor?;
21
+ private _traceGatherer?;
22
+ private _devtoolsGatherer?;
23
+ private _pwaGatherer?;
24
+ constructor(_session: CDPSession, _page: Page, _driver: GathererDriver, _options: DevtoolsConfig, _browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser);
25
+ /**
26
+ * Start tracing the browser. You can optionally pass in custom tracing categories and the
27
+ * sampling frequency.
28
+ */
29
+ startTracing({ categories, path, screenshots }?: TracingOptions): Promise<void>;
30
+ /**
31
+ * Stop tracing the browser.
32
+ */
33
+ endTracing(): Promise<TraceEvent[] | undefined>;
34
+ /**
35
+ * Returns the tracelogs that was captured within the tracing period.
36
+ * You can use this command to store the trace logs on the file system to analyse the trace
37
+ * via Chrome DevTools interface.
38
+ */
39
+ getTraceLogs(): TraceEvent[] | undefined;
40
+ /**
41
+ * Returns page weight information of the last page load.
42
+ */
43
+ getPageWeight(): {
44
+ pageWeight: number;
45
+ transferred: number;
46
+ requestCount: number;
47
+ details: {
48
+ Document?: RequestPayload | undefined;
49
+ Stylesheet?: RequestPayload | undefined;
50
+ Image?: RequestPayload | undefined;
51
+ Media?: RequestPayload | undefined;
52
+ Font?: RequestPayload | undefined;
53
+ Script?: RequestPayload | undefined;
54
+ TextTrack?: RequestPayload | undefined;
55
+ XHR?: RequestPayload | undefined;
56
+ Fetch?: RequestPayload | undefined;
57
+ Prefetch?: RequestPayload | undefined;
58
+ EventSource?: RequestPayload | undefined;
59
+ WebSocket?: RequestPayload | undefined;
60
+ Manifest?: RequestPayload | undefined;
61
+ SignedExchange?: RequestPayload | undefined;
62
+ Ping?: RequestPayload | undefined;
63
+ CSPViolationReport?: RequestPayload | undefined;
64
+ Preflight?: RequestPayload | undefined;
65
+ Other?: RequestPayload | undefined;
66
+ };
67
+ };
68
+ /**
69
+ * set flag to run performance audits for page transitions
70
+ */
71
+ enablePerformanceAudits({ networkThrottling, cpuThrottling, cacheEnabled, formFactor }?: EnablePerformanceAuditsOptions): void;
72
+ /**
73
+ * custom command to disable performance audits
74
+ */
75
+ disablePerformanceAudits(): void;
76
+ /**
77
+ * helper method to set throttling profile
78
+ */
79
+ setThrottlingProfile(networkThrottling?: "online" | "offline" | "GPRS" | "Regular 2G" | "Good 2G" | "Regular 3G" | "Good 3G" | "Regular 4G" | "DSL" | "Wifi", cpuThrottling?: number, cacheEnabled?: boolean): Promise<void>;
80
+ checkPWA(auditsToBeRun?: PWAAudits[]): Promise<import("./types.js").AuditResult>;
81
+ private _propagateWSEvents;
82
+ _initCommand(): Promise<void>;
83
+ _beforeCmd(commandName: string, params: any[]): Promise<void> | undefined;
84
+ _afterCmd(commandName: string): Promise<void> | undefined;
85
+ }
86
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oDAAoD,CAAA;AACpF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,8CAA8C,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAA;AAErF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAK1D,OAAO,KAAK,EACR,cAAc,EACd,8BAA8B,EAE9B,cAAc,EACd,SAAS,EACZ,MAAM,YAAY,CAAA;AAqBnB,MAAM,CAAC,OAAO,OAAO,cAAc;IAiB3B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IApBpB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,YAAY,CAAC,CAAc;IAEnC,OAAO,CAAC,2BAA2B,CAAQ;IAE3C,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,cAAc,CAAC,CAAQ;IAC/B,OAAO,CAAC,kBAAkB,CAAC,CAA6B;IACxD,OAAO,CAAC,WAAW,CAAC,CAAY;IAEhC,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,iBAAiB,CAAC,CAAkB;IAC5C,OAAO,CAAC,YAAY,CAAC,CAAa;gBAGtB,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,IAAI,EACX,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB;IA2B1E;;;OAGG;IACH,YAAY,CAAE,EACV,UAAuC,EACvC,IAAI,EACJ,WAAkB,EACrB,GAAE,cAAmB;IAUtB;;OAEG;IACG,UAAU;IAmBhB;;;;OAIG;IACH,YAAY;IAIZ;;OAEG;IACH,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;IAQb;;OAEG;IACH,uBAAuB,CAAE,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,GAAE,8BAAuD;IAgBhJ;;OAEG;IACH,wBAAwB;IAIxB;;OAEG;IACG,oBAAoB,CACtB,iBAAiB,sHAA2C,EAC5D,aAAa,GAAE,MAA6C,EAC5D,YAAY,GAAE,OAA6C;IAWzD,QAAQ,CAAE,aAAa,CAAC,EAAE,SAAS,EAAE;IAM3C,OAAO,CAAC,kBAAkB;IAkBpB,YAAY;IAWlB,UAAU,CAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE;IAiB9C,SAAS,CAAE,WAAW,EAAE,MAAM;CAmCjC"}