@lokalise/playwright-reporters 1.8.1 → 1.9.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 +1 -0
- package/dist/analytics/elastic.js +7 -0
- package/dist/analytics/report.types.d.ts +15 -0
- package/dist/analytics/reporter.js +14 -0
- package/dist/analytics/transform.d.ts +1 -0
- package/dist/datadog/datadog.d.ts +25 -0
- package/dist/datadog/datadog.js +86 -0
- package/dist/datadog/index.d.ts +2 -0
- package/dist/datadog/index.js +9 -0
- package/dist/datadog/report.types.d.ts +175 -0
- package/dist/datadog/report.types.js +9 -0
- package/dist/datadog/reporter.d.ts +35 -0
- package/dist/datadog/reporter.js +296 -0
- package/dist/datadog/tests/e2e/browser.test.d.ts +1 -0
- package/dist/datadog/tests/e2e/browser.test.js +49 -0
- package/dist/datadog/tests/e2e/sample.test.d.ts +1 -0
- package/dist/datadog/tests/e2e/sample.test.js +69 -0
- package/dist/datadog/transform.d.ts +26 -0
- package/dist/datadog/transform.js +185 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +36 -23
- package/dist/permissions/elastic.js +2 -0
- package/dist/permissions/reporter.js +4 -0
- package/dist/retry/reporter.js +7 -0
- package/dist/stepDuration/reporter.js +3 -0
- package/dist/timeline/reporter.js +2 -0
- package/dist/translation/elastic.js +2 -0
- package/dist/translation/reporter.js +3 -0
- package/dist/translation/tests/transform.test.js +17 -7
- package/package.json +26 -19
package/README.md
CHANGED
|
@@ -4,6 +4,13 @@ exports.Elastic = void 0;
|
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
5
|
const logger_1 = require("./logger");
|
|
6
6
|
class Elastic {
|
|
7
|
+
request;
|
|
8
|
+
flakyTestIndex;
|
|
9
|
+
failedTestIndex;
|
|
10
|
+
testRunIndex;
|
|
11
|
+
browserUsageIndex;
|
|
12
|
+
elasticUrl;
|
|
13
|
+
elasticToken;
|
|
7
14
|
constructor(analyticsConfig) {
|
|
8
15
|
this.flakyTestIndex = analyticsConfig.flakyTestIndex;
|
|
9
16
|
this.failedTestIndex = analyticsConfig.failedTestIndex;
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import { type TestStatus } from '@playwright/test/reporter';
|
|
2
2
|
import type { ElasticConfig } from './elastic';
|
|
3
|
+
/**
|
|
4
|
+
* CI/CD context information for test runs
|
|
5
|
+
*/
|
|
6
|
+
export interface CIContext {
|
|
7
|
+
/** Git branch name */
|
|
8
|
+
branchName?: string;
|
|
9
|
+
/** Git commit SHA */
|
|
10
|
+
commitSha?: string;
|
|
11
|
+
/** Pull request number */
|
|
12
|
+
prNumber?: string;
|
|
13
|
+
/** CI job identifier */
|
|
14
|
+
ciJobId?: string;
|
|
15
|
+
/** What triggered the run (push, pr, schedule, manual) */
|
|
16
|
+
triggeredBy?: string;
|
|
17
|
+
}
|
|
3
18
|
export interface TestAnalyticsData {
|
|
4
19
|
timestamp: number;
|
|
5
20
|
name: string;
|
|
@@ -8,6 +8,20 @@ const helpers_1 = require("./helpers");
|
|
|
8
8
|
const transform_1 = require("./transform");
|
|
9
9
|
// eslint-disable-next-line import/no-default-export
|
|
10
10
|
class AnalyticsReporter {
|
|
11
|
+
listOfNonPassingTests;
|
|
12
|
+
listOfFlakyTests;
|
|
13
|
+
browserCreationTimes;
|
|
14
|
+
browserUsage;
|
|
15
|
+
elastic;
|
|
16
|
+
runStartTime;
|
|
17
|
+
runEndTime;
|
|
18
|
+
numberOfTests;
|
|
19
|
+
testRunId;
|
|
20
|
+
projectNames;
|
|
21
|
+
testOwnerCount;
|
|
22
|
+
options;
|
|
23
|
+
isMainPREnv;
|
|
24
|
+
workerCount;
|
|
11
25
|
constructor(options) {
|
|
12
26
|
this.options = options;
|
|
13
27
|
this.listOfNonPassingTests = [];
|
|
@@ -7,6 +7,7 @@ export declare const calculateHooksDuration: (steps: TestStep[], hook: "before"
|
|
|
7
7
|
export declare const getTeamNames: (test: TestCase) => {
|
|
8
8
|
type: string;
|
|
9
9
|
description?: string;
|
|
10
|
+
location?: import("playwright/types/test").Location;
|
|
10
11
|
}[];
|
|
11
12
|
export declare const formFailedTestData: (test: TestCase, result: TestResult, testRunId: string, prenvId?: string) => {
|
|
12
13
|
prenvId?: string | undefined;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DatadogMetricsPayload, DatadogReporterOptions } from './report.types';
|
|
2
|
+
/**
|
|
3
|
+
* Datadog API client for submitting metrics
|
|
4
|
+
*/
|
|
5
|
+
export declare class Datadog {
|
|
6
|
+
private request;
|
|
7
|
+
private readonly apiKey;
|
|
8
|
+
private readonly site;
|
|
9
|
+
private readonly debug;
|
|
10
|
+
constructor(options: Pick<DatadogReporterOptions, 'apiKey' | 'site' | 'debug'>);
|
|
11
|
+
private log;
|
|
12
|
+
/**
|
|
13
|
+
* Initialize the Playwright request context for API calls
|
|
14
|
+
*/
|
|
15
|
+
setNativeRequestContext(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Submit metrics to Datadog Metrics API v2
|
|
18
|
+
* @see https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
|
|
19
|
+
*/
|
|
20
|
+
submitMetrics(payload: DatadogMetricsPayload): Promise<boolean>;
|
|
21
|
+
/**
|
|
22
|
+
* Close the request context
|
|
23
|
+
*/
|
|
24
|
+
dispose(): Promise<void>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Datadog = void 0;
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
/**
|
|
6
|
+
* Returns the Datadog API endpoint for the given site
|
|
7
|
+
*/
|
|
8
|
+
const getApiEndpoint = (site) => {
|
|
9
|
+
const endpoints = {
|
|
10
|
+
'datadoghq.com': 'https://api.datadoghq.com',
|
|
11
|
+
'datadoghq.eu': 'https://api.datadoghq.eu',
|
|
12
|
+
'us3.datadoghq.com': 'https://api.us3.datadoghq.com',
|
|
13
|
+
'us5.datadoghq.com': 'https://api.us5.datadoghq.com',
|
|
14
|
+
'ap1.datadoghq.com': 'https://api.ap1.datadoghq.com',
|
|
15
|
+
'ddog-gov.com': 'https://api.ddog-gov.com',
|
|
16
|
+
};
|
|
17
|
+
return endpoints[site];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Datadog API client for submitting metrics
|
|
21
|
+
*/
|
|
22
|
+
class Datadog {
|
|
23
|
+
request;
|
|
24
|
+
apiKey;
|
|
25
|
+
site;
|
|
26
|
+
debug;
|
|
27
|
+
constructor(options) {
|
|
28
|
+
this.apiKey = options.apiKey;
|
|
29
|
+
this.site = options.site ?? 'datadoghq.eu';
|
|
30
|
+
this.debug = options.debug ?? false;
|
|
31
|
+
}
|
|
32
|
+
log(message, data) {
|
|
33
|
+
if (this.debug) {
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
35
|
+
console.log(message, data !== undefined ? JSON.stringify(data, null, 2) : '');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Initialize the Playwright request context for API calls
|
|
40
|
+
*/
|
|
41
|
+
async setNativeRequestContext() {
|
|
42
|
+
this.request = await test_1.request.newContext({
|
|
43
|
+
baseURL: getApiEndpoint(this.site),
|
|
44
|
+
extraHTTPHeaders: {
|
|
45
|
+
'DD-API-KEY': this.apiKey,
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Submit metrics to Datadog Metrics API v2
|
|
52
|
+
* @see https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
|
|
53
|
+
*/
|
|
54
|
+
async submitMetrics(payload) {
|
|
55
|
+
try {
|
|
56
|
+
if (!this.request) {
|
|
57
|
+
// eslint-disable-next-line no-console
|
|
58
|
+
console.error('[Datadog] Request context not initialized. Call setNativeRequestContext first.');
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
this.log('[Datadog] Submitting metrics:', payload);
|
|
62
|
+
const response = await this.request.post('/api/v2/series', { data: payload });
|
|
63
|
+
if (!response.ok()) {
|
|
64
|
+
// eslint-disable-next-line no-console
|
|
65
|
+
console.error(`[Datadog] Failed to submit metrics: ${response.status()} - ${await response.text()}`);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
this.log(`[Datadog] Successfully submitted ${payload.series.length} metric series`);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
// eslint-disable-next-line no-console
|
|
73
|
+
console.error('[Datadog] Error submitting metrics:', error);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Close the request context
|
|
79
|
+
*/
|
|
80
|
+
async dispose() {
|
|
81
|
+
if (this.request) {
|
|
82
|
+
await this.request.dispose();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.Datadog = Datadog;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.defineDatadogReporterConfig = exports.DatadogReporter = void 0;
|
|
7
|
+
var reporter_1 = require("./reporter");
|
|
8
|
+
Object.defineProperty(exports, "DatadogReporter", { enumerable: true, get: function () { return __importDefault(reporter_1).default; } });
|
|
9
|
+
Object.defineProperty(exports, "defineDatadogReporterConfig", { enumerable: true, get: function () { return reporter_1.defineDatadogReporterConfig; } });
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import type { CIContext } from '../analytics/report.types';
|
|
2
|
+
/**
|
|
3
|
+
* Datadog site endpoints for different regions
|
|
4
|
+
*/
|
|
5
|
+
export type DatadogSite = 'datadoghq.com' | 'datadoghq.eu' | 'us3.datadoghq.com' | 'us5.datadoghq.com' | 'ap1.datadoghq.com' | 'ddog-gov.com';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration options for the Datadog reporter
|
|
8
|
+
*/
|
|
9
|
+
export type DatadogReporterOptions = {
|
|
10
|
+
/**
|
|
11
|
+
* Datadog API key for authentication.
|
|
12
|
+
* Can also be set via DD_API_KEY environment variable.
|
|
13
|
+
*/
|
|
14
|
+
apiKey: string;
|
|
15
|
+
/**
|
|
16
|
+
* Datadog site/region endpoint.
|
|
17
|
+
* @default 'datadoghq.eu'
|
|
18
|
+
*/
|
|
19
|
+
site?: DatadogSite;
|
|
20
|
+
/**
|
|
21
|
+
* Service name for metric namespace.
|
|
22
|
+
* @default 'playwright-tests'
|
|
23
|
+
*/
|
|
24
|
+
service?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Environment tag (e.g., 'ci', 'local', 'staging').
|
|
27
|
+
*/
|
|
28
|
+
env?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Product identifier for filtering metrics.
|
|
31
|
+
*/
|
|
32
|
+
product?: string;
|
|
33
|
+
/**
|
|
34
|
+
* PR environment identifier.
|
|
35
|
+
*/
|
|
36
|
+
prenvId?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Enable debug logging.
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
debug?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Skip sending data to Datadog (for testing).
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
dryRun?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* CI/CD context information.
|
|
49
|
+
*/
|
|
50
|
+
ci?: CIContext;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Datadog metric types for API v2
|
|
54
|
+
* @see https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
|
|
55
|
+
* 0 = unspecified, 1 = count, 2 = rate, 3 = gauge
|
|
56
|
+
*/
|
|
57
|
+
export type MetricType = 0 | 1 | 2 | 3;
|
|
58
|
+
export declare const MetricTypes: {
|
|
59
|
+
UNSPECIFIED: 0;
|
|
60
|
+
COUNT: 1;
|
|
61
|
+
RATE: 2;
|
|
62
|
+
GAUGE: 3;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* A single metric point with timestamp and value
|
|
66
|
+
*/
|
|
67
|
+
export interface MetricPoint {
|
|
68
|
+
/** Unix timestamp in seconds */
|
|
69
|
+
timestamp: number;
|
|
70
|
+
/** Metric value */
|
|
71
|
+
value: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* A metric series to submit to Datadog
|
|
75
|
+
*/
|
|
76
|
+
export interface MetricSeries {
|
|
77
|
+
/** Metric name (e.g., 'playwright.test_run.uptime') */
|
|
78
|
+
metric: string;
|
|
79
|
+
/** Metric type */
|
|
80
|
+
type: MetricType;
|
|
81
|
+
/** Metric points (timestamp + value pairs) */
|
|
82
|
+
points: MetricPoint[];
|
|
83
|
+
/** Tags for filtering and grouping */
|
|
84
|
+
tags?: string[];
|
|
85
|
+
/** Unit of the metric (optional) */
|
|
86
|
+
unit?: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Datadog Metrics API v2 request body
|
|
90
|
+
* @see https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
|
|
91
|
+
*/
|
|
92
|
+
export interface DatadogMetricsPayload {
|
|
93
|
+
series: MetricSeries[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Aggregated test run data for metrics generation
|
|
97
|
+
*/
|
|
98
|
+
export interface TestRunMetrics {
|
|
99
|
+
/** Test run unique identifier */
|
|
100
|
+
testRunId: string;
|
|
101
|
+
/** Unix timestamp when run started (seconds) */
|
|
102
|
+
timestamp: number;
|
|
103
|
+
/** Total number of tests */
|
|
104
|
+
totalTests: number;
|
|
105
|
+
/** Number of passed tests (including flaky that eventually passed) */
|
|
106
|
+
passedTests: number;
|
|
107
|
+
/** Number of failed tests (permanently failed) */
|
|
108
|
+
failedTests: number;
|
|
109
|
+
/** Number of flaky tests (passed after retry) */
|
|
110
|
+
flakyTests: number;
|
|
111
|
+
/** Number of skipped tests */
|
|
112
|
+
skippedTests: number;
|
|
113
|
+
/** Number of tests that timed out */
|
|
114
|
+
timedOutTests: number;
|
|
115
|
+
/** Total run duration in milliseconds */
|
|
116
|
+
durationMs: number;
|
|
117
|
+
/** Total time spent on browser creation in milliseconds */
|
|
118
|
+
browserCreationMs: number;
|
|
119
|
+
/** Total time spent on retries in milliseconds */
|
|
120
|
+
retryTimeMs: number;
|
|
121
|
+
/** Total time spent on page navigations in milliseconds */
|
|
122
|
+
navigationMs: number;
|
|
123
|
+
/** Whether all tests passed (uptime = 1) */
|
|
124
|
+
allPassed: boolean;
|
|
125
|
+
/** Pass rate as percentage (0-100) */
|
|
126
|
+
passRate: number;
|
|
127
|
+
/** Flaky rate as percentage (0-100) */
|
|
128
|
+
flakyRate: number;
|
|
129
|
+
/** Number of parallel workers */
|
|
130
|
+
workerCount: number;
|
|
131
|
+
/** Average test duration in milliseconds */
|
|
132
|
+
avgTestDurationMs: number;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Individual test metrics
|
|
136
|
+
*/
|
|
137
|
+
export interface TestMetrics {
|
|
138
|
+
/** Test name/title */
|
|
139
|
+
name: string;
|
|
140
|
+
/** Test stable ID */
|
|
141
|
+
testId: string;
|
|
142
|
+
/** Test duration in milliseconds */
|
|
143
|
+
durationMs: number;
|
|
144
|
+
/** Number of retries */
|
|
145
|
+
retryCount: number;
|
|
146
|
+
/** Whether this test was flaky */
|
|
147
|
+
isFlaky: boolean;
|
|
148
|
+
/** Whether this test timed out */
|
|
149
|
+
isTimedOut: boolean;
|
|
150
|
+
/** Team that owns this test */
|
|
151
|
+
team?: string;
|
|
152
|
+
/** Project name */
|
|
153
|
+
project?: string;
|
|
154
|
+
/** Navigation time in milliseconds */
|
|
155
|
+
navigationMs: number;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Tags to apply to all metrics
|
|
159
|
+
*/
|
|
160
|
+
export interface MetricTags {
|
|
161
|
+
/** Git branch name */
|
|
162
|
+
branch?: string;
|
|
163
|
+
/** Project name(s) */
|
|
164
|
+
project?: string[];
|
|
165
|
+
/** PR environment identifier */
|
|
166
|
+
prenvId?: string;
|
|
167
|
+
/** What triggered the run */
|
|
168
|
+
triggeredBy?: string;
|
|
169
|
+
/** Environment (ci, local, etc.) */
|
|
170
|
+
env?: string;
|
|
171
|
+
/** Service name */
|
|
172
|
+
service?: string;
|
|
173
|
+
/** Product identifier */
|
|
174
|
+
product?: string;
|
|
175
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type FullConfig, type FullResult, type Reporter, type Suite, type TestCase, type TestResult, type TestStep } from '@playwright/test/reporter';
|
|
2
|
+
import type { DatadogReporterOptions } from './report.types';
|
|
3
|
+
/**
|
|
4
|
+
* Playwright reporter that sends test execution metrics to Datadog
|
|
5
|
+
*/
|
|
6
|
+
export default class DatadogReporter implements Reporter {
|
|
7
|
+
private readonly options;
|
|
8
|
+
private readonly datadog;
|
|
9
|
+
private readonly testRunId;
|
|
10
|
+
private runStartTime;
|
|
11
|
+
private runEndTime;
|
|
12
|
+
private totalTests;
|
|
13
|
+
private passedTests;
|
|
14
|
+
private failedTests;
|
|
15
|
+
private flakyTests;
|
|
16
|
+
private skippedTests;
|
|
17
|
+
private timedOutTests;
|
|
18
|
+
private browserCreationMs;
|
|
19
|
+
private retryTimeMs;
|
|
20
|
+
private navigationMs;
|
|
21
|
+
private workerCount;
|
|
22
|
+
private readonly testDurations;
|
|
23
|
+
private readonly testMetrics;
|
|
24
|
+
private projectNames;
|
|
25
|
+
private readonly currentTestNavigationMs;
|
|
26
|
+
constructor(options: DatadogReporterOptions);
|
|
27
|
+
onBegin(config: FullConfig, suite: Suite): Promise<void>;
|
|
28
|
+
onStepEnd(test: TestCase, result: TestResult, step: TestStep): void;
|
|
29
|
+
onTestEnd(test: TestCase, result: TestResult): void;
|
|
30
|
+
onEnd(result: FullResult): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Helper function for type-safe configuration
|
|
34
|
+
*/
|
|
35
|
+
export declare const defineDatadogReporterConfig: (options: ConstructorParameters<typeof DatadogReporter>[0]) => DatadogReporterOptions;
|