@alternative-path/testlens-playwright-reporter 0.4.1 → 0.4.3
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/index.d.ts +192 -207
- package/index.js +18 -262
- package/index.ts +18 -283
- package/package.json +1 -2
- package/testlens-ca-bundle.pem +0 -88
package/index.d.ts
CHANGED
|
@@ -1,207 +1,192 @@
|
|
|
1
|
-
import type { Reporter, TestCase, TestResult, FullConfig, Suite } from '@playwright/test/reporter';
|
|
2
|
-
export interface TestLensReporterConfig {
|
|
3
|
-
/** TestLens API endpoint URL */
|
|
4
|
-
apiEndpoint?: string;
|
|
5
|
-
/** API key for authentication - can be provided in config or via TESTLENS_API_KEY environment variable */
|
|
6
|
-
apiKey?: string;
|
|
7
|
-
/** Enable real-time streaming of test events */
|
|
8
|
-
enableRealTimeStream?: boolean;
|
|
9
|
-
/** Enable Git information collection */
|
|
10
|
-
enableGitInfo?: boolean;
|
|
11
|
-
/** Enable artifact processing */
|
|
12
|
-
enableArtifacts?: boolean;
|
|
13
|
-
/** Enable video capture - defaults to true */
|
|
14
|
-
enableVideo?: boolean;
|
|
15
|
-
/** Enable screenshot capture - defaults to true */
|
|
16
|
-
enableScreenshot?: boolean;
|
|
17
|
-
/** Batch size for API requests */
|
|
18
|
-
batchSize?: number;
|
|
19
|
-
/** Flush interval in milliseconds */
|
|
20
|
-
flushInterval?: number;
|
|
21
|
-
/** Number of retry attempts for failed API calls */
|
|
22
|
-
retryAttempts?: number;
|
|
23
|
-
/** Request timeout in milliseconds */
|
|
24
|
-
timeout?: number;
|
|
25
|
-
/** SSL certificate validation - set to false to disable SSL verification */
|
|
26
|
-
rejectUnauthorized?: boolean;
|
|
27
|
-
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
28
|
-
ignoreSslErrors?: boolean;
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
/** Enable
|
|
40
|
-
|
|
41
|
-
/** Enable
|
|
42
|
-
|
|
43
|
-
/** Enable
|
|
44
|
-
|
|
45
|
-
/** Enable
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
|
|
57
|
-
/** SSL
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
private
|
|
159
|
-
private
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
*
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
private
|
|
171
|
-
private
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
private
|
|
182
|
-
|
|
183
|
-
private
|
|
184
|
-
private
|
|
185
|
-
private
|
|
186
|
-
private
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
private sendToApi;
|
|
194
|
-
private processArtifacts;
|
|
195
|
-
private sendSpecCodeBlocks;
|
|
196
|
-
private extractTestBlocks;
|
|
197
|
-
private collectGitInfo;
|
|
198
|
-
private getArtifactType;
|
|
199
|
-
private extractTags;
|
|
200
|
-
private getTestId;
|
|
201
|
-
private uploadArtifactToS3;
|
|
202
|
-
private getContentType;
|
|
203
|
-
private generateS3Key;
|
|
204
|
-
private sanitizeForS3;
|
|
205
|
-
private getFileSize;
|
|
206
|
-
}
|
|
207
|
-
export default TestLensReporter;
|
|
1
|
+
import type { Reporter, TestCase, TestResult, FullConfig, Suite } from '@playwright/test/reporter';
|
|
2
|
+
export interface TestLensReporterConfig {
|
|
3
|
+
/** TestLens API endpoint URL */
|
|
4
|
+
apiEndpoint?: string;
|
|
5
|
+
/** API key for authentication - can be provided in config or via TESTLENS_API_KEY environment variable */
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
/** Enable real-time streaming of test events */
|
|
8
|
+
enableRealTimeStream?: boolean;
|
|
9
|
+
/** Enable Git information collection */
|
|
10
|
+
enableGitInfo?: boolean;
|
|
11
|
+
/** Enable artifact processing */
|
|
12
|
+
enableArtifacts?: boolean;
|
|
13
|
+
/** Enable video capture - defaults to true */
|
|
14
|
+
enableVideo?: boolean;
|
|
15
|
+
/** Enable screenshot capture - defaults to true */
|
|
16
|
+
enableScreenshot?: boolean;
|
|
17
|
+
/** Batch size for API requests */
|
|
18
|
+
batchSize?: number;
|
|
19
|
+
/** Flush interval in milliseconds */
|
|
20
|
+
flushInterval?: number;
|
|
21
|
+
/** Number of retry attempts for failed API calls */
|
|
22
|
+
retryAttempts?: number;
|
|
23
|
+
/** Request timeout in milliseconds */
|
|
24
|
+
timeout?: number;
|
|
25
|
+
/** SSL certificate validation - set to false to disable SSL verification */
|
|
26
|
+
rejectUnauthorized?: boolean;
|
|
27
|
+
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
28
|
+
ignoreSslErrors?: boolean;
|
|
29
|
+
/** Custom metadata from CLI arguments (automatically parsed from --key=value arguments) */
|
|
30
|
+
customMetadata?: Record<string, string | string[]>;
|
|
31
|
+
}
|
|
32
|
+
export interface TestLensReporterOptions {
|
|
33
|
+
/** TestLens API endpoint URL */
|
|
34
|
+
apiEndpoint?: string;
|
|
35
|
+
/** API key for authentication - can be provided in config or via TESTLENS_API_KEY environment variable */
|
|
36
|
+
apiKey?: string;
|
|
37
|
+
/** Enable real-time streaming of test events */
|
|
38
|
+
enableRealTimeStream?: boolean;
|
|
39
|
+
/** Enable Git information collection */
|
|
40
|
+
enableGitInfo?: boolean;
|
|
41
|
+
/** Enable artifact processing */
|
|
42
|
+
enableArtifacts?: boolean;
|
|
43
|
+
/** Enable video capture - defaults to true */
|
|
44
|
+
enableVideo?: boolean;
|
|
45
|
+
/** Enable screenshot capture - defaults to true */
|
|
46
|
+
enableScreenshot?: boolean;
|
|
47
|
+
/** Batch size for API requests */
|
|
48
|
+
batchSize?: number;
|
|
49
|
+
/** Flush interval in milliseconds */
|
|
50
|
+
flushInterval?: number;
|
|
51
|
+
/** Number of retry attempts for failed API calls */
|
|
52
|
+
retryAttempts?: number;
|
|
53
|
+
/** Request timeout in milliseconds */
|
|
54
|
+
timeout?: number;
|
|
55
|
+
/** SSL certificate validation - set to false to disable SSL verification */
|
|
56
|
+
rejectUnauthorized?: boolean;
|
|
57
|
+
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
58
|
+
ignoreSslErrors?: boolean;
|
|
59
|
+
/** Custom metadata from CLI arguments (automatically parsed from --key=value arguments) */
|
|
60
|
+
customMetadata?: Record<string, string | string[]>;
|
|
61
|
+
}
|
|
62
|
+
export interface GitInfo {
|
|
63
|
+
branch: string;
|
|
64
|
+
commit: string;
|
|
65
|
+
shortCommit: string;
|
|
66
|
+
author: string;
|
|
67
|
+
message: string;
|
|
68
|
+
timestamp: string;
|
|
69
|
+
isDirty: boolean;
|
|
70
|
+
remoteName: string;
|
|
71
|
+
remoteUrl: string;
|
|
72
|
+
}
|
|
73
|
+
export interface CodeBlock {
|
|
74
|
+
type: 'test' | 'describe';
|
|
75
|
+
name: string;
|
|
76
|
+
content: string;
|
|
77
|
+
summary?: string;
|
|
78
|
+
describe?: string;
|
|
79
|
+
startLine?: number;
|
|
80
|
+
endLine?: number;
|
|
81
|
+
}
|
|
82
|
+
export interface RunMetadata {
|
|
83
|
+
id: string;
|
|
84
|
+
startTime: string;
|
|
85
|
+
endTime?: string;
|
|
86
|
+
duration?: number;
|
|
87
|
+
environment: string;
|
|
88
|
+
browser: string;
|
|
89
|
+
os: string;
|
|
90
|
+
playwrightVersion: string;
|
|
91
|
+
nodeVersion: string;
|
|
92
|
+
gitInfo?: GitInfo | null;
|
|
93
|
+
shardInfo?: {
|
|
94
|
+
current: number;
|
|
95
|
+
total: number;
|
|
96
|
+
};
|
|
97
|
+
totalTests?: number;
|
|
98
|
+
passedTests?: number;
|
|
99
|
+
failedTests?: number;
|
|
100
|
+
skippedTests?: number;
|
|
101
|
+
status?: string;
|
|
102
|
+
testlensBuildName?: string;
|
|
103
|
+
customMetadata?: Record<string, string | string[]>;
|
|
104
|
+
}
|
|
105
|
+
export interface TestError {
|
|
106
|
+
message: string;
|
|
107
|
+
stack?: string;
|
|
108
|
+
location?: {
|
|
109
|
+
file: string;
|
|
110
|
+
line: number;
|
|
111
|
+
column: number;
|
|
112
|
+
};
|
|
113
|
+
snippet?: string;
|
|
114
|
+
expected?: string;
|
|
115
|
+
actual?: string;
|
|
116
|
+
diff?: string;
|
|
117
|
+
matcherName?: string;
|
|
118
|
+
timeout?: number;
|
|
119
|
+
}
|
|
120
|
+
export interface TestData {
|
|
121
|
+
id: string;
|
|
122
|
+
name: string;
|
|
123
|
+
status: string;
|
|
124
|
+
originalStatus?: string;
|
|
125
|
+
duration: number;
|
|
126
|
+
startTime: string;
|
|
127
|
+
endTime: string;
|
|
128
|
+
errorMessages: string[];
|
|
129
|
+
errors?: TestError[];
|
|
130
|
+
retryAttempts: number;
|
|
131
|
+
currentRetry: number;
|
|
132
|
+
annotations: Array<{
|
|
133
|
+
type: string;
|
|
134
|
+
description?: string;
|
|
135
|
+
}>;
|
|
136
|
+
projectName: string;
|
|
137
|
+
workerIndex?: number;
|
|
138
|
+
parallelIndex?: number;
|
|
139
|
+
location?: {
|
|
140
|
+
file: string;
|
|
141
|
+
line: number;
|
|
142
|
+
column: number;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export interface SpecData {
|
|
146
|
+
filePath: string;
|
|
147
|
+
testSuiteName: string;
|
|
148
|
+
tags?: string[];
|
|
149
|
+
startTime: string;
|
|
150
|
+
endTime?: string;
|
|
151
|
+
status: string;
|
|
152
|
+
}
|
|
153
|
+
export declare class TestLensReporter implements Reporter {
|
|
154
|
+
private config;
|
|
155
|
+
private axiosInstance;
|
|
156
|
+
private runId;
|
|
157
|
+
private runMetadata;
|
|
158
|
+
private specMap;
|
|
159
|
+
private testMap;
|
|
160
|
+
private runCreationFailed;
|
|
161
|
+
private cliArgs;
|
|
162
|
+
/**
|
|
163
|
+
* Parse custom metadata from environment variables
|
|
164
|
+
* Checks for common metadata environment variables
|
|
165
|
+
*/
|
|
166
|
+
private static parseCustomArgs;
|
|
167
|
+
constructor(options: TestLensReporterOptions);
|
|
168
|
+
private initializeRunMetadata;
|
|
169
|
+
private getPlaywrightVersion;
|
|
170
|
+
private normalizeTestStatus;
|
|
171
|
+
private normalizeRunStatus;
|
|
172
|
+
onBegin(config: FullConfig, suite: Suite): Promise<void>;
|
|
173
|
+
onTestBegin(test: TestCase, result: TestResult): Promise<void>;
|
|
174
|
+
onTestEnd(test: TestCase, result: TestResult): Promise<void>;
|
|
175
|
+
onEnd(result: {
|
|
176
|
+
status: string;
|
|
177
|
+
}): Promise<void>;
|
|
178
|
+
private sendToApi;
|
|
179
|
+
private processArtifacts;
|
|
180
|
+
private sendSpecCodeBlocks;
|
|
181
|
+
private extractTestBlocks;
|
|
182
|
+
private collectGitInfo;
|
|
183
|
+
private getArtifactType;
|
|
184
|
+
private extractTags;
|
|
185
|
+
private getTestId;
|
|
186
|
+
private uploadArtifactToS3;
|
|
187
|
+
private getContentType;
|
|
188
|
+
private generateS3Key;
|
|
189
|
+
private sanitizeForS3;
|
|
190
|
+
private getFileSize;
|
|
191
|
+
}
|
|
192
|
+
export default TestLensReporter;
|
package/index.js
CHANGED
|
@@ -7,7 +7,6 @@ const os = tslib_1.__importStar(require("os"));
|
|
|
7
7
|
const path = tslib_1.__importStar(require("path"));
|
|
8
8
|
const fs = tslib_1.__importStar(require("fs"));
|
|
9
9
|
const https = tslib_1.__importStar(require("https"));
|
|
10
|
-
const tls = tslib_1.__importStar(require("tls"));
|
|
11
10
|
const axios_1 = tslib_1.__importDefault(require("axios"));
|
|
12
11
|
const child_process_1 = require("child_process");
|
|
13
12
|
// Lazy-load mime module to support ESM
|
|
@@ -21,94 +20,6 @@ async function getMime() {
|
|
|
21
20
|
return mimeModule;
|
|
22
21
|
}
|
|
23
22
|
class TestLensReporter {
|
|
24
|
-
/**
|
|
25
|
-
* Get bundled CA certificates for TestLens
|
|
26
|
-
* Combines custom CA bundle with Node.js root certificates
|
|
27
|
-
* This ensures SSL works with both testlens.qa-path.com and other HTTPS endpoints
|
|
28
|
-
*/
|
|
29
|
-
static getBundledCaCertificates() {
|
|
30
|
-
const allCerts = [];
|
|
31
|
-
// First, add our bundled TestLens CA certificate chain
|
|
32
|
-
try {
|
|
33
|
-
const certPath = path.join(__dirname, 'testlens-ca-bundle.pem');
|
|
34
|
-
if (fs.existsSync(certPath)) {
|
|
35
|
-
const certData = fs.readFileSync(certPath, 'utf8');
|
|
36
|
-
// Split the bundle into individual certificates
|
|
37
|
-
const certs = certData.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
|
|
38
|
-
if (certs && certs.length > 0) {
|
|
39
|
-
const buffers = certs.map(cert => Buffer.from(cert, 'utf8'));
|
|
40
|
-
allCerts.push(...buffers);
|
|
41
|
-
if (process.env.DEBUG) {
|
|
42
|
-
console.log(`✓ Loaded bundled TestLens CA certificates (${buffers.length} certificate(s))`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
if (process.env.DEBUG) {
|
|
49
|
-
console.log('⚠️ Bundled CA certificate not available');
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// Then, add Node.js built-in root certificates for general SSL support
|
|
53
|
-
try {
|
|
54
|
-
if (tls.rootCertificates && Array.isArray(tls.rootCertificates) && tls.rootCertificates.length > 0) {
|
|
55
|
-
const rootCerts = tls.rootCertificates.map(cert => Buffer.from(cert, 'utf8'));
|
|
56
|
-
allCerts.push(...rootCerts);
|
|
57
|
-
if (process.env.DEBUG) {
|
|
58
|
-
console.log(`✓ Added Node.js built-in root certificates (${rootCerts.length} certificates)`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
if (process.env.DEBUG) {
|
|
64
|
-
console.log('⚠️ Node.js built-in root certificates not available');
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return allCerts.length > 0 ? allCerts : undefined;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Automatically detect and load system CA certificates
|
|
71
|
-
* Uses bundled certificates as primary source, falls back to system certificates
|
|
72
|
-
*/
|
|
73
|
-
static getSystemCaCertificates() {
|
|
74
|
-
// First, try to use our bundled certificates (Node.js rootCertificates)
|
|
75
|
-
const bundledCerts = TestLensReporter.getBundledCaCertificates();
|
|
76
|
-
if (bundledCerts && bundledCerts.length > 0) {
|
|
77
|
-
return bundledCerts;
|
|
78
|
-
}
|
|
79
|
-
// Fallback: Try to load from file system (for older Node.js versions or special cases)
|
|
80
|
-
const platform = os.platform();
|
|
81
|
-
const certificates = [];
|
|
82
|
-
const certPaths = [];
|
|
83
|
-
if (platform === 'darwin') {
|
|
84
|
-
// macOS: Common certificate locations
|
|
85
|
-
certPaths.push('/etc/ssl/cert.pem', '/usr/local/etc/openssl/cert.pem', '/opt/homebrew/etc/openssl/cert.pem', '/System/Library/OpenSSL/certs/cert.pem');
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
// Linux and other Unix-like systems
|
|
89
|
-
certPaths.push('/etc/ssl/certs/ca-certificates.crt', '/etc/ssl/certs/ca-bundle.crt', '/etc/pki/tls/certs/ca-bundle.crt', '/etc/ssl/ca-bundle.pem', '/usr/share/ssl/certs/ca-bundle.crt', '/usr/local/share/certs/ca-root-nss.crt', '/etc/ca-certificates/extracted/tls-ca-bundle.pem');
|
|
90
|
-
}
|
|
91
|
-
// Try to load certificates from common locations
|
|
92
|
-
for (const certPath of certPaths) {
|
|
93
|
-
try {
|
|
94
|
-
if (certPath && fs.existsSync(certPath)) {
|
|
95
|
-
const certData = fs.readFileSync(certPath);
|
|
96
|
-
certificates.push(certData);
|
|
97
|
-
// Only log in debug mode to avoid noise
|
|
98
|
-
if (process.env.DEBUG) {
|
|
99
|
-
console.log(`✓ Loaded CA certificates from: ${certPath}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
// Silently continue if a certificate file can't be read
|
|
105
|
-
// This is expected as not all paths will exist on every system
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// Return undefined if no certificates found (let Node.js use defaults)
|
|
109
|
-
// Return certificates array if we found any
|
|
110
|
-
return certificates.length > 0 ? certificates : undefined;
|
|
111
|
-
}
|
|
112
23
|
/**
|
|
113
24
|
* Parse custom metadata from environment variables
|
|
114
25
|
* Checks for common metadata environment variables
|
|
@@ -186,46 +97,6 @@ class TestLensReporter {
|
|
|
186
97
|
}
|
|
187
98
|
// Determine SSL validation behavior
|
|
188
99
|
let rejectUnauthorized = true; // Default to secure
|
|
189
|
-
let ca = undefined;
|
|
190
|
-
// Use bundled CA certificates as primary source (Node.js rootCertificates)
|
|
191
|
-
// This ensures consistent behavior across all platforms
|
|
192
|
-
const bundledCerts = TestLensReporter.getBundledCaCertificates();
|
|
193
|
-
// Load custom CA certificate if explicitly provided (for advanced users)
|
|
194
|
-
// Custom certificates will be combined with bundled certificates
|
|
195
|
-
if (this.config.caCertificate) {
|
|
196
|
-
try {
|
|
197
|
-
if (fs.existsSync(this.config.caCertificate)) {
|
|
198
|
-
const customCert = fs.readFileSync(this.config.caCertificate);
|
|
199
|
-
// Combine bundled certs with custom cert
|
|
200
|
-
if (bundledCerts && Array.isArray(bundledCerts) && bundledCerts.length > 0) {
|
|
201
|
-
ca = [...bundledCerts, customCert];
|
|
202
|
-
console.log(`✓ Using bundled CA certificates + custom certificate: ${this.config.caCertificate}`);
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
ca = customCert;
|
|
206
|
-
console.log(`✓ Using custom CA certificate: ${this.config.caCertificate}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
console.warn(`⚠️ CA certificate file not found: ${this.config.caCertificate}`);
|
|
211
|
-
// Fall back to bundled certs if custom cert not found
|
|
212
|
-
ca = bundledCerts || undefined;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
catch (error) {
|
|
216
|
-
console.warn(`⚠️ Failed to read CA certificate file: ${this.config.caCertificate}`, error.message);
|
|
217
|
-
// Fall back to bundled certs if custom cert read fails
|
|
218
|
-
ca = bundledCerts || undefined;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
// Use bundled certificates as primary source
|
|
223
|
-
// This works reliably across all platforms (Windows, macOS, Linux)
|
|
224
|
-
ca = bundledCerts || undefined;
|
|
225
|
-
if (ca && process.env.DEBUG) {
|
|
226
|
-
console.log(`✓ Using bundled CA certificates (${Array.isArray(ca) ? ca.length : 1} certificates)`);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
100
|
// Check various ways SSL validation can be disabled (in order of precedence)
|
|
230
101
|
if (this.config.ignoreSslErrors) {
|
|
231
102
|
// Explicit configuration option
|
|
@@ -243,24 +114,6 @@ class TestLensReporter {
|
|
|
243
114
|
console.log('⚠️ SSL certificate validation disabled via NODE_TLS_REJECT_UNAUTHORIZED environment variable');
|
|
244
115
|
}
|
|
245
116
|
// Set up axios instance with retry logic and enhanced SSL handling
|
|
246
|
-
const httpsAgentOptions = {
|
|
247
|
-
rejectUnauthorized: rejectUnauthorized,
|
|
248
|
-
// Allow any TLS version for better compatibility
|
|
249
|
-
minVersion: 'TLSv1.2',
|
|
250
|
-
maxVersion: 'TLSv1.3'
|
|
251
|
-
};
|
|
252
|
-
// Add CA certificates if available
|
|
253
|
-
// On Windows, ca will be undefined to let Node.js use Windows certificate store automatically
|
|
254
|
-
// On Unix systems, ca will contain certificates if found, or undefined to use Node.js defaults
|
|
255
|
-
if (ca !== undefined) {
|
|
256
|
-
if (Array.isArray(ca) && ca.length > 0) {
|
|
257
|
-
httpsAgentOptions.ca = ca;
|
|
258
|
-
}
|
|
259
|
-
else if (typeof ca === 'string' || Buffer.isBuffer(ca)) {
|
|
260
|
-
httpsAgentOptions.ca = ca;
|
|
261
|
-
}
|
|
262
|
-
// If ca is undefined, we don't set it, allowing Node.js to use its default certificate store
|
|
263
|
-
}
|
|
264
117
|
this.axiosInstance = axios_1.default.create({
|
|
265
118
|
baseURL: this.config.apiEndpoint,
|
|
266
119
|
timeout: this.config.timeout,
|
|
@@ -269,7 +122,12 @@ class TestLensReporter {
|
|
|
269
122
|
...(this.config.apiKey && { 'X-API-Key': this.config.apiKey }),
|
|
270
123
|
},
|
|
271
124
|
// Enhanced SSL handling with flexible TLS configuration
|
|
272
|
-
httpsAgent: new https.Agent(
|
|
125
|
+
httpsAgent: new https.Agent({
|
|
126
|
+
rejectUnauthorized: rejectUnauthorized,
|
|
127
|
+
// Allow any TLS version for better compatibility
|
|
128
|
+
minVersion: 'TLSv1.2',
|
|
129
|
+
maxVersion: 'TLSv1.3'
|
|
130
|
+
})
|
|
273
131
|
});
|
|
274
132
|
// Add retry interceptor
|
|
275
133
|
this.axiosInstance.interceptors.response.use((response) => response, async (error) => {
|
|
@@ -789,68 +647,17 @@ class TestLensReporter {
|
|
|
789
647
|
console.error(`❌ Authentication failed: ${errorData?.error || 'Invalid API key'}`);
|
|
790
648
|
}
|
|
791
649
|
}
|
|
792
|
-
else {
|
|
793
|
-
//
|
|
794
|
-
|
|
795
|
-
error?.
|
|
796
|
-
|
|
797
|
-
error?.
|
|
798
|
-
|
|
799
|
-
error?.
|
|
800
|
-
error?.
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
console.error('❌ SSL Certificate Error');
|
|
804
|
-
console.error('='.repeat(80));
|
|
805
|
-
console.error('');
|
|
806
|
-
console.error(`Failed to send ${payload.type} event to TestLens due to SSL certificate issue.`);
|
|
807
|
-
console.error('');
|
|
808
|
-
console.error('The reporter automatically attempts to detect and use system CA certificates.');
|
|
809
|
-
console.error('If this error persists, it may indicate:');
|
|
810
|
-
console.error(' - Missing or outdated system CA certificates');
|
|
811
|
-
console.error(' - Corporate proxy with custom CA certificate');
|
|
812
|
-
console.error(' - Incomplete certificate chain from the server');
|
|
813
|
-
console.error('');
|
|
814
|
-
console.error('Error details:');
|
|
815
|
-
console.error(` Code: ${error?.code || 'Unknown'}`);
|
|
816
|
-
console.error(` Message: ${error?.message || 'Unknown error'}`);
|
|
817
|
-
console.error('');
|
|
818
|
-
console.error('Possible solutions:');
|
|
819
|
-
console.error('');
|
|
820
|
-
console.error('1. Update your system\'s CA certificate store:');
|
|
821
|
-
console.error(' - Windows: Update Windows root certificates via Windows Update');
|
|
822
|
-
console.error(' - macOS: Run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate.pem>');
|
|
823
|
-
console.error(' - Linux: Update ca-certificates package: sudo apt-get update && sudo apt-get install ca-certificates');
|
|
824
|
-
console.error('');
|
|
825
|
-
console.error('2. If you have a custom CA certificate file (e.g., from corporate proxy),');
|
|
826
|
-
console.error(' you can specify it in your config (optional):');
|
|
827
|
-
console.error(' reporter: [');
|
|
828
|
-
console.error(' [\'@testlens/playwright-reporter\', {');
|
|
829
|
-
console.error(' caCertificate: \'/path/to/your/ca-certificate.pem\'');
|
|
830
|
-
console.error(' }]');
|
|
831
|
-
console.error(' ]');
|
|
832
|
-
console.error('');
|
|
833
|
-
console.error('3. Contact your network administrator if you\'re behind a corporate proxy');
|
|
834
|
-
console.error(' that uses a custom CA certificate.');
|
|
835
|
-
console.error('');
|
|
836
|
-
console.error('⚠️ WARNING: Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables SSL verification');
|
|
837
|
-
console.error(' and is insecure. Only use this as a last resort in development.');
|
|
838
|
-
console.error('');
|
|
839
|
-
console.error('='.repeat(80));
|
|
840
|
-
console.error('');
|
|
841
|
-
}
|
|
842
|
-
else if (status !== 403) {
|
|
843
|
-
// Log other errors (but not 403 which we handled above)
|
|
844
|
-
console.error(`❌ Failed to send ${payload.type} event to TestLens:`, {
|
|
845
|
-
message: error?.message || 'Unknown error',
|
|
846
|
-
status: status,
|
|
847
|
-
statusText: error?.response?.statusText,
|
|
848
|
-
data: errorData,
|
|
849
|
-
code: error?.code,
|
|
850
|
-
url: error?.config?.url,
|
|
851
|
-
method: error?.config?.method
|
|
852
|
-
});
|
|
853
|
-
}
|
|
650
|
+
else if (status !== 403) {
|
|
651
|
+
// Log other errors (but not 403 which we handled above)
|
|
652
|
+
console.error(`❌ Failed to send ${payload.type} event to TestLens:`, {
|
|
653
|
+
message: error?.message || 'Unknown error',
|
|
654
|
+
status: status,
|
|
655
|
+
statusText: error?.response?.statusText,
|
|
656
|
+
data: errorData,
|
|
657
|
+
code: error?.code,
|
|
658
|
+
url: error?.config?.url,
|
|
659
|
+
method: error?.config?.method
|
|
660
|
+
});
|
|
854
661
|
}
|
|
855
662
|
// Don't throw error to avoid breaking test execution
|
|
856
663
|
}
|
|
@@ -969,58 +776,7 @@ class TestLensReporter {
|
|
|
969
776
|
console.log(`ℹ️ Spec code blocks already exist for: ${path.basename(specPath)} (skipped)`);
|
|
970
777
|
return;
|
|
971
778
|
}
|
|
972
|
-
|
|
973
|
-
const isSslError = error?.code === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' ||
|
|
974
|
-
error?.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
|
|
975
|
-
error?.code === 'CERT_HAS_EXPIRED' ||
|
|
976
|
-
error?.code === 'SELF_SIGNED_CERT_IN_CHAIN' ||
|
|
977
|
-
error?.message?.includes('certificate') ||
|
|
978
|
-
error?.message?.includes('SSL') ||
|
|
979
|
-
error?.message?.includes('TLS');
|
|
980
|
-
if (isSslError) {
|
|
981
|
-
console.error('\n' + '='.repeat(80));
|
|
982
|
-
console.error('❌ SSL Certificate Error');
|
|
983
|
-
console.error('='.repeat(80));
|
|
984
|
-
console.error('');
|
|
985
|
-
console.error('Failed to send spec code blocks due to SSL certificate issue.');
|
|
986
|
-
console.error('');
|
|
987
|
-
console.error('The reporter automatically attempts to detect and use system CA certificates.');
|
|
988
|
-
console.error('If this error persists, it may indicate:');
|
|
989
|
-
console.error(' - Missing or outdated system CA certificates');
|
|
990
|
-
console.error(' - Corporate proxy with custom CA certificate');
|
|
991
|
-
console.error(' - Incomplete certificate chain from the server');
|
|
992
|
-
console.error('');
|
|
993
|
-
console.error('Error details:');
|
|
994
|
-
console.error(` Code: ${error?.code || 'Unknown'}`);
|
|
995
|
-
console.error(` Message: ${error?.message || 'Unknown error'}`);
|
|
996
|
-
console.error('');
|
|
997
|
-
console.error('Possible solutions:');
|
|
998
|
-
console.error('');
|
|
999
|
-
console.error('1. Update your system\'s CA certificate store:');
|
|
1000
|
-
console.error(' - Windows: Update Windows root certificates via Windows Update');
|
|
1001
|
-
console.error(' - macOS: Run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate.pem>');
|
|
1002
|
-
console.error(' - Linux: Update ca-certificates package: sudo apt-get update && sudo apt-get install ca-certificates');
|
|
1003
|
-
console.error('');
|
|
1004
|
-
console.error('2. If you have a custom CA certificate file (e.g., from corporate proxy),');
|
|
1005
|
-
console.error(' you can specify it in your config (optional):');
|
|
1006
|
-
console.error(' reporter: [');
|
|
1007
|
-
console.error(' [\'@testlens/playwright-reporter\', {');
|
|
1008
|
-
console.error(' caCertificate: \'/path/to/your/ca-certificate.pem\'');
|
|
1009
|
-
console.error(' }]');
|
|
1010
|
-
console.error(' ]');
|
|
1011
|
-
console.error('');
|
|
1012
|
-
console.error('3. Contact your network administrator if you\'re behind a corporate proxy');
|
|
1013
|
-
console.error(' that uses a custom CA certificate.');
|
|
1014
|
-
console.error('');
|
|
1015
|
-
console.error('⚠️ WARNING: Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables SSL verification');
|
|
1016
|
-
console.error(' and is insecure. Only use this as a last resort in development.');
|
|
1017
|
-
console.error('');
|
|
1018
|
-
console.error('='.repeat(80));
|
|
1019
|
-
console.error('');
|
|
1020
|
-
}
|
|
1021
|
-
else {
|
|
1022
|
-
console.error('Failed to send spec code blocks:', errorData || error?.message || 'Unknown error');
|
|
1023
|
-
}
|
|
779
|
+
console.error('Failed to send spec code blocks:', errorData || error?.message || 'Unknown error');
|
|
1024
780
|
}
|
|
1025
781
|
}
|
|
1026
782
|
extractTestBlocks(filePath) {
|
package/index.ts
CHANGED
|
@@ -3,7 +3,6 @@ import * as os from 'os';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as https from 'https';
|
|
6
|
-
import * as tls from 'tls';
|
|
7
6
|
import axios, { AxiosInstance } from 'axios';
|
|
8
7
|
import type { Reporter, TestCase, TestResult, FullConfig, Suite } from '@playwright/test/reporter';
|
|
9
8
|
import { execSync } from 'child_process';
|
|
@@ -47,8 +46,6 @@ export interface TestLensReporterConfig {
|
|
|
47
46
|
rejectUnauthorized?: boolean;
|
|
48
47
|
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
49
48
|
ignoreSslErrors?: boolean;
|
|
50
|
-
/** Path to a custom CA certificate file (PEM format) to use for SSL verification */
|
|
51
|
-
caCertificate?: string;
|
|
52
49
|
/** Custom metadata from CLI arguments (automatically parsed from --key=value arguments) */
|
|
53
50
|
customMetadata?: Record<string, string | string[]>;
|
|
54
51
|
}
|
|
@@ -80,8 +77,6 @@ export interface TestLensReporterOptions {
|
|
|
80
77
|
rejectUnauthorized?: boolean;
|
|
81
78
|
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
82
79
|
ignoreSslErrors?: boolean;
|
|
83
|
-
/** Path to a custom CA certificate file (PEM format) to use for SSL verification */
|
|
84
|
-
caCertificate?: string;
|
|
85
80
|
/** Custom metadata from CLI arguments (automatically parsed from --key=value arguments) */
|
|
86
81
|
customMetadata?: Record<string, string | string[]>;
|
|
87
82
|
}
|
|
@@ -183,112 +178,6 @@ export interface SpecData {
|
|
|
183
178
|
export class TestLensReporter implements Reporter {
|
|
184
179
|
private config: Required<TestLensReporterConfig>;
|
|
185
180
|
private axiosInstance: AxiosInstance;
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Get bundled CA certificates for TestLens
|
|
189
|
-
* Combines custom CA bundle with Node.js root certificates
|
|
190
|
-
* This ensures SSL works with both testlens.qa-path.com and other HTTPS endpoints
|
|
191
|
-
*/
|
|
192
|
-
private static getBundledCaCertificates(): Buffer[] | undefined {
|
|
193
|
-
const allCerts: Buffer[] = [];
|
|
194
|
-
|
|
195
|
-
// First, add our bundled TestLens CA certificate chain
|
|
196
|
-
try {
|
|
197
|
-
const certPath = path.join(__dirname, 'testlens-ca-bundle.pem');
|
|
198
|
-
if (fs.existsSync(certPath)) {
|
|
199
|
-
const certData = fs.readFileSync(certPath, 'utf8');
|
|
200
|
-
// Split the bundle into individual certificates
|
|
201
|
-
const certs = certData.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
|
|
202
|
-
if (certs && certs.length > 0) {
|
|
203
|
-
const buffers = certs.map(cert => Buffer.from(cert, 'utf8'));
|
|
204
|
-
allCerts.push(...buffers);
|
|
205
|
-
if (process.env.DEBUG) {
|
|
206
|
-
console.log(`✓ Loaded bundled TestLens CA certificates (${buffers.length} certificate(s))`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
} catch (error) {
|
|
211
|
-
if (process.env.DEBUG) {
|
|
212
|
-
console.log('⚠️ Bundled CA certificate not available');
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Then, add Node.js built-in root certificates for general SSL support
|
|
217
|
-
try {
|
|
218
|
-
if (tls.rootCertificates && Array.isArray(tls.rootCertificates) && tls.rootCertificates.length > 0) {
|
|
219
|
-
const rootCerts = tls.rootCertificates.map(cert => Buffer.from(cert, 'utf8'));
|
|
220
|
-
allCerts.push(...rootCerts);
|
|
221
|
-
if (process.env.DEBUG) {
|
|
222
|
-
console.log(`✓ Added Node.js built-in root certificates (${rootCerts.length} certificates)`);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
} catch (error) {
|
|
226
|
-
if (process.env.DEBUG) {
|
|
227
|
-
console.log('⚠️ Node.js built-in root certificates not available');
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return allCerts.length > 0 ? allCerts : undefined;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Automatically detect and load system CA certificates
|
|
236
|
-
* Uses bundled certificates as primary source, falls back to system certificates
|
|
237
|
-
*/
|
|
238
|
-
private static getSystemCaCertificates(): Buffer[] | undefined {
|
|
239
|
-
// First, try to use our bundled certificates (Node.js rootCertificates)
|
|
240
|
-
const bundledCerts = TestLensReporter.getBundledCaCertificates();
|
|
241
|
-
if (bundledCerts && bundledCerts.length > 0) {
|
|
242
|
-
return bundledCerts;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Fallback: Try to load from file system (for older Node.js versions or special cases)
|
|
246
|
-
const platform = os.platform();
|
|
247
|
-
const certificates: Buffer[] = [];
|
|
248
|
-
const certPaths: string[] = [];
|
|
249
|
-
|
|
250
|
-
if (platform === 'darwin') {
|
|
251
|
-
// macOS: Common certificate locations
|
|
252
|
-
certPaths.push(
|
|
253
|
-
'/etc/ssl/cert.pem',
|
|
254
|
-
'/usr/local/etc/openssl/cert.pem',
|
|
255
|
-
'/opt/homebrew/etc/openssl/cert.pem',
|
|
256
|
-
'/System/Library/OpenSSL/certs/cert.pem'
|
|
257
|
-
);
|
|
258
|
-
} else {
|
|
259
|
-
// Linux and other Unix-like systems
|
|
260
|
-
certPaths.push(
|
|
261
|
-
'/etc/ssl/certs/ca-certificates.crt',
|
|
262
|
-
'/etc/ssl/certs/ca-bundle.crt',
|
|
263
|
-
'/etc/pki/tls/certs/ca-bundle.crt',
|
|
264
|
-
'/etc/ssl/ca-bundle.pem',
|
|
265
|
-
'/usr/share/ssl/certs/ca-bundle.crt',
|
|
266
|
-
'/usr/local/share/certs/ca-root-nss.crt',
|
|
267
|
-
'/etc/ca-certificates/extracted/tls-ca-bundle.pem'
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Try to load certificates from common locations
|
|
272
|
-
for (const certPath of certPaths) {
|
|
273
|
-
try {
|
|
274
|
-
if (certPath && fs.existsSync(certPath)) {
|
|
275
|
-
const certData = fs.readFileSync(certPath);
|
|
276
|
-
certificates.push(certData);
|
|
277
|
-
// Only log in debug mode to avoid noise
|
|
278
|
-
if (process.env.DEBUG) {
|
|
279
|
-
console.log(`✓ Loaded CA certificates from: ${certPath}`);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
} catch (error) {
|
|
283
|
-
// Silently continue if a certificate file can't be read
|
|
284
|
-
// This is expected as not all paths will exist on every system
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Return undefined if no certificates found (let Node.js use defaults)
|
|
289
|
-
// Return certificates array if we found any
|
|
290
|
-
return certificates.length > 0 ? certificates : undefined;
|
|
291
|
-
}
|
|
292
181
|
private runId: string;
|
|
293
182
|
private runMetadata: RunMetadata;
|
|
294
183
|
private specMap: Map<string, SpecData>;
|
|
@@ -379,44 +268,6 @@ export class TestLensReporter implements Reporter {
|
|
|
379
268
|
|
|
380
269
|
// Determine SSL validation behavior
|
|
381
270
|
let rejectUnauthorized = true; // Default to secure
|
|
382
|
-
let ca: Buffer | string | Buffer[] | undefined = undefined;
|
|
383
|
-
|
|
384
|
-
// Use bundled CA certificates as primary source (Node.js rootCertificates)
|
|
385
|
-
// This ensures consistent behavior across all platforms
|
|
386
|
-
const bundledCerts = TestLensReporter.getBundledCaCertificates();
|
|
387
|
-
|
|
388
|
-
// Load custom CA certificate if explicitly provided (for advanced users)
|
|
389
|
-
// Custom certificates will be combined with bundled certificates
|
|
390
|
-
if (this.config.caCertificate) {
|
|
391
|
-
try {
|
|
392
|
-
if (fs.existsSync(this.config.caCertificate)) {
|
|
393
|
-
const customCert = fs.readFileSync(this.config.caCertificate);
|
|
394
|
-
// Combine bundled certs with custom cert
|
|
395
|
-
if (bundledCerts && Array.isArray(bundledCerts) && bundledCerts.length > 0) {
|
|
396
|
-
ca = [...bundledCerts, customCert];
|
|
397
|
-
console.log(`✓ Using bundled CA certificates + custom certificate: ${this.config.caCertificate}`);
|
|
398
|
-
} else {
|
|
399
|
-
ca = customCert;
|
|
400
|
-
console.log(`✓ Using custom CA certificate: ${this.config.caCertificate}`);
|
|
401
|
-
}
|
|
402
|
-
} else {
|
|
403
|
-
console.warn(`⚠️ CA certificate file not found: ${this.config.caCertificate}`);
|
|
404
|
-
// Fall back to bundled certs if custom cert not found
|
|
405
|
-
ca = bundledCerts || undefined;
|
|
406
|
-
}
|
|
407
|
-
} catch (error) {
|
|
408
|
-
console.warn(`⚠️ Failed to read CA certificate file: ${this.config.caCertificate}`, (error as Error).message);
|
|
409
|
-
// Fall back to bundled certs if custom cert read fails
|
|
410
|
-
ca = bundledCerts || undefined;
|
|
411
|
-
}
|
|
412
|
-
} else {
|
|
413
|
-
// Use bundled certificates as primary source
|
|
414
|
-
// This works reliably across all platforms (Windows, macOS, Linux)
|
|
415
|
-
ca = bundledCerts || undefined;
|
|
416
|
-
if (ca && process.env.DEBUG) {
|
|
417
|
-
console.log(`✓ Using bundled CA certificates (${Array.isArray(ca) ? ca.length : 1} certificates)`);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
271
|
|
|
421
272
|
// Check various ways SSL validation can be disabled (in order of precedence)
|
|
422
273
|
if (this.config.ignoreSslErrors) {
|
|
@@ -434,25 +285,6 @@ export class TestLensReporter implements Reporter {
|
|
|
434
285
|
}
|
|
435
286
|
|
|
436
287
|
// Set up axios instance with retry logic and enhanced SSL handling
|
|
437
|
-
const httpsAgentOptions: https.AgentOptions = {
|
|
438
|
-
rejectUnauthorized: rejectUnauthorized,
|
|
439
|
-
// Allow any TLS version for better compatibility
|
|
440
|
-
minVersion: 'TLSv1.2',
|
|
441
|
-
maxVersion: 'TLSv1.3'
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
// Add CA certificates if available
|
|
445
|
-
// On Windows, ca will be undefined to let Node.js use Windows certificate store automatically
|
|
446
|
-
// On Unix systems, ca will contain certificates if found, or undefined to use Node.js defaults
|
|
447
|
-
if (ca !== undefined) {
|
|
448
|
-
if (Array.isArray(ca) && ca.length > 0) {
|
|
449
|
-
httpsAgentOptions.ca = ca;
|
|
450
|
-
} else if (typeof ca === 'string' || Buffer.isBuffer(ca)) {
|
|
451
|
-
httpsAgentOptions.ca = ca;
|
|
452
|
-
}
|
|
453
|
-
// If ca is undefined, we don't set it, allowing Node.js to use its default certificate store
|
|
454
|
-
}
|
|
455
|
-
|
|
456
288
|
this.axiosInstance = axios.create({
|
|
457
289
|
baseURL: this.config.apiEndpoint,
|
|
458
290
|
timeout: this.config.timeout,
|
|
@@ -461,7 +293,12 @@ export class TestLensReporter implements Reporter {
|
|
|
461
293
|
...(this.config.apiKey && { 'X-API-Key': this.config.apiKey }),
|
|
462
294
|
},
|
|
463
295
|
// Enhanced SSL handling with flexible TLS configuration
|
|
464
|
-
httpsAgent: new https.Agent(
|
|
296
|
+
httpsAgent: new https.Agent({
|
|
297
|
+
rejectUnauthorized: rejectUnauthorized,
|
|
298
|
+
// Allow any TLS version for better compatibility
|
|
299
|
+
minVersion: 'TLSv1.2',
|
|
300
|
+
maxVersion: 'TLSv1.3'
|
|
301
|
+
})
|
|
465
302
|
});
|
|
466
303
|
|
|
467
304
|
// Add retry interceptor
|
|
@@ -1039,68 +876,17 @@ export class TestLensReporter implements Reporter {
|
|
|
1039
876
|
} else {
|
|
1040
877
|
console.error(`❌ Authentication failed: ${errorData?.error || 'Invalid API key'}`);
|
|
1041
878
|
}
|
|
1042
|
-
} else {
|
|
1043
|
-
//
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
console.error('\n' + '='.repeat(80));
|
|
1054
|
-
console.error('❌ SSL Certificate Error');
|
|
1055
|
-
console.error('='.repeat(80));
|
|
1056
|
-
console.error('');
|
|
1057
|
-
console.error(`Failed to send ${payload.type} event to TestLens due to SSL certificate issue.`);
|
|
1058
|
-
console.error('');
|
|
1059
|
-
console.error('The reporter automatically attempts to detect and use system CA certificates.');
|
|
1060
|
-
console.error('If this error persists, it may indicate:');
|
|
1061
|
-
console.error(' - Missing or outdated system CA certificates');
|
|
1062
|
-
console.error(' - Corporate proxy with custom CA certificate');
|
|
1063
|
-
console.error(' - Incomplete certificate chain from the server');
|
|
1064
|
-
console.error('');
|
|
1065
|
-
console.error('Error details:');
|
|
1066
|
-
console.error(` Code: ${error?.code || 'Unknown'}`);
|
|
1067
|
-
console.error(` Message: ${error?.message || 'Unknown error'}`);
|
|
1068
|
-
console.error('');
|
|
1069
|
-
console.error('Possible solutions:');
|
|
1070
|
-
console.error('');
|
|
1071
|
-
console.error('1. Update your system\'s CA certificate store:');
|
|
1072
|
-
console.error(' - Windows: Update Windows root certificates via Windows Update');
|
|
1073
|
-
console.error(' - macOS: Run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate.pem>');
|
|
1074
|
-
console.error(' - Linux: Update ca-certificates package: sudo apt-get update && sudo apt-get install ca-certificates');
|
|
1075
|
-
console.error('');
|
|
1076
|
-
console.error('2. If you have a custom CA certificate file (e.g., from corporate proxy),');
|
|
1077
|
-
console.error(' you can specify it in your config (optional):');
|
|
1078
|
-
console.error(' reporter: [');
|
|
1079
|
-
console.error(' [\'@testlens/playwright-reporter\', {');
|
|
1080
|
-
console.error(' caCertificate: \'/path/to/your/ca-certificate.pem\'');
|
|
1081
|
-
console.error(' }]');
|
|
1082
|
-
console.error(' ]');
|
|
1083
|
-
console.error('');
|
|
1084
|
-
console.error('3. Contact your network administrator if you\'re behind a corporate proxy');
|
|
1085
|
-
console.error(' that uses a custom CA certificate.');
|
|
1086
|
-
console.error('');
|
|
1087
|
-
console.error('⚠️ WARNING: Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables SSL verification');
|
|
1088
|
-
console.error(' and is insecure. Only use this as a last resort in development.');
|
|
1089
|
-
console.error('');
|
|
1090
|
-
console.error('='.repeat(80));
|
|
1091
|
-
console.error('');
|
|
1092
|
-
} else if (status !== 403) {
|
|
1093
|
-
// Log other errors (but not 403 which we handled above)
|
|
1094
|
-
console.error(`❌ Failed to send ${payload.type} event to TestLens:`, {
|
|
1095
|
-
message: error?.message || 'Unknown error',
|
|
1096
|
-
status: status,
|
|
1097
|
-
statusText: error?.response?.statusText,
|
|
1098
|
-
data: errorData,
|
|
1099
|
-
code: error?.code,
|
|
1100
|
-
url: error?.config?.url,
|
|
1101
|
-
method: error?.config?.method
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
879
|
+
} else if (status !== 403) {
|
|
880
|
+
// Log other errors (but not 403 which we handled above)
|
|
881
|
+
console.error(`❌ Failed to send ${payload.type} event to TestLens:`, {
|
|
882
|
+
message: error?.message || 'Unknown error',
|
|
883
|
+
status: status,
|
|
884
|
+
statusText: error?.response?.statusText,
|
|
885
|
+
data: errorData,
|
|
886
|
+
code: error?.code,
|
|
887
|
+
url: error?.config?.url,
|
|
888
|
+
method: error?.config?.method
|
|
889
|
+
});
|
|
1104
890
|
}
|
|
1105
891
|
|
|
1106
892
|
// Don't throw error to avoid breaking test execution
|
|
@@ -1236,58 +1022,7 @@ export class TestLensReporter implements Reporter {
|
|
|
1236
1022
|
return;
|
|
1237
1023
|
}
|
|
1238
1024
|
|
|
1239
|
-
|
|
1240
|
-
const isSslError = error?.code === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' ||
|
|
1241
|
-
error?.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
|
|
1242
|
-
error?.code === 'CERT_HAS_EXPIRED' ||
|
|
1243
|
-
error?.code === 'SELF_SIGNED_CERT_IN_CHAIN' ||
|
|
1244
|
-
error?.message?.includes('certificate') ||
|
|
1245
|
-
error?.message?.includes('SSL') ||
|
|
1246
|
-
error?.message?.includes('TLS');
|
|
1247
|
-
|
|
1248
|
-
if (isSslError) {
|
|
1249
|
-
console.error('\n' + '='.repeat(80));
|
|
1250
|
-
console.error('❌ SSL Certificate Error');
|
|
1251
|
-
console.error('='.repeat(80));
|
|
1252
|
-
console.error('');
|
|
1253
|
-
console.error('Failed to send spec code blocks due to SSL certificate issue.');
|
|
1254
|
-
console.error('');
|
|
1255
|
-
console.error('The reporter automatically attempts to detect and use system CA certificates.');
|
|
1256
|
-
console.error('If this error persists, it may indicate:');
|
|
1257
|
-
console.error(' - Missing or outdated system CA certificates');
|
|
1258
|
-
console.error(' - Corporate proxy with custom CA certificate');
|
|
1259
|
-
console.error(' - Incomplete certificate chain from the server');
|
|
1260
|
-
console.error('');
|
|
1261
|
-
console.error('Error details:');
|
|
1262
|
-
console.error(` Code: ${error?.code || 'Unknown'}`);
|
|
1263
|
-
console.error(` Message: ${error?.message || 'Unknown error'}`);
|
|
1264
|
-
console.error('');
|
|
1265
|
-
console.error('Possible solutions:');
|
|
1266
|
-
console.error('');
|
|
1267
|
-
console.error('1. Update your system\'s CA certificate store:');
|
|
1268
|
-
console.error(' - Windows: Update Windows root certificates via Windows Update');
|
|
1269
|
-
console.error(' - macOS: Run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate.pem>');
|
|
1270
|
-
console.error(' - Linux: Update ca-certificates package: sudo apt-get update && sudo apt-get install ca-certificates');
|
|
1271
|
-
console.error('');
|
|
1272
|
-
console.error('2. If you have a custom CA certificate file (e.g., from corporate proxy),');
|
|
1273
|
-
console.error(' you can specify it in your config (optional):');
|
|
1274
|
-
console.error(' reporter: [');
|
|
1275
|
-
console.error(' [\'@testlens/playwright-reporter\', {');
|
|
1276
|
-
console.error(' caCertificate: \'/path/to/your/ca-certificate.pem\'');
|
|
1277
|
-
console.error(' }]');
|
|
1278
|
-
console.error(' ]');
|
|
1279
|
-
console.error('');
|
|
1280
|
-
console.error('3. Contact your network administrator if you\'re behind a corporate proxy');
|
|
1281
|
-
console.error(' that uses a custom CA certificate.');
|
|
1282
|
-
console.error('');
|
|
1283
|
-
console.error('⚠️ WARNING: Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables SSL verification');
|
|
1284
|
-
console.error(' and is insecure. Only use this as a last resort in development.');
|
|
1285
|
-
console.error('');
|
|
1286
|
-
console.error('='.repeat(80));
|
|
1287
|
-
console.error('');
|
|
1288
|
-
} else {
|
|
1289
|
-
console.error('Failed to send spec code blocks:', errorData || error?.message || 'Unknown error');
|
|
1290
|
-
}
|
|
1025
|
+
console.error('Failed to send spec code blocks:', errorData || error?.message || 'Unknown error');
|
|
1291
1026
|
}
|
|
1292
1027
|
}
|
|
1293
1028
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alternative-path/testlens-playwright-reporter",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Universal Playwright reporter for TestLens - works with both TypeScript and JavaScript projects",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
"lib/",
|
|
15
15
|
"postinstall.js",
|
|
16
16
|
"cross-env.js",
|
|
17
|
-
"testlens-ca-bundle.pem",
|
|
18
17
|
"README.md",
|
|
19
18
|
"CHANGELOG.md"
|
|
20
19
|
],
|
package/testlens-ca-bundle.pem
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
-----BEGIN CERTIFICATE-----
|
|
2
|
-
MIIFvDCCBKSgAwIBAgIQCCpc5jpiqFvmHWmaKaa8zTANBgkqhkiG9w0BAQsFADA8
|
|
3
|
-
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
|
|
4
|
-
UlNBIDIwNDggTTA0MB4XDTI1MTExNDAwMDAwMFoXDTI2MTIxMzIzNTk1OVowGDEW
|
|
5
|
-
MBQGA1UEAwwNKi5xYS1wYXRoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
|
6
|
-
AQoCggEBAMFsdDGpKLNQ9GayoFXQpE9VLNxEZ/76AaiJMj30Nkuf245KxcPdmPMQ
|
|
7
|
-
rklyBsKv2r4vGwqIrIh4ey59Zpi5z/GMtSP6DwPU/MGGRQGJ9Mpc2dhpxNvka7hW
|
|
8
|
-
9+t/uFAMbwvAhAe82fahsd6q/jtRMChkKQ2Ndln41PPnTPzqqoc2GWdYJO69W1x0
|
|
9
|
-
5CbovMOOoGKkskrS2TNe5+vYp8c8AWR6ga3zR2lxMVDAAXKcD/ejMq/FMR8TD9rf
|
|
10
|
-
6pWnsalQE7UAIgSltu9hrJRttCnyC6343WIQKspd3x+fZ6WdqtR4YywLij9DMBgJ
|
|
11
|
-
KwYUHMjoY4lfkSgowhgnuCUFeqVhBrsCAwEAAaOCAtwwggLYMB8GA1UdIwQYMBaA
|
|
12
|
-
FB9SkmFWglR/gWbYHT0KqjJch90IMB0GA1UdDgQWBBSsbNiBXRvG7yzfgQnHA4Fm
|
|
13
|
-
Gvve1TAYBgNVHREEETAPgg0qLnFhLXBhdGguY29tMBMGA1UdIAQMMAowCAYGZ4EM
|
|
14
|
-
AQIBMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATA7BgNVHR8E
|
|
15
|
-
NDAyMDCgLqAshipodHRwOi8vY3JsLnIybTA0LmFtYXpvbnRydXN0LmNvbS9yMm0w
|
|
16
|
-
NC5jcmwwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5y
|
|
17
|
-
Mm0wNC5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQucjJt
|
|
18
|
-
MDQuYW1hem9udHJ1c3QuY29tL3IybTA0LmNlcjAMBgNVHRMBAf8EAjAAMIIBfgYK
|
|
19
|
-
KwYBBAHWeQIEAgSCAW4EggFqAWgAdgDYCVU7lE96/8gWGW+UT4WrsPj8XodVJg8V
|
|
20
|
-
0S5yu0VLFAAAAZqBmF/qAAAEAwBHMEUCIHg3mktTsuS8r57mR014haS8fqwcbqa1
|
|
21
|
-
P3so9Qd02JFBAiEAsHQf6eH9AL0HoG5jEVfz4aZdNp/Y8unnDO+ZWSfW/wcAdgDC
|
|
22
|
-
MX5XRRmjRe5/ON6ykEHrx8IhWiK/f9W1rXaa2Q5SzQAAAZqBmF/lAAAEAwBHMEUC
|
|
23
|
-
IQCZhIaG3vpxTThIdHhvNCymkHGKFLggUBcPCqYMdYVFpAIgW+BszH9Kdon3IKNJ
|
|
24
|
-
xKx5e4K+XZ+NhfXqqnCmPYeCwzQAdgCUTkOH+uzB74HzGSQmqBhlAcfTXzgCAT9y
|
|
25
|
-
Z31VNy4Z2AAAAZqBmF/1AAAEAwBHMEUCIQDGh+jKNI6NO30js2yl0ItBltCDGA5d
|
|
26
|
-
3A1qoPf81FCF8wIgFTxoXXotS8nhDzOeyJh1wL6wKMxcwKXUUMcOKEjFsH4wDQYJ
|
|
27
|
-
KoZIhvcNAQELBQADggEBAMY6zXuf7YSu4s/nHd4qSjOq7mAPvWKSumPMXcRp4FfX
|
|
28
|
-
16dAyqaiasX2B7dXccks4QeCUyNxCjh89irTYwgDcde8J05PEM9dpxUglyWE6gEB
|
|
29
|
-
r+pp8xJzT9hP2TmLhkNsFKhiT8aR+wz9fiALVDeQLyUS1GOSmnAXbH8MjZkm5Cxb
|
|
30
|
-
Taqb+N8alKrMf7Y9Cwf77KRFpKqm+b1e6h/EuVIJWAFau1jKVS5Qd6KTjyf0sRys
|
|
31
|
-
7nvF3JqKVIb6BlTimNUq1wYMJKX6mOb/MlHo8juzKMb+MYUA5ZHrO36u3nOgThiI
|
|
32
|
-
oOJavnwzLhk7AWp8urdy9yTj8P3b/3H3VtCfYMeAabE=
|
|
33
|
-
-----END CERTIFICATE-----
|
|
34
|
-
|
|
35
|
-
-----BEGIN CERTIFICATE-----
|
|
36
|
-
MIIEXjCCA0agAwIBAgITB3MSTyqVLj7Rili9uF0bwM5fJzANBgkqhkiG9w0BAQsF
|
|
37
|
-
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
|
|
38
|
-
b24gUm9vdCBDQSAxMB4XDTIyMDgyMzIyMjYzNVoXDTMwMDgyMzIyMjYzNVowPDEL
|
|
39
|
-
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEcMBoGA1UEAxMTQW1hem9uIFJT
|
|
40
|
-
QSAyMDQ4IE0wNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM3pVR6A
|
|
41
|
-
lQOp4xe776FdePXyejgA38mYx1ou9/jrpV6Sfn+/oqBKgwhY6ePsQHHQayWBJdBn
|
|
42
|
-
v4Wz363qRI4XUh9swBFJ11TnZ3LqOMvHmWq2+loA0QPtOfXdJ2fHBLrBrngtJ/GB
|
|
43
|
-
0p5olAVYrSZgvQGP16Rf8ddtNyxEEhYm3HuhmNi+vSeAq1tLYJPAvRCXonTpWdSD
|
|
44
|
-
xY6hvdmxlqTYi82AtBXSfpGQ58HHM0hw0C6aQakghrwWi5fGslLOqzpimNMIsT7c
|
|
45
|
-
qa0GJx6JfKqJqmQQNplO2h8n9ZsFJgBowof01ppdoLAWg6caMOM0om/VILKaa30F
|
|
46
|
-
9W/r8Qjah7ltGVkCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD
|
|
47
|
-
VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNV
|
|
48
|
-
HQ4EFgQUH1KSYVaCVH+BZtgdPQqqMlyH3QgwHwYDVR0jBBgwFoAUhBjMhTTsvAyU
|
|
49
|
-
lC4IWZzHshBOCggwewYIKwYBBQUHAQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8v
|
|
50
|
-
b2NzcC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDov
|
|
51
|
-
L2NydC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8E
|
|
52
|
-
ODA2MDSgMqAwhi5odHRwOi8vY3JsLnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jv
|
|
53
|
-
b3RjYTEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IB
|
|
54
|
-
AQA+1O5UsAaNuW3lHzJtpNGwBnZd9QEYFtxpiAnIaV4qApnGS9OCw5ZPwie7YSlD
|
|
55
|
-
ZF5yyFPsFhUC2Q9uJHY/CRV1b5hIiGH0+6+w5PgKiY1MWuWT8VAaJjFxvuhM7a/e
|
|
56
|
-
fN2TIw1Wd6WCl6YRisunjQOrSP+unqC8A540JNyZ1JOE3jVqat3OZBGgMvihdj2w
|
|
57
|
-
Y23EpwesrKiQzkHzmvSH67PVW4ycbPy08HVZnBxZ5NrlGG9bwXR3fNTaz+c+Ej6c
|
|
58
|
-
5AnwI3qkOFgSkg3Y75cdFz6pO/olK+e3AqygAcv0WjzmkDPuBjssuZjCHMC56oH3
|
|
59
|
-
GJkV29Di2j5prHJbwZjG1inU
|
|
60
|
-
-----END CERTIFICATE-----
|
|
61
|
-
|
|
62
|
-
-----BEGIN CERTIFICATE-----
|
|
63
|
-
MIIEkjCCA3qgAwIBAgITBn+USionzfP6wq4rAfkI7rnExjANBgkqhkiG9w0BAQsF
|
|
64
|
-
ADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNj
|
|
65
|
-
b3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4x
|
|
66
|
-
OzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1
|
|
67
|
-
dGhvcml0eSAtIEcyMB4XDTE1MDUyNTEyMDAwMFoXDTM3MTIzMTAxMDAwMFowOTEL
|
|
68
|
-
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
|
|
69
|
-
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
|
|
70
|
-
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
|
|
71
|
-
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
|
|
72
|
-
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
|
|
73
|
-
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
|
|
74
|
-
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
|
|
75
|
-
jgSubJrIqg0CAwEAAaOCATEwggEtMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
|
|
76
|
-
BAQDAgGGMB0GA1UdDgQWBBSEGMyFNOy8DJSULghZnMeyEE4KCDAfBgNVHSMEGDAW
|
|
77
|
-
gBScXwDfqgHXMCs4iKK4bUqc8hGRgzB4BggrBgEFBQcBAQRsMGowLgYIKwYBBQUH
|
|
78
|
-
MAGGImh0dHA6Ly9vY3NwLnJvb3RnMi5hbWF6b250cnVzdC5jb20wOAYIKwYBBQUH
|
|
79
|
-
MAKGLGh0dHA6Ly9jcnQucm9vdGcyLmFtYXpvbnRydXN0LmNvbS9yb290ZzIuY2Vy
|
|
80
|
-
MD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwucm9vdGcyLmFtYXpvbnRydXN0
|
|
81
|
-
LmNvbS9yb290ZzIuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsF
|
|
82
|
-
AAOCAQEAYjdCXLwQtT6LLOkMm2xF4gcAevnFWAu5CIw+7bMlPLVvUOTNNWqnkzSW
|
|
83
|
-
MiGpSESrnO09tKpzbeR/FoCJbM8oAxiDR3mjEH4wW6w7sGDgd9QIpuEdfF7Au/ma
|
|
84
|
-
eyKdpwAJfqxGF4PcnCZXmTA5YpaP7dreqsXMGz7KQ2hsVxa81Q4gLv7/wmpdLqBK
|
|
85
|
-
bRRYh5TmOTFffHPLkIhqhBGWJ6bt2YFGpn6jcgAKUj6DiAdjd4lpFw85hdKrCEVN
|
|
86
|
-
0FE6/V1dN2RMfjCyVSRCnTawXZwXgWHxyvkQAiSr6w10kY17RSlQOYiypok1JR4U
|
|
87
|
-
akcjMS9cmvqtmg5iUaQqqcT5NJ0hGA==
|
|
88
|
-
-----END CERTIFICATE-----
|