@testrelic/maestro-analytics 1.1.0 → 1.2.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/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { TestStatus, CloudReporterOptions, ReportMode, CloudConfig, TimelineEntry, Summary, TestRunReport, AuthMode, GitMetadata, TimelineStep, CIMetadata } from '@testrelic/core';
1
+ import { TestStatus, CloudReporterOptions, ReportMode, CloudConfig, ApiCallRecord, TimelineEntry, Summary, TestRunReport, AuthMode, GitMetadata, TimelineStep, CIMetadata } from '@testrelic/core';
2
2
  export { ActionCategory, ActionStep, ArtifactRunManifest, AuthMode, AuthState, CIMetadata, CIProvider, CloudConfig, CloudReporterOptions, ConsoleLogEntry, ConsoleLogLevel, FailureDiagnostic, GitMetadata, MergeOptions, QueueEntry, ReportMode, StreamingReportSummary, Summary, TestArtifacts, TestDetailData, TestIndexEntry, TestResult, TestRunReport, TestStatus, TimelineEntry, TimelineStep, UploadStrategy } from '@testrelic/core';
3
3
  export { mergeReports, mergeReportsFromDirectory } from './merge.cjs';
4
4
 
@@ -11,6 +11,55 @@ export { mergeReports, mergeReportsFromDirectory } from './merge.cjs';
11
11
  */
12
12
 
13
13
  type MaestroPlatform = 'android' | 'ios' | 'web' | 'unknown';
