@wdio/nightwatch-devtools 1.2.0 → 1.4.0

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.
package/README.md CHANGED
@@ -82,8 +82,9 @@ module.exports = {
82
82
  |--------|------|---------|-------------|
83
83
  | `port` | `number` | `3000` | Port for the DevTools backend server. Auto-incremented if already in use. |
84
84
  | `hostname` | `string` | `'localhost'` | Hostname the backend server binds to. |
85
- | `screencast` | `ScreencastOptions` | `{ enabled: false }` | Session video recording (see [Screencast](#screencast)). |
85
+ | `screencast` | `ScreencastOptions` | `{ enabled: false }` | Session video recording — live mode only (see [Screencast](#screencast)). |
86
86
  | `bidi` | `boolean` | `false` | Opt into WebDriver BiDi capture for browser console + JS exceptions + network. Requires `webSocketUrl: true` in your capabilities and a BiDi-capable chromedriver. When attached, the per-command Chrome perf-log network path is gated off so requests don't duplicate. |
87
+ | `mode` | `'live' \| 'trace'` | `'live'` | `'live'` opens the DevTools UI window; `'trace'` skips the UI and writes a `trace-<sessionId>.zip` next to your `nightwatch.conf.cjs` at run end. See [Trace mode](../../README.md#-trace-mode-tracezip). |
87
88
 
88
89
  ```javascript
89
90
  globals: nightwatchDevtools({
@@ -71,6 +71,15 @@ async function attachLogInspector(driver, factory, sinks, log2) {
71
71
  return false;
72
72
  }
73
73
  }
74
+ var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
75
+ function bidiResponseTiming(timings, startTime, timestamp) {
76
+ if (timings && isFiniteNumber(timings.requestTime) && isFiniteNumber(timings.responseEnd) && timings.responseEnd > timings.requestTime) {
77
+ const time = Math.round(timings.responseEnd - timings.requestTime);
78
+ return { endTime: startTime + time, time };
79
+ }
80
+ const endTime = Number(timestamp ?? Date.now());
81
+ return { endTime, time: Math.max(0, endTime - startTime) };
82
+ }
74
83
  function handleBidiRequestSent(rawEvent, pending, sinks, log2) {
75
84
  const event = rawEvent;
76
85
  try {
@@ -101,14 +110,19 @@ function handleBidiResponseCompleted(rawEvent, pending, sinks, log2) {
101
110
  if (!previous) {
102
111
  return;
103
112
  }
113
+ const { endTime, time } = bidiResponseTiming(
114
+ event?.request?.timings,
115
+ previous.startTime,
116
+ event?.timestamp
117
+ );
104
118
  const finalized = {
105
119
  ...previous,
106
120
  status: Number(event?.response?.status) || previous.status,
107
121
  statusText: event?.response?.statusText ?? previous.statusText,
108
122
  responseHeaders: arrayHeadersToObject(event?.response?.headers),
109
123
  type: getRequestType(previous.url, event?.response?.mimeType),
110
- endTime: Number(event?.timestamp ?? Date.now()),
111
- time: Number(event?.timestamp ?? Date.now()) - previous.startTime,
124
+ endTime,
125
+ time,
112
126
  size: Number(event?.response?.bytesReceived) || void 0
113
127
  };
114
128
  pending.delete(requestId);
@@ -212,4 +226,4 @@ export {
212
226
  attachBidiHandlers2 as attachBidiHandlers,
213
227
  buildBidiSinks
214
228
  };
215
- //# sourceMappingURL=bidi-OH4ZFDN5.js.map
229
+ //# sourceMappingURL=bidi-FIHBBGT4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bidi.ts","../../core/src/bidi.ts"],"sourcesContent":["import logger from '@wdio/logger'\nimport {\n type BidiHandlerSinks,\n attachBidiHandlers as attachBidiHandlersCore\n} from '@wdio/devtools-core'\nimport type { SessionCapturer } from './session.js'\n\nconst log = logger('@wdio/nightwatch-devtools:bidi')\n\n/**\n * Nightwatch wrapper around the core BiDi attach helper. Nightwatch ships\n * selenium-webdriver under the hood (via chromedriver), so the same\n * `selenium-webdriver/bidi` inspectors selenium-devtools uses are available\n * whenever the user has set `webSocketUrl: true` in their capabilities.\n *\n * Opt-in via the plugin's `bidi: true` option. When attached, the per-command\n * Chrome performance-log network capture is gated off to avoid duplicate\n * entries in the dashboard.\n */\nexport async function attachBidiHandlers(\n driver: unknown,\n sinks: BidiHandlerSinks\n): Promise<boolean> {\n return attachBidiHandlersCore(driver, sinks, (level, message) =>\n log[level](message)\n )\n}\n\n/**\n * Build sinks that route BiDi events into the SessionCapturer's local arrays\n * and broadcast them upstream. Mirrors selenium-devtools' `buildBidiSinks` —\n * separate per-adapter because the SessionCapturer concrete types differ.\n */\nexport function buildBidiSinks(capturer: SessionCapturer): BidiHandlerSinks {\n return {\n pushConsoleLog: (entry) => {\n capturer.consoleLogs.push(entry)\n capturer.sendUpstream('consoleLogs', [entry])\n },\n pushNetworkRequest: (entry) => {\n capturer.networkRequests.push(entry)\n capturer.sendUpstream('networkRequests', [entry])\n },\n replaceNetworkRequest: (id, entry) => {\n const idx = capturer.networkRequests.findIndex(\n (r: { id?: string }) => r.id === id\n )\n if (idx !== -1) {\n capturer.networkRequests[idx] = entry\n } else {\n capturer.networkRequests.push(entry)\n }\n capturer.sendUpstream('networkRequests', [entry])\n }\n }\n}\n","import { createRequire } from 'node:module'\nimport type {\n ConsoleLog,\n LogLevel,\n NetworkRequest\n} from '@wdio/devtools-shared'\nimport {\n LOG_SOURCES,\n chromeLogLevelToLogLevel,\n type LogSource\n} from './console.js'\nimport { errorMessage } from './error.js'\nimport { getRequestType } from './net.js'\n\n/**\n * Generic sinks the BiDi handlers push into. Each adapter wires these to its\n * own SessionCapturer state — selenium's `buildBidiSinks` is the canonical\n * example; nightwatch can mirror the pattern when it wires up BiDi.\n */\nexport interface BidiHandlerSinks {\n pushConsoleLog: (entry: ConsoleLog) => void\n pushNetworkRequest: (entry: NetworkRequest) => void\n replaceNetworkRequest: (id: string, entry: NetworkRequest) => void\n}\n\n/**\n * Resolve a `selenium-webdriver/<subpath>` module from the user's install\n * (preferred) or the package's local install (fallback). Returns `null` if\n * neither resolves — caller should treat as \"BiDi not available on this\n * runtime\" and degrade gracefully.\n *\n * Used by both selenium-devtools and (when wired up) nightwatch-devtools —\n * both ship selenium-webdriver-style drivers under the hood.\n */\nexport function loadSeleniumSubmodule<T = unknown>(subpath: string): T | null {\n try {\n const userRequire = createRequire(`${process.cwd()}/`)\n return userRequire(`selenium-webdriver/${subpath}`) as T\n } catch {\n try {\n const localRequire = createRequire(import.meta.url)\n return localRequire(`selenium-webdriver/${subpath}`) as T\n } catch {\n return null\n }\n }\n}\n\ntype BidiLogger = (level: 'info' | 'warn', message: string) => void\ntype InspectorFactory = (driver: unknown) => Promise<unknown>\n\ninterface LogInspector {\n onConsoleEntry: (cb: (entry: unknown) => void) => Promise<void>\n onJavascriptException: (cb: (exc: unknown) => void) => Promise<void>\n}\n\ninterface NetworkInspector {\n beforeRequestSent: (cb: (e: unknown) => void) => Promise<void>\n responseCompleted: (cb: (e: unknown) => void) => Promise<void>\n}\n\nexport function handleBidiConsoleEntry(\n rawEntry: unknown,\n sinks: BidiHandlerSinks,\n log: BidiLogger\n): void {\n const entry = rawEntry as {\n level?: string\n type?: string\n text?: string\n message?: string\n timestamp?: number\n }\n try {\n const level = (entry?.level ?? entry?.type ?? 'info').toString()\n const text = entry?.text ?? entry?.message ?? ''\n sinks.pushConsoleLog({\n timestamp: Number(entry?.timestamp) || Date.now(),\n type: chromeLogLevelToLogLevel(level) as LogLevel,\n args: [text],\n source: LOG_SOURCES.BROWSER as LogSource\n })\n } catch (err) {\n log('warn', `onConsoleEntry handler threw: ${errorMessage(err)}`)\n }\n}\n\nexport function handleBidiJsException(\n rawExc: unknown,\n sinks: BidiHandlerSinks,\n log: BidiLogger\n): void {\n const exception = rawExc as { text?: string; message?: string }\n try {\n const text = exception?.text ?? exception?.message ?? String(rawExc)\n const trimmed = String(text).replace(/\\s+/g, ' ').slice(0, 200)\n log(\n 'warn',\n `🐛 JS error in page: ${trimmed}${String(text).length > 200 ? '…' : ''}`\n )\n sinks.pushConsoleLog({\n timestamp: Date.now(),\n type: 'error',\n args: [text],\n source: LOG_SOURCES.BROWSER as LogSource\n })\n } catch (err) {\n log('warn', `onJavascriptException handler threw: ${errorMessage(err)}`)\n }\n}\n\nasync function attachLogInspector(\n driver: unknown,\n factory: InspectorFactory,\n sinks: BidiHandlerSinks,\n log: BidiLogger\n): Promise<boolean> {\n try {\n const inspector = (await factory(driver)) as LogInspector\n await inspector.onConsoleEntry((e) => handleBidiConsoleEntry(e, sinks, log))\n await inspector.onJavascriptException((e) =>\n handleBidiJsException(e, sinks, log)\n )\n log('info', '✓ BiDi LogInspector attached (console + JS exceptions)')\n return true\n } catch (err) {\n log('warn', `BiDi LogInspector attach failed: ${errorMessage(err)}`)\n return false\n }\n}\n\n/** Subset of WebDriver BiDi `FetchTimingInfo` (selenium exposes these via\n * getters). Values are ms offsets from the request baseline `requestTime`\n * (usually 0), so `responseEnd - requestTime` is the request duration. */\ninterface FetchTimings {\n requestTime?: number\n responseEnd?: number\n}\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value)\n\ninterface BeforeRequestSentEvent {\n request?: {\n request?: string\n url?: string\n method?: string\n headers?: unknown\n timings?: FetchTimings\n }\n id?: string\n timestamp?: number\n}\n\ninterface ResponseCompletedEvent {\n request?: { request?: string; timings?: FetchTimings }\n id?: string\n timestamp?: number\n response?: {\n status?: number\n statusText?: string\n headers?: unknown\n mimeType?: string\n bytesReceived?: number\n }\n}\n\n/** Request duration (ms) from the browser's FetchTimingInfo, plus a derived\n * endTime anchored to `startTime`. The browser timings are immune to BiDi\n * events arriving batched in one tick (which collapses the event-level\n * `timestamp`/`Date.now()` to a single value and yields 0-duration requests).\n * Falls back to the timestamp diff only when timings are unavailable. */\nfunction bidiResponseTiming(\n timings: FetchTimings | undefined,\n startTime: number,\n timestamp?: number\n): { endTime: number; time: number } {\n if (\n timings &&\n isFiniteNumber(timings.requestTime) &&\n isFiniteNumber(timings.responseEnd) &&\n timings.responseEnd > timings.requestTime\n ) {\n const time = Math.round(timings.responseEnd - timings.requestTime)\n return { endTime: startTime + time, time }\n }\n const endTime = Number(timestamp ?? Date.now())\n return { endTime, time: Math.max(0, endTime - startTime) }\n}\n\nexport function handleBidiRequestSent(\n rawEvent: unknown,\n pending: Map<string, NetworkRequest>,\n sinks: BidiHandlerSinks,\n log: BidiLogger\n): void {\n const event = rawEvent as BeforeRequestSentEvent\n try {\n const requestId = String(event?.request?.request ?? event?.id ?? '')\n if (!requestId) {\n return\n }\n const entry: NetworkRequest = {\n id: requestId,\n url: event?.request?.url ?? '',\n method: event?.request?.method ?? 'GET',\n requestHeaders: arrayHeadersToObject(event?.request?.headers),\n timestamp: Date.now(),\n startTime: Number(event?.timestamp ?? Date.now()),\n type: getRequestType(event?.request?.url ?? '')\n }\n pending.set(requestId, entry)\n sinks.pushNetworkRequest(entry)\n } catch (err) {\n log('warn', `beforeRequestSent threw: ${errorMessage(err)}`)\n }\n}\n\nexport function handleBidiResponseCompleted(\n rawEvent: unknown,\n pending: Map<string, NetworkRequest>,\n sinks: BidiHandlerSinks,\n log: BidiLogger\n): void {\n const event = rawEvent as ResponseCompletedEvent\n try {\n const requestId = String(event?.request?.request ?? event?.id ?? '')\n const previous = pending.get(requestId)\n if (!previous) {\n return\n }\n const { endTime, time } = bidiResponseTiming(\n event?.request?.timings,\n previous.startTime,\n event?.timestamp\n )\n const finalized: NetworkRequest = {\n ...previous,\n status: Number(event?.response?.status) || previous.status,\n statusText: event?.response?.statusText ?? previous.statusText,\n responseHeaders: arrayHeadersToObject(event?.response?.headers),\n type: getRequestType(previous.url, event?.response?.mimeType),\n endTime,\n time,\n size: Number(event?.response?.bytesReceived) || undefined\n }\n pending.delete(requestId)\n sinks.replaceNetworkRequest(requestId, finalized)\n } catch (err) {\n log('warn', `responseCompleted threw: ${errorMessage(err)}`)\n }\n}\n\nasync function attachNetworkInspector(\n driver: unknown,\n factory: InspectorFactory,\n sinks: BidiHandlerSinks,\n log: BidiLogger\n): Promise<boolean> {\n try {\n const inspector = (await factory(driver)) as NetworkInspector\n const pending = new Map<string, NetworkRequest>()\n await inspector.beforeRequestSent((e) =>\n handleBidiRequestSent(e, pending, sinks, log)\n )\n await inspector.responseCompleted((e) =>\n handleBidiResponseCompleted(e, pending, sinks, log)\n )\n log('info', '✓ BiDi NetworkInspector attached (request + response)')\n return true\n } catch (err) {\n log('warn', `BiDi NetworkInspector attach failed: ${errorMessage(err)}`)\n return false\n }\n}\n\n/**\n * Attach the selenium-webdriver BiDi LogInspector + NetworkInspector to a\n * driver and route their events into the given sinks. Returns `true` when at\n * least one inspector connected — caller can disable the equivalent\n * script-injection collectors to avoid duplicates.\n *\n * Tolerant of older / non-BiDi runtimes: if either submodule fails to load\n * or the inspector factory throws (driver session doesn't have webSocketUrl\n * capability set, etc.), the corresponding stream is silently skipped and\n * the function returns false.\n *\n * @param onLog Optional callback for adapter-side logging. Receives ('info' |\n * 'warn', message) on lifecycle events. Default: silent — adapters wire their\n * own logger when they want visibility into BiDi attach state.\n */\nexport async function attachBidiHandlers(\n driver: unknown,\n sinks: BidiHandlerSinks,\n onLog?: (level: 'info' | 'warn', message: string) => void\n): Promise<boolean> {\n const log: BidiLogger = (level, message) => onLog?.(level, message)\n const logFactory =\n loadSeleniumSubmodule<InspectorFactory>('bidi/logInspector')\n const networkFactory = loadSeleniumSubmodule<InspectorFactory>(\n 'bidi/networkInspector'\n )\n\n let attached = 0\n if (typeof logFactory === 'function') {\n if (await attachLogInspector(driver, logFactory, sinks, log)) {\n attached++\n }\n } else {\n log('info', 'selenium-webdriver/bidi/logInspector not available — skipping')\n }\n if (typeof networkFactory === 'function') {\n if (await attachNetworkInspector(driver, networkFactory, sinks, log)) {\n attached++\n }\n } else {\n log(\n 'info',\n 'selenium-webdriver/bidi/networkInspector not available — skipping'\n )\n }\n return attached > 0\n}\n\n/**\n * Flatten BiDi's `Array<{name, value:{value|type}}>` header shape to a\n * lowercased `Record<string, string>`. Exported so adapter-side helpers can\n * reuse it for their own header normalization.\n */\nexport function arrayHeadersToObject(\n headers: unknown\n): Record<string, string> | undefined {\n if (!Array.isArray(headers)) {\n return undefined\n }\n const out: Record<string, string> = {}\n for (const h of headers as Array<{\n name?: string\n value?: string | { value?: string; type?: string }\n }>) {\n const name = String(h?.name ?? '').toLowerCase()\n if (!name) {\n continue\n }\n const v = h?.value\n out[name] =\n typeof v === 'string'\n ? v\n : typeof (v as { value?: string })?.value === 'string'\n ? (v as { value: string }).value\n : JSON.stringify(v ?? '')\n }\n return out\n}\n"],"mappings":"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","names":["log","attachBidiHandlers"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ScreencastOptions } from '@wdio/devtools-shared';
1
+ import { ScreencastOptions, DevToolsMode, TraceFormat, TraceGranularity } from '@wdio/devtools-shared';
2
2
 
3
3
  /** Nightwatch `eventHub` shape — only `runner` + `on()` are documented; the
4
4
  * rest of the public surface is `unknown` to us. */
@@ -25,6 +25,15 @@ interface DevToolsOptions {
25
25
  * entries. Defaults to `false` — opt-in.
26
26
  */
27
27
  bidi?: boolean;
28
+ /** `live` (default) launches the DevTools UI; `trace` skips it. */
29
+ mode?: DevToolsMode;
30
+ /** Trace output layout — `zip` (default) writes a single archive,
31
+ * `ndjson-directory` unpacks into `trace-<id>/`. Only applies in trace mode. */
32
+ traceFormat?: TraceFormat;
33
+ /** Trace output granularity — `session` (default) writes one trace per
34
+ * worker session; `spec` writes one trace per spec file. Only applies in
35
+ * trace mode. */
36
+ traceGranularity?: TraceGranularity;
28
37
  }
29
38
  interface NightwatchBrowser {
30
39
  url: (url: string) => Promise<unknown>;