14
+ /**
15
+ * Network capture configuration. See `network-proxy.ts` and `parsers/har-parser.ts`.
16
+ *
17
+ * Maestro is a black-box UI driver — it can't intercept HTTP from inside the
18
+ * mobile app the way Playwright can. Two strategies are supported:
19
+ *
20
+ * - `mitmproxy` (auto-spawn): SDK launches `mitmdump` with a bundled addon
21
+ * that writes redacted ApiCallRecord JSONL. Requires `mitmdump` on PATH
22
+ * and a configured proxy / CA on the device.
23
+ * - `har` (user-supplied): User produces a HAR file with their own proxy
24
+ * (Charles, Proxyman, mitmweb, etc.) and points the SDK at it.
25
+ */
26
+ interface NetworkCaptureConfig {
27
+ /** When true, attempt to spawn mitmproxy and inject proxy settings into the device. Default: false. */
28
+ readonly enabled?: boolean;
29
+ /** Proxy listen port. Default: 8080. */
30
+ readonly proxyPort?: number;
31
+ /** Proxy listen host. Default: 127.0.0.1. */
32
+ readonly proxyHost?: string;
33
+ /** Path to a pre-generated HAR file to import instead of spawning a proxy. */
34
+ readonly harPath?: string;
35
+ /** Override the directory where mitmproxy writes its JSONL output. Default: `<outputDir>/network`. */
36
+ readonly outputDir?: string;
37
+ /** Skip auto-installing the mitmproxy CA on the device. Useful when the user pre-installed it. */
38
+ readonly skipCertInstall?: boolean;
39
+ /** Only capture calls whose URL matches one of these patterns (string substring or RegExp). */
40
+ readonly includeUrls?: (string | RegExp)[];
41
+ /** Exclude calls matching these patterns. Takes precedence over `includeUrls`. */
42
+ readonly excludeUrls?: (string | RegExp)[];
43
+ /** Header names whose values are replaced with "[REDACTED]". Case-insensitive. */
44
+ readonly redactHeaders?: string[];
45
+ /** Body field names whose values are replaced with "[REDACTED]" at any JSON depth. */
46
+ readonly redactBodyFields?: string[];
47
+ /** Maximum body size to capture (bytes). Larger bodies are truncated. Default: 1 MiB. */
48
+ readonly maxBodyBytes?: number;
49
+ }
50
+ interface ResolvedNetworkCaptureConfig {
51
+ readonly enabled: boolean;
52
+ readonly proxyPort: number;
53
+ readonly proxyHost: string;
54
+ readonly harPath: string | null;
55
+ readonly outputDir: string | null;
56
+ readonly skipCertInstall: boolean;
57
+ readonly includeUrls: readonly (string | RegExp)[];
58
+ readonly excludeUrls: readonly (string | RegExp)[];
59
+ readonly redactHeaders: readonly string[];
60
+ readonly redactBodyFields: readonly string[];
61
+ readonly maxBodyBytes: number;
62
+ }
14
63
  interface MaestroReporterConfig {
15
64
  readonly outputPath?: string;
16
65
  readonly htmlReportPath?: string;
@@ -26,6 +75,7 @@ interface MaestroReporterConfig {
26
75
  readonly cloud?: CloudReporterOptions;
27
76
  readonly reportMode?: ReportMode;
28
77
  readonly quiet?: boolean;
78
+ readonly network?: NetworkCaptureConfig;
29
79
  }
30
80
  interface ResolvedMaestroConfig {
31
81
  readonly outputPath: string;
@@ -42,6 +92,7 @@ interface ResolvedMaestroConfig {
42
92
  readonly cloud: CloudConfig | null;
43
93
  readonly reportMode: ReportMode;
44
94
  readonly quiet: boolean;
95
+ readonly network: ResolvedNetworkCaptureConfig;
45
96
  }
46
97
  interface JUnitProperty {
47
98
  readonly name: string;
@@ -87,7 +138,35 @@ interface MaestroCommandStep {
87
138
  readonly timestamp: string;
88
139
  readonly selector?: string;
89
140
  readonly error?: string;
141
+ /**
142
+ * Raw passthrough of Maestro's metadata block (status / timestamp / duration / sequenceNumber).
143
+ * Kept separate from `details` because consumers like report-orchestrator depend on
144
+ * specific Maestro-internal keys (e.g. `metadata.path` for `startRecording`).
145
+ */
90
146
  readonly metadata?: Record<string, unknown>;
147
+ /**
148
+ * Extracted human-relevant command parameters surfaced in the timeline.
149
+ * Examples:
150
+ * inputText → { text: "<typed value>" }
151
+ * swipe → { direction: "UP", start: "0,0", end: "0,500", duration: 300 }
152
+ * setLocation → { latitude: 37.7749, longitude: -122.4194 }
153
+ * pressKey → { key: "BACK" }
154
+ * assertWithAI → { assertion: "<prompt>" }
155
+ * runScript → { path: "scripts/foo.js" } or { script: "<truncated source>" }
156
+ *
157
+ * Values are post-redaction (see api-redactor / details-redactor).
158
+ */
159
+ readonly details?: Record<string, unknown>;
160
+ /**
161
+ * Sort tiebreaker when two commands share a timestamp (Maestro emits sub-ms timing
162
+ * for fast back-to-back commands). Source: Maestro's metadata.sequenceNumber.
163
+ */
164
+ readonly sequenceNumber?: number;
165
+ /**
166
+ * Sub-commands when this step wraps a flow-control block (`retry`, `repeat`, `runFlow`).
167
+ * Empty / undefined for leaf commands.
168
+ */
169
+ readonly children?: MaestroCommandStep[];
91
170
  }
92
171
  interface MaestroFlowMetadata {
93
172
  readonly appId: string | null;
@@ -169,6 +248,7 @@ interface MaestroTestOptions {
169
248
  readonly env?: Record<string, string>;
170
249
  readonly quiet?: boolean;
171
250
  readonly maestroArgs?: string[];
251
+ readonly network?: NetworkCaptureConfig;
172
252
  }
173
253
  interface MaestroReportOptions {
174
254
  readonly junitPath?: string;
@@ -261,8 +341,13 @@ declare function getArtifactStats(artifacts: CollectedArtifacts): Record<string,
261
341
  * Maps Maestro data to the @testrelic/core TimelineEntry shape.
262
342
  */
263
343
 
264
- declare function buildTimelineEntry(flow: MaestroFlowResult): TimelineEntry;
265
- declare function buildTimeline(flows: MaestroFlowResult[]): TimelineEntry[];
344
+ /**
345
+ * Build a TimelineEntry for a single flow. Optionally accepts an
346
+ * `apiCallsByFlow` map keyed by `testId` (`${flowFile}::${flowName}`) so the
347
+ * orchestrator can plumb network capture results in without re-shaping flows.
348
+ */
349
+ declare function buildTimelineEntry(flow: MaestroFlowResult, apiCallsByFlow?: ReadonlyMap<string, readonly ApiCallRecord[]>): TimelineEntry;
350
+ declare function buildTimeline(flows: MaestroFlowResult[], apiCallsByFlow?: ReadonlyMap<string, readonly ApiCallRecord[]>): TimelineEntry[];
266
351
 
267
352
  /**
268
353
  * Computes Summary stats from TimelineEntry arrays.
@@ -311,9 +396,15 @@ interface MaestroRunResult {
311
396
  readonly debugOutputDir: string;
312
397
  readonly stdout: string;
313
398
  readonly stderr: string;
399
+ /** Directory where the network proxy wrote JSONL records (null when capture was disabled or failed to start). */
400
+ readonly networkJsonlDir: string | null;
314
401
  }
315
402
  declare function buildMaestroArgs(options: MaestroTestOptions, tempDir: string): string[];
316
- declare function runMaestro(options: MaestroTestOptions): Promise<MaestroRunResult>;
403
+ interface RunMaestroExtras {
404
+ /** Optional network-capture config. When `enabled`, mitmproxy is spawned and the device is configured to route through it. */
405
+ readonly network?: ResolvedNetworkCaptureConfig;
406
+ }
407
+ declare function runMaestro(options: MaestroTestOptions, extras?: RunMaestroExtras): Promise<MaestroRunResult>;
317
408
 
318
409
  /**
319
410
  * Report orchestrator — ties all parsers together to produce
@@ -335,6 +426,12 @@ interface OrchestratorInput {
335
426
  * rely on heuristic detection that may return 'unknown'.
336
427
  */
337
428
  readonly platform?: MaestroPlatform;
429
+ /**
430
+ * Directory containing JSONL files emitted by `network-proxy.ts` (mitmproxy
431
+ * addon). When omitted, the orchestrator still picks up `config.network.harPath`
432
+ * if set. Unrelated to Maestro's own debug output.
433
+ */
434
+ readonly networkJsonlDir?: string | null;
338
435
  }
339
436
  interface OrchestratorResult {
340
437
  readonly report: TestRunReport;
@@ -419,6 +516,13 @@ interface TestResultForUpload {
419
516
  readonly timestamp: string;
420
517
  readonly source?: string | null;
421
518
  }>;
519
+ /**
520
+ * Per-flow captured API calls. The cloud platform's `normalizeApiCall` (in
521
+ * `server/src/utils/artifact-normalizer.ts`) accepts this shape directly and
522
+ * stores it as `network.json`. Surfaced in the Test Detail Network panel and
523
+ * via Ask AI's `query_network_logs` tool — works for free, no cloud changes.
524
+ */
525
+ readonly apiCalls?: readonly ApiCallRecord[];
422
526
  }
423
527
  interface RunUploadPayload {
424
528
  readonly runId: string;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { TestStatus, CloudReporterOptions, ReportMode, CloudConfig, TimelineEntry, Summary, TestRunReport, AuthMode, GitMetadata, TimelineStep, CIMetadata } from '@testrelic/core';
1
+ import { TestStatus, CloudReporterOptions, ReportMode, CloudConfig, ApiCallRecord, TimelineEntry, Summary, TestRunReport, AuthMode, GitMetadata, TimelineStep, CIMetadata } from '@testrelic/core';
2
2
  export { ActionCategory, ActionStep, ArtifactRunManifest, AuthMode, AuthState, CIMetadata, CIProvider, CloudConfig, CloudReporterOptions, ConsoleLogEntry, ConsoleLogLevel, FailureDiagnostic, GitMetadata, MergeOptions, QueueEntry, ReportMode, StreamingReportSummary, Summary, TestArtifacts, TestDetailData, TestIndexEntry, TestResult, TestRunReport, TestStatus, TimelineEntry, TimelineStep, UploadStrategy } from '@testrelic/core';
3
3
  export { mergeReports, mergeReportsFromDirectory } from './merge.js';
4
4
 
@@ -11,6 +11,55 @@ export { mergeReports, mergeReportsFromDirectory } from './merge.js';
11
11
  */
12
12
 
13
13
  type MaestroPlatform = 'android' | 'ios' | 'web' | 'unknown';
14
+ /**
15
+ * Network capture configuration. See `network-proxy.ts` and `parsers/har-parser.ts`.
16
+ *
17
+ * Maestro is a black-box UI driver — it can't intercept HTTP from inside the
18
+ * mobile app the way Playwright can. Two strategies are supported:
19
+ *
20
+ * - `mitmproxy` (auto-spawn): SDK launches `mitmdump` with a bundled addon
21
+ * that writes redacted ApiCallRecord JSONL. Requires `mitmdump` on PATH
22
+ * and a configured proxy / CA on the device.
23
+ * - `har` (user-supplied): User produces a HAR file with their own proxy
24
+ * (Charles, Proxyman, mitmweb, etc.) and points the SDK at it.
25
+ */
26
+ interface NetworkCaptureConfig {
27
+ /** When true, attempt to spawn mitmproxy and inject proxy settings into the device. Default: false. */
28
+ readonly enabled?: boolean;
29
+ /** Proxy listen port. Default: 8080. */
30
+ readonly proxyPort?: number;
31
+ /** Proxy listen host. Default: 127.0.0.1. */
32
+ readonly proxyHost?: string;
33
+ /** Path to a pre-generated HAR file to import instead of spawning a proxy. */
34
+ readonly harPath?: string;
35
+ /** Override the directory where mitmproxy writes its JSONL output. Default: `<outputDir>/network`. */
36
+ readonly outputDir?: string;
37
+ /** Skip auto-installing the mitmproxy CA on the device. Useful when the user pre-installed it. */
38
+ readonly skipCertInstall?: boolean;
39
+ /** Only capture calls whose URL matches one of these patterns (string substring or RegExp). */
40
+ readonly includeUrls?: (string | RegExp)[];
41
+ /** Exclude calls matching these patterns. Takes precedence over `includeUrls`. */
42
+ readonly excludeUrls?: (string | RegExp)[];
43
+ /** Header names whose values are replaced with "[REDACTED]". Case-insensitive. */
44
+ readonly redactHeaders?: string[];
45
+ /** Body field names whose values are replaced with "[REDACTED]" at any JSON depth. */
46
+ readonly redactBodyFields?: string[];
47
+ /** Maximum body size to capture (bytes). Larger bodies are truncated. Default: 1 MiB. */
48
+ readonly maxBodyBytes?: number;
49
+ }
50
+ interface ResolvedNetworkCaptureConfig {
51
+ readonly enabled: boolean;
52
+ readonly proxyPort: number;
53
+ readonly proxyHost: string;
54
+ readonly harPath: string | null;
55
+ readonly outputDir: string | null;
56
+ readonly skipCertInstall: boolean;
57
+ readonly includeUrls: readonly (string | RegExp)[];
58
+ readonly excludeUrls: readonly (string | RegExp)[];
59
+ readonly redactHeaders: readonly string[];
60
+ readonly redactBodyFields: readonly string[];
61
+ readonly maxBodyBytes: number;
62
+ }
14
63
  interface MaestroReporterConfig {
15
64
  readonly outputPath?: string;
16
65
  readonly htmlReportPath?: string;
@@ -26,6 +75,7 @@ interface MaestroReporterConfig {
26
75
  readonly cloud?: CloudReporterOptions;
27
76
  readonly reportMode?: ReportMode;
28
77
  readonly quiet?: boolean;
78
+ readonly network?: NetworkCaptureConfig;
29
79
  }
30
80
  interface ResolvedMaestroConfig {
31
81
  readonly outputPath: string;
@@ -42,6 +92,7 @@ interface ResolvedMaestroConfig {
42
92
  readonly cloud: CloudConfig | null;
43
93
  readonly reportMode: ReportMode;
44
94
  readonly quiet: boolean;
95
+ readonly network: ResolvedNetworkCaptureConfig;
45
96
  }
46
97
  interface JUnitProperty {
47
98
  readonly name: string;
@@ -87,7 +138,35 @@ interface MaestroCommandStep {
87
138
  readonly timestamp: string;
88
139
  readonly selector?: string;
89
140
  readonly error?: string;
141
+ /**
142
+ * Raw passthrough of Maestro's metadata block (status / timestamp / duration / sequenceNumber).
143
+ * Kept separate from `details` because consumers like report-orchestrator depend on
144
+ * specific Maestro-internal keys (e.g. `metadata.path` for `startRecording`).
145
+ */
90
146
  readonly metadata?: Record<string, unknown>;
147
+ /**
148
+ * Extracted human-relevant command parameters surfaced in the timeline.
149
+ * Examples:
150
+ * inputText → { text: "<typed value>" }
151
+ * swipe → { direction: "UP", start: "0,0", end: "0,500", duration: 300 }
152
+ * setLocation → { latitude: 37.7749, longitude: -122.4194 }
153
+ * pressKey → { key: "BACK" }
154
+ * assertWithAI → { assertion: "<prompt>" }
155
+ * runScript → { path: "scripts/foo.js" } or { script: "<truncated source>" }
156
+ *
157
+ * Values are post-redaction (see api-redactor / details-redactor).
158
+ */
159
+ readonly details?: Record<string, unknown>;
160
+ /**
161
+ * Sort tiebreaker when two commands share a timestamp (Maestro emits sub-ms timing
162
+ * for fast back-to-back commands). Source: Maestro's metadata.sequenceNumber.
163
+ */
164
+ readonly sequenceNumber?: number;
165
+ /**
166
+ * Sub-commands when this step wraps a flow-control block (`retry`, `repeat`, `runFlow`).
167
+ * Empty / undefined for leaf commands.
168
+ */
169
+ readonly children?: MaestroCommandStep[];
91
170
  }
92
171
  interface MaestroFlowMetadata {
93
172
  readonly appId: string | null;
@@ -169,6 +248,7 @@ interface MaestroTestOptions {
169
248
  readonly env?: Record<string, string>;
170
249
  readonly quiet?: boolean;
171
250
  readonly maestroArgs?: string[];
251
+ readonly network?: NetworkCaptureConfig;
172
252
  }
173
253
  interface MaestroReportOptions {
174
254
  readonly junitPath?: string;
@@ -261,8 +341,13 @@ declare function getArtifactStats(artifacts: CollectedArtifacts): Record<string,
261
341
  * Maps Maestro data to the @testrelic/core TimelineEntry shape.
262
342
  */
263
343
 
264
- declare function buildTimelineEntry(flow: MaestroFlowResult): TimelineEntry;
265
- declare function buildTimeline(flows: MaestroFlowResult[]): TimelineEntry[];
344
+ /**
345
+ * Build a TimelineEntry for a single flow. Optionally accepts an
346
+ * `apiCallsByFlow` map keyed by `testId` (`${flowFile}::${flowName}`) so the
347
+ * orchestrator can plumb network capture results in without re-shaping flows.
348
+ */
349
+ declare function buildTimelineEntry(flow: MaestroFlowResult, apiCallsByFlow?: ReadonlyMap<string, readonly ApiCallRecord[]>): TimelineEntry;
350
+ declare function buildTimeline(flows: MaestroFlowResult[], apiCallsByFlow?: ReadonlyMap<string, readonly ApiCallRecord[]>): TimelineEntry[];
266
351
 
267
352
  /**
268
353
  * Computes Summary stats from TimelineEntry arrays.
@@ -311,9 +396,15 @@ interface MaestroRunResult {
311
396
  readonly debugOutputDir: string;
312
397
  readonly stdout: string;
313
398
  readonly stderr: string;
399
+ /** Directory where the network proxy wrote JSONL records (null when capture was disabled or failed to start). */
400
+ readonly networkJsonlDir: string | null;
314
401
  }
315
402
  declare function buildMaestroArgs(options: MaestroTestOptions, tempDir: string): string[];
316
- declare function runMaestro(options: MaestroTestOptions): Promise<MaestroRunResult>;
403
+ interface RunMaestroExtras {
404
+ /** Optional network-capture config. When `enabled`, mitmproxy is spawned and the device is configured to route through it. */
405
+ readonly network?: ResolvedNetworkCaptureConfig;
406
+ }
407
+ declare function runMaestro(options: MaestroTestOptions, extras?: RunMaestroExtras): Promise<MaestroRunResult>;
317
408
 
318
409
  /**
319
410
  * Report orchestrator — ties all parsers together to produce
@@ -335,6 +426,12 @@ interface OrchestratorInput {
335
426
  * rely on heuristic detection that may return 'unknown'.
336
427
  */
337
428
  readonly platform?: MaestroPlatform;
429
+ /**
430
+ * Directory containing JSONL files emitted by `network-proxy.ts` (mitmproxy
431
+ * addon). When omitted, the orchestrator still picks up `config.network.harPath`
432
+ * if set. Unrelated to Maestro's own debug output.
433
+ */
434
+ readonly networkJsonlDir?: string | null;
338
435
  }
339
436
  interface OrchestratorResult {
340
437
  readonly report: TestRunReport;
@@ -419,6 +516,13 @@ interface TestResultForUpload {
419
516
  readonly timestamp: string;
420
517
  readonly source?: string | null;
421
518
  }>;
519
+ /**
520
+ * Per-flow captured API calls. The cloud platform's `normalizeApiCall` (in
521
+ * `server/src/utils/artifact-normalizer.ts`) accepts this shape directly and
522
+ * stores it as `network.json`. Surfaced in the Test Detail Network panel and
523
+ * via Ask AI's `query_network_logs` tool — works for free, no cloud changes.
524
+ */
525
+ readonly apiCalls?: readonly ApiCallRecord[];
422
526
  }
423
527
  interface RunUploadPayload {
424
528
  readonly runId: string;