@alternative-path/testlens-playwright-reporter 0.3.7 → 0.3.8
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 +4 -0
- package/index.js +202 -18
- package/index.ts +222 -18
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface TestLensReporterConfig {
|
|
|
26
26
|
rejectUnauthorized?: boolean;
|
|
27
27
|
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
28
28
|
ignoreSslErrors?: boolean;
|
|
29
|
+
/** Path to a custom CA certificate file (PEM format) to use for SSL verification */
|
|
30
|
+
caCertificate?: string;
|
|
29
31
|
/** Custom metadata from CLI arguments (automatically parsed from --key=value arguments) */
|
|
30
32
|
customMetadata?: Record<string, string | string[]>;
|
|
31
33
|
}
|
|
@@ -56,6 +58,8 @@ export interface TestLensReporterOptions {
|
|
|
56
58
|
rejectUnauthorized?: boolean;
|
|
57
59
|
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
58
60
|
ignoreSslErrors?: boolean;
|
|
61
|
+
/** Path to a custom CA certificate file (PEM format) to use for SSL verification */
|
|
62
|
+
caCertificate?: string;
|
|
59
63
|
/** Custom metadata from CLI arguments (automatically parsed from --key=value arguments) */
|
|
60
64
|
customMetadata?: Record<string, string | string[]>;
|
|
61
65
|
}
|
package/index.js
CHANGED
|
@@ -20,6 +20,51 @@ async function getMime() {
|
|
|
20
20
|
return mimeModule;
|
|
21
21
|
}
|
|
22
22
|
class TestLensReporter {
|
|
23
|
+
/**
|
|
24
|
+
* Automatically detect and load system CA certificates
|
|
25
|
+
* Tries multiple common system certificate locations
|
|
26
|
+
*/
|
|
27
|
+
static getSystemCaCertificates() {
|
|
28
|
+
const certificates = [];
|
|
29
|
+
const platform = os.platform();
|
|
30
|
+
// Common certificate store locations by platform
|
|
31
|
+
const certPaths = [];
|
|
32
|
+
if (platform === 'win32') {
|
|
33
|
+
// Windows: Node.js uses Windows certificate store automatically
|
|
34
|
+
// But we can also check common locations
|
|
35
|
+
const winPaths = [
|
|
36
|
+
process.env.CERT_PATH,
|
|
37
|
+
'C:\\Windows\\System32\\certmgr.msc', // Not a file, but indicates cert store
|
|
38
|
+
];
|
|
39
|
+
certPaths.push(...winPaths.filter(Boolean));
|
|
40
|
+
}
|
|
41
|
+
else if (platform === 'darwin') {
|
|
42
|
+
// macOS: Common certificate locations
|
|
43
|
+
certPaths.push('/etc/ssl/cert.pem', '/usr/local/etc/openssl/cert.pem', '/opt/homebrew/etc/openssl/cert.pem', '/System/Library/OpenSSL/certs/cert.pem');
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// Linux and other Unix-like systems
|
|
47
|
+
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');
|
|
48
|
+
}
|
|
49
|
+
// Try to load certificates from common locations
|
|
50
|
+
for (const certPath of certPaths) {
|
|
51
|
+
try {
|
|
52
|
+
if (certPath && fs.existsSync(certPath)) {
|
|
53
|
+
const certData = fs.readFileSync(certPath);
|
|
54
|
+
certificates.push(certData);
|
|
55
|
+
// Only log in debug mode to avoid noise
|
|
56
|
+
if (process.env.DEBUG) {
|
|
57
|
+
console.log(`✓ Loaded CA certificates from: ${certPath}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// Silently continue if a certificate file can't be read
|
|
63
|
+
// This is expected as not all paths will exist on every system
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return certificates;
|
|
67
|
+
}
|
|
23
68
|
/**
|
|
24
69
|
* Parse custom metadata from environment variables
|
|
25
70
|
* Checks for common metadata environment variables
|
|
@@ -97,6 +142,37 @@ class TestLensReporter {
|
|
|
97
142
|
}
|
|
98
143
|
// Determine SSL validation behavior
|
|
99
144
|
let rejectUnauthorized = true; // Default to secure
|
|
145
|
+
let ca = undefined;
|
|
146
|
+
// Automatically detect and load system CA certificates
|
|
147
|
+
// This helps resolve "unable to get local issuer certificate" errors
|
|
148
|
+
const systemCerts = TestLensReporter.getSystemCaCertificates();
|
|
149
|
+
// Load custom CA certificate if explicitly provided (for advanced users)
|
|
150
|
+
if (this.config.caCertificate) {
|
|
151
|
+
try {
|
|
152
|
+
if (fs.existsSync(this.config.caCertificate)) {
|
|
153
|
+
const customCert = fs.readFileSync(this.config.caCertificate);
|
|
154
|
+
// Combine system certs with custom cert
|
|
155
|
+
ca = systemCerts.length > 0 ? [...systemCerts, customCert] : customCert;
|
|
156
|
+
console.log(`✓ Using custom CA certificate: ${this.config.caCertificate}`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
console.warn(`⚠️ CA certificate file not found: ${this.config.caCertificate}`);
|
|
160
|
+
// Fall back to system certs if custom cert not found
|
|
161
|
+
ca = systemCerts.length > 0 ? systemCerts : undefined;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
console.warn(`⚠️ Failed to read CA certificate file: ${this.config.caCertificate}`, error.message);
|
|
166
|
+
// Fall back to system certs if custom cert read fails
|
|
167
|
+
ca = systemCerts.length > 0 ? systemCerts : undefined;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Use automatically detected system certificates
|
|
172
|
+
ca = systemCerts.length > 0 ? systemCerts : undefined;
|
|
173
|
+
// Node.js will use system default CA store if we don't specify 'ca'
|
|
174
|
+
// But providing system certs explicitly can help in some environments
|
|
175
|
+
}
|
|
100
176
|
// Check various ways SSL validation can be disabled (in order of precedence)
|
|
101
177
|
if (this.config.ignoreSslErrors) {
|
|
102
178
|
// Explicit configuration option
|
|
@@ -114,6 +190,17 @@ class TestLensReporter {
|
|
|
114
190
|
console.log('⚠️ SSL certificate validation disabled via NODE_TLS_REJECT_UNAUTHORIZED environment variable');
|
|
115
191
|
}
|
|
116
192
|
// Set up axios instance with retry logic and enhanced SSL handling
|
|
193
|
+
const httpsAgentOptions = {
|
|
194
|
+
rejectUnauthorized: rejectUnauthorized,
|
|
195
|
+
// Allow any TLS version for better compatibility
|
|
196
|
+
minVersion: 'TLSv1.2',
|
|
197
|
+
maxVersion: 'TLSv1.3'
|
|
198
|
+
};
|
|
199
|
+
// Add CA certificates if available (Node.js will use system defaults if not specified)
|
|
200
|
+
// Explicitly setting 'ca' can help in environments where Node.js doesn't find certs automatically
|
|
201
|
+
if (ca && ca.length > 0) {
|
|
202
|
+
httpsAgentOptions.ca = ca;
|
|
203
|
+
}
|
|
117
204
|
this.axiosInstance = axios_1.default.create({
|
|
118
205
|
baseURL: this.config.apiEndpoint,
|
|
119
206
|
timeout: this.config.timeout,
|
|
@@ -122,12 +209,7 @@ class TestLensReporter {
|
|
|
122
209
|
...(this.config.apiKey && { 'X-API-Key': this.config.apiKey }),
|
|
123
210
|
},
|
|
124
211
|
// Enhanced SSL handling with flexible TLS configuration
|
|
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
|
-
})
|
|
212
|
+
httpsAgent: new https.Agent(httpsAgentOptions)
|
|
131
213
|
});
|
|
132
214
|
// Add retry interceptor
|
|
133
215
|
this.axiosInstance.interceptors.response.use((response) => response, async (error) => {
|
|
@@ -647,17 +729,68 @@ class TestLensReporter {
|
|
|
647
729
|
console.error(`❌ Authentication failed: ${errorData?.error || 'Invalid API key'}`);
|
|
648
730
|
}
|
|
649
731
|
}
|
|
650
|
-
else
|
|
651
|
-
//
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
732
|
+
else {
|
|
733
|
+
// Check for SSL certificate errors
|
|
734
|
+
const isSslError = error?.code === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' ||
|
|
735
|
+
error?.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
|
|
736
|
+
error?.code === 'CERT_HAS_EXPIRED' ||
|
|
737
|
+
error?.code === 'SELF_SIGNED_CERT_IN_CHAIN' ||
|
|
738
|
+
error?.message?.includes('certificate') ||
|
|
739
|
+
error?.message?.includes('SSL') ||
|
|
740
|
+
error?.message?.includes('TLS');
|
|
741
|
+
if (isSslError && status !== 403) {
|
|
742
|
+
console.error('\n' + '='.repeat(80));
|
|
743
|
+
console.error('❌ SSL Certificate Error');
|
|
744
|
+
console.error('='.repeat(80));
|
|
745
|
+
console.error('');
|
|
746
|
+
console.error(`Failed to send ${payload.type} event to TestLens due to SSL certificate issue.`);
|
|
747
|
+
console.error('');
|
|
748
|
+
console.error('The reporter automatically attempts to detect and use system CA certificates.');
|
|
749
|
+
console.error('If this error persists, it may indicate:');
|
|
750
|
+
console.error(' - Missing or outdated system CA certificates');
|
|
751
|
+
console.error(' - Corporate proxy with custom CA certificate');
|
|
752
|
+
console.error(' - Incomplete certificate chain from the server');
|
|
753
|
+
console.error('');
|
|
754
|
+
console.error('Error details:');
|
|
755
|
+
console.error(` Code: ${error?.code || 'Unknown'}`);
|
|
756
|
+
console.error(` Message: ${error?.message || 'Unknown error'}`);
|
|
757
|
+
console.error('');
|
|
758
|
+
console.error('Possible solutions:');
|
|
759
|
+
console.error('');
|
|
760
|
+
console.error('1. Update your system\'s CA certificate store:');
|
|
761
|
+
console.error(' - Windows: Update Windows root certificates via Windows Update');
|
|
762
|
+
console.error(' - macOS: Run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate.pem>');
|
|
763
|
+
console.error(' - Linux: Update ca-certificates package: sudo apt-get update && sudo apt-get install ca-certificates');
|
|
764
|
+
console.error('');
|
|
765
|
+
console.error('2. If you have a custom CA certificate file (e.g., from corporate proxy),');
|
|
766
|
+
console.error(' you can specify it in your config (optional):');
|
|
767
|
+
console.error(' reporter: [');
|
|
768
|
+
console.error(' [\'@testlens/playwright-reporter\', {');
|
|
769
|
+
console.error(' caCertificate: \'/path/to/your/ca-certificate.pem\'');
|
|
770
|
+
console.error(' }]');
|
|
771
|
+
console.error(' ]');
|
|
772
|
+
console.error('');
|
|
773
|
+
console.error('3. Contact your network administrator if you\'re behind a corporate proxy');
|
|
774
|
+
console.error(' that uses a custom CA certificate.');
|
|
775
|
+
console.error('');
|
|
776
|
+
console.error('⚠️ WARNING: Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables SSL verification');
|
|
777
|
+
console.error(' and is insecure. Only use this as a last resort in development.');
|
|
778
|
+
console.error('');
|
|
779
|
+
console.error('='.repeat(80));
|
|
780
|
+
console.error('');
|
|
781
|
+
}
|
|
782
|
+
else if (status !== 403) {
|
|
783
|
+
// Log other errors (but not 403 which we handled above)
|
|
784
|
+
console.error(`❌ Failed to send ${payload.type} event to TestLens:`, {
|
|
785
|
+
message: error?.message || 'Unknown error',
|
|
786
|
+
status: status,
|
|
787
|
+
statusText: error?.response?.statusText,
|
|
788
|
+
data: errorData,
|
|
789
|
+
code: error?.code,
|
|
790
|
+
url: error?.config?.url,
|
|
791
|
+
method: error?.config?.method
|
|
792
|
+
});
|
|
793
|
+
}
|
|
661
794
|
}
|
|
662
795
|
// Don't throw error to avoid breaking test execution
|
|
663
796
|
}
|
|
@@ -776,7 +909,58 @@ class TestLensReporter {
|
|
|
776
909
|
console.log(`ℹ️ Spec code blocks already exist for: ${path.basename(specPath)} (skipped)`);
|
|
777
910
|
return;
|
|
778
911
|
}
|
|
779
|
-
|
|
912
|
+
// Check for SSL certificate errors
|
|
913
|
+
const isSslError = error?.code === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' ||
|
|
914
|
+
error?.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
|
|
915
|
+
error?.code === 'CERT_HAS_EXPIRED' ||
|
|
916
|
+
error?.code === 'SELF_SIGNED_CERT_IN_CHAIN' ||
|
|
917
|
+
error?.message?.includes('certificate') ||
|
|
918
|
+
error?.message?.includes('SSL') ||
|
|
919
|
+
error?.message?.includes('TLS');
|
|
920
|
+
if (isSslError) {
|
|
921
|
+
console.error('\n' + '='.repeat(80));
|
|
922
|
+
console.error('❌ SSL Certificate Error');
|
|
923
|
+
console.error('='.repeat(80));
|
|
924
|
+
console.error('');
|
|
925
|
+
console.error('Failed to send spec code blocks due to SSL certificate issue.');
|
|
926
|
+
console.error('');
|
|
927
|
+
console.error('The reporter automatically attempts to detect and use system CA certificates.');
|
|
928
|
+
console.error('If this error persists, it may indicate:');
|
|
929
|
+
console.error(' - Missing or outdated system CA certificates');
|
|
930
|
+
console.error(' - Corporate proxy with custom CA certificate');
|
|
931
|
+
console.error(' - Incomplete certificate chain from the server');
|
|
932
|
+
console.error('');
|
|
933
|
+
console.error('Error details:');
|
|
934
|
+
console.error(` Code: ${error?.code || 'Unknown'}`);
|
|
935
|
+
console.error(` Message: ${error?.message || 'Unknown error'}`);
|
|
936
|
+
console.error('');
|
|
937
|
+
console.error('Possible solutions:');
|
|
938
|
+
console.error('');
|
|
939
|
+
console.error('1. Update your system\'s CA certificate store:');
|
|
940
|
+
console.error(' - Windows: Update Windows root certificates via Windows Update');
|
|
941
|
+
console.error(' - macOS: Run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate.pem>');
|
|
942
|
+
console.error(' - Linux: Update ca-certificates package: sudo apt-get update && sudo apt-get install ca-certificates');
|
|
943
|
+
console.error('');
|
|
944
|
+
console.error('2. If you have a custom CA certificate file (e.g., from corporate proxy),');
|
|
945
|
+
console.error(' you can specify it in your config (optional):');
|
|
946
|
+
console.error(' reporter: [');
|
|
947
|
+
console.error(' [\'@testlens/playwright-reporter\', {');
|
|
948
|
+
console.error(' caCertificate: \'/path/to/your/ca-certificate.pem\'');
|
|
949
|
+
console.error(' }]');
|
|
950
|
+
console.error(' ]');
|
|
951
|
+
console.error('');
|
|
952
|
+
console.error('3. Contact your network administrator if you\'re behind a corporate proxy');
|
|
953
|
+
console.error(' that uses a custom CA certificate.');
|
|
954
|
+
console.error('');
|
|
955
|
+
console.error('⚠️ WARNING: Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables SSL verification');
|
|
956
|
+
console.error(' and is insecure. Only use this as a last resort in development.');
|
|
957
|
+
console.error('');
|
|
958
|
+
console.error('='.repeat(80));
|
|
959
|
+
console.error('');
|
|
960
|
+
}
|
|
961
|
+
else {
|
|
962
|
+
console.error('Failed to send spec code blocks:', errorData || error?.message || 'Unknown error');
|
|
963
|
+
}
|
|
780
964
|
}
|
|
781
965
|
}
|
|
782
966
|
extractTestBlocks(filePath) {
|
package/index.ts
CHANGED
|
@@ -46,6 +46,8 @@ export interface TestLensReporterConfig {
|
|
|
46
46
|
rejectUnauthorized?: boolean;
|
|
47
47
|
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
48
48
|
ignoreSslErrors?: boolean;
|
|
49
|
+
/** Path to a custom CA certificate file (PEM format) to use for SSL verification */
|
|
50
|
+
caCertificate?: string;
|
|
49
51
|
/** Custom metadata from CLI arguments (automatically parsed from --key=value arguments) */
|
|
50
52
|
customMetadata?: Record<string, string | string[]>;
|
|
51
53
|
}
|
|
@@ -77,6 +79,8 @@ export interface TestLensReporterOptions {
|
|
|
77
79
|
rejectUnauthorized?: boolean;
|
|
78
80
|
/** Alternative SSL option - set to true to ignore SSL certificate errors */
|
|
79
81
|
ignoreSslErrors?: boolean;
|
|
82
|
+
/** Path to a custom CA certificate file (PEM format) to use for SSL verification */
|
|
83
|
+
caCertificate?: string;
|
|
80
84
|
/** Custom metadata from CLI arguments (automatically parsed from --key=value arguments) */
|
|
81
85
|
customMetadata?: Record<string, string | string[]>;
|
|
82
86
|
}
|
|
@@ -178,6 +182,66 @@ export interface SpecData {
|
|
|
178
182
|
export class TestLensReporter implements Reporter {
|
|
179
183
|
private config: Required<TestLensReporterConfig>;
|
|
180
184
|
private axiosInstance: AxiosInstance;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Automatically detect and load system CA certificates
|
|
188
|
+
* Tries multiple common system certificate locations
|
|
189
|
+
*/
|
|
190
|
+
private static getSystemCaCertificates(): Buffer[] {
|
|
191
|
+
const certificates: Buffer[] = [];
|
|
192
|
+
const platform = os.platform();
|
|
193
|
+
|
|
194
|
+
// Common certificate store locations by platform
|
|
195
|
+
const certPaths: string[] = [];
|
|
196
|
+
|
|
197
|
+
if (platform === 'win32') {
|
|
198
|
+
// Windows: Node.js uses Windows certificate store automatically
|
|
199
|
+
// But we can also check common locations
|
|
200
|
+
const winPaths = [
|
|
201
|
+
process.env.CERT_PATH,
|
|
202
|
+
'C:\\Windows\\System32\\certmgr.msc', // Not a file, but indicates cert store
|
|
203
|
+
];
|
|
204
|
+
certPaths.push(...winPaths.filter(Boolean) as string[]);
|
|
205
|
+
} else if (platform === 'darwin') {
|
|
206
|
+
// macOS: Common certificate locations
|
|
207
|
+
certPaths.push(
|
|
208
|
+
'/etc/ssl/cert.pem',
|
|
209
|
+
'/usr/local/etc/openssl/cert.pem',
|
|
210
|
+
'/opt/homebrew/etc/openssl/cert.pem',
|
|
211
|
+
'/System/Library/OpenSSL/certs/cert.pem'
|
|
212
|
+
);
|
|
213
|
+
} else {
|
|
214
|
+
// Linux and other Unix-like systems
|
|
215
|
+
certPaths.push(
|
|
216
|
+
'/etc/ssl/certs/ca-certificates.crt',
|
|
217
|
+
'/etc/ssl/certs/ca-bundle.crt',
|
|
218
|
+
'/etc/pki/tls/certs/ca-bundle.crt',
|
|
219
|
+
'/etc/ssl/ca-bundle.pem',
|
|
220
|
+
'/usr/share/ssl/certs/ca-bundle.crt',
|
|
221
|
+
'/usr/local/share/certs/ca-root-nss.crt',
|
|
222
|
+
'/etc/ca-certificates/extracted/tls-ca-bundle.pem'
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Try to load certificates from common locations
|
|
227
|
+
for (const certPath of certPaths) {
|
|
228
|
+
try {
|
|
229
|
+
if (certPath && fs.existsSync(certPath)) {
|
|
230
|
+
const certData = fs.readFileSync(certPath);
|
|
231
|
+
certificates.push(certData);
|
|
232
|
+
// Only log in debug mode to avoid noise
|
|
233
|
+
if (process.env.DEBUG) {
|
|
234
|
+
console.log(`✓ Loaded CA certificates from: ${certPath}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
// Silently continue if a certificate file can't be read
|
|
239
|
+
// This is expected as not all paths will exist on every system
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return certificates;
|
|
244
|
+
}
|
|
181
245
|
private runId: string;
|
|
182
246
|
private runMetadata: RunMetadata;
|
|
183
247
|
private specMap: Map<string, SpecData>;
|
|
@@ -268,6 +332,36 @@ export class TestLensReporter implements Reporter {
|
|
|
268
332
|
|
|
269
333
|
// Determine SSL validation behavior
|
|
270
334
|
let rejectUnauthorized = true; // Default to secure
|
|
335
|
+
let ca: Buffer | string | Buffer[] | undefined = undefined;
|
|
336
|
+
|
|
337
|
+
// Automatically detect and load system CA certificates
|
|
338
|
+
// This helps resolve "unable to get local issuer certificate" errors
|
|
339
|
+
const systemCerts = TestLensReporter.getSystemCaCertificates();
|
|
340
|
+
|
|
341
|
+
// Load custom CA certificate if explicitly provided (for advanced users)
|
|
342
|
+
if (this.config.caCertificate) {
|
|
343
|
+
try {
|
|
344
|
+
if (fs.existsSync(this.config.caCertificate)) {
|
|
345
|
+
const customCert = fs.readFileSync(this.config.caCertificate);
|
|
346
|
+
// Combine system certs with custom cert
|
|
347
|
+
ca = systemCerts.length > 0 ? [...systemCerts, customCert] : customCert;
|
|
348
|
+
console.log(`✓ Using custom CA certificate: ${this.config.caCertificate}`);
|
|
349
|
+
} else {
|
|
350
|
+
console.warn(`⚠️ CA certificate file not found: ${this.config.caCertificate}`);
|
|
351
|
+
// Fall back to system certs if custom cert not found
|
|
352
|
+
ca = systemCerts.length > 0 ? systemCerts : undefined;
|
|
353
|
+
}
|
|
354
|
+
} catch (error) {
|
|
355
|
+
console.warn(`⚠️ Failed to read CA certificate file: ${this.config.caCertificate}`, (error as Error).message);
|
|
356
|
+
// Fall back to system certs if custom cert read fails
|
|
357
|
+
ca = systemCerts.length > 0 ? systemCerts : undefined;
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
// Use automatically detected system certificates
|
|
361
|
+
ca = systemCerts.length > 0 ? systemCerts : undefined;
|
|
362
|
+
// Node.js will use system default CA store if we don't specify 'ca'
|
|
363
|
+
// But providing system certs explicitly can help in some environments
|
|
364
|
+
}
|
|
271
365
|
|
|
272
366
|
// Check various ways SSL validation can be disabled (in order of precedence)
|
|
273
367
|
if (this.config.ignoreSslErrors) {
|
|
@@ -285,6 +379,19 @@ export class TestLensReporter implements Reporter {
|
|
|
285
379
|
}
|
|
286
380
|
|
|
287
381
|
// Set up axios instance with retry logic and enhanced SSL handling
|
|
382
|
+
const httpsAgentOptions: https.AgentOptions = {
|
|
383
|
+
rejectUnauthorized: rejectUnauthorized,
|
|
384
|
+
// Allow any TLS version for better compatibility
|
|
385
|
+
minVersion: 'TLSv1.2',
|
|
386
|
+
maxVersion: 'TLSv1.3'
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
// Add CA certificates if available (Node.js will use system defaults if not specified)
|
|
390
|
+
// Explicitly setting 'ca' can help in environments where Node.js doesn't find certs automatically
|
|
391
|
+
if (ca && ca.length > 0) {
|
|
392
|
+
httpsAgentOptions.ca = ca;
|
|
393
|
+
}
|
|
394
|
+
|
|
288
395
|
this.axiosInstance = axios.create({
|
|
289
396
|
baseURL: this.config.apiEndpoint,
|
|
290
397
|
timeout: this.config.timeout,
|
|
@@ -293,12 +400,7 @@ export class TestLensReporter implements Reporter {
|
|
|
293
400
|
...(this.config.apiKey && { 'X-API-Key': this.config.apiKey }),
|
|
294
401
|
},
|
|
295
402
|
// Enhanced SSL handling with flexible TLS configuration
|
|
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
|
-
})
|
|
403
|
+
httpsAgent: new https.Agent(httpsAgentOptions)
|
|
302
404
|
});
|
|
303
405
|
|
|
304
406
|
// Add retry interceptor
|
|
@@ -876,17 +978,68 @@ export class TestLensReporter implements Reporter {
|
|
|
876
978
|
} else {
|
|
877
979
|
console.error(`❌ Authentication failed: ${errorData?.error || 'Invalid API key'}`);
|
|
878
980
|
}
|
|
879
|
-
} else
|
|
880
|
-
//
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
981
|
+
} else {
|
|
982
|
+
// Check for SSL certificate errors
|
|
983
|
+
const isSslError = error?.code === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' ||
|
|
984
|
+
error?.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
|
|
985
|
+
error?.code === 'CERT_HAS_EXPIRED' ||
|
|
986
|
+
error?.code === 'SELF_SIGNED_CERT_IN_CHAIN' ||
|
|
987
|
+
error?.message?.includes('certificate') ||
|
|
988
|
+
error?.message?.includes('SSL') ||
|
|
989
|
+
error?.message?.includes('TLS');
|
|
990
|
+
|
|
991
|
+
if (isSslError && status !== 403) {
|
|
992
|
+
console.error('\n' + '='.repeat(80));
|
|
993
|
+
console.error('❌ SSL Certificate Error');
|
|
994
|
+
console.error('='.repeat(80));
|
|
995
|
+
console.error('');
|
|
996
|
+
console.error(`Failed to send ${payload.type} event to TestLens due to SSL certificate issue.`);
|
|
997
|
+
console.error('');
|
|
998
|
+
console.error('The reporter automatically attempts to detect and use system CA certificates.');
|
|
999
|
+
console.error('If this error persists, it may indicate:');
|
|
1000
|
+
console.error(' - Missing or outdated system CA certificates');
|
|
1001
|
+
console.error(' - Corporate proxy with custom CA certificate');
|
|
1002
|
+
console.error(' - Incomplete certificate chain from the server');
|
|
1003
|
+
console.error('');
|
|
1004
|
+
console.error('Error details:');
|
|
1005
|
+
console.error(` Code: ${error?.code || 'Unknown'}`);
|
|
1006
|
+
console.error(` Message: ${error?.message || 'Unknown error'}`);
|
|
1007
|
+
console.error('');
|
|
1008
|
+
console.error('Possible solutions:');
|
|
1009
|
+
console.error('');
|
|
1010
|
+
console.error('1. Update your system\'s CA certificate store:');
|
|
1011
|
+
console.error(' - Windows: Update Windows root certificates via Windows Update');
|
|
1012
|
+
console.error(' - macOS: Run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate.pem>');
|
|
1013
|
+
console.error(' - Linux: Update ca-certificates package: sudo apt-get update && sudo apt-get install ca-certificates');
|
|
1014
|
+
console.error('');
|
|
1015
|
+
console.error('2. If you have a custom CA certificate file (e.g., from corporate proxy),');
|
|
1016
|
+
console.error(' you can specify it in your config (optional):');
|
|
1017
|
+
console.error(' reporter: [');
|
|
1018
|
+
console.error(' [\'@testlens/playwright-reporter\', {');
|
|
1019
|
+
console.error(' caCertificate: \'/path/to/your/ca-certificate.pem\'');
|
|
1020
|
+
console.error(' }]');
|
|
1021
|
+
console.error(' ]');
|
|
1022
|
+
console.error('');
|
|
1023
|
+
console.error('3. Contact your network administrator if you\'re behind a corporate proxy');
|
|
1024
|
+
console.error(' that uses a custom CA certificate.');
|
|
1025
|
+
console.error('');
|
|
1026
|
+
console.error('⚠️ WARNING: Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables SSL verification');
|
|
1027
|
+
console.error(' and is insecure. Only use this as a last resort in development.');
|
|
1028
|
+
console.error('');
|
|
1029
|
+
console.error('='.repeat(80));
|
|
1030
|
+
console.error('');
|
|
1031
|
+
} else if (status !== 403) {
|
|
1032
|
+
// Log other errors (but not 403 which we handled above)
|
|
1033
|
+
console.error(`❌ Failed to send ${payload.type} event to TestLens:`, {
|
|
1034
|
+
message: error?.message || 'Unknown error',
|
|
1035
|
+
status: status,
|
|
1036
|
+
statusText: error?.response?.statusText,
|
|
1037
|
+
data: errorData,
|
|
1038
|
+
code: error?.code,
|
|
1039
|
+
url: error?.config?.url,
|
|
1040
|
+
method: error?.config?.method
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
890
1043
|
}
|
|
891
1044
|
|
|
892
1045
|
// Don't throw error to avoid breaking test execution
|
|
@@ -1022,7 +1175,58 @@ export class TestLensReporter implements Reporter {
|
|
|
1022
1175
|
return;
|
|
1023
1176
|
}
|
|
1024
1177
|
|
|
1025
|
-
|
|
1178
|
+
// Check for SSL certificate errors
|
|
1179
|
+
const isSslError = error?.code === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' ||
|
|
1180
|
+
error?.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
|
|
1181
|
+
error?.code === 'CERT_HAS_EXPIRED' ||
|
|
1182
|
+
error?.code === 'SELF_SIGNED_CERT_IN_CHAIN' ||
|
|
1183
|
+
error?.message?.includes('certificate') ||
|
|
1184
|
+
error?.message?.includes('SSL') ||
|
|
1185
|
+
error?.message?.includes('TLS');
|
|
1186
|
+
|
|
1187
|
+
if (isSslError) {
|
|
1188
|
+
console.error('\n' + '='.repeat(80));
|
|
1189
|
+
console.error('❌ SSL Certificate Error');
|
|
1190
|
+
console.error('='.repeat(80));
|
|
1191
|
+
console.error('');
|
|
1192
|
+
console.error('Failed to send spec code blocks due to SSL certificate issue.');
|
|
1193
|
+
console.error('');
|
|
1194
|
+
console.error('The reporter automatically attempts to detect and use system CA certificates.');
|
|
1195
|
+
console.error('If this error persists, it may indicate:');
|
|
1196
|
+
console.error(' - Missing or outdated system CA certificates');
|
|
1197
|
+
console.error(' - Corporate proxy with custom CA certificate');
|
|
1198
|
+
console.error(' - Incomplete certificate chain from the server');
|
|
1199
|
+
console.error('');
|
|
1200
|
+
console.error('Error details:');
|
|
1201
|
+
console.error(` Code: ${error?.code || 'Unknown'}`);
|
|
1202
|
+
console.error(` Message: ${error?.message || 'Unknown error'}`);
|
|
1203
|
+
console.error('');
|
|
1204
|
+
console.error('Possible solutions:');
|
|
1205
|
+
console.error('');
|
|
1206
|
+
console.error('1. Update your system\'s CA certificate store:');
|
|
1207
|
+
console.error(' - Windows: Update Windows root certificates via Windows Update');
|
|
1208
|
+
console.error(' - macOS: Run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate.pem>');
|
|
1209
|
+
console.error(' - Linux: Update ca-certificates package: sudo apt-get update && sudo apt-get install ca-certificates');
|
|
1210
|
+
console.error('');
|
|
1211
|
+
console.error('2. If you have a custom CA certificate file (e.g., from corporate proxy),');
|
|
1212
|
+
console.error(' you can specify it in your config (optional):');
|
|
1213
|
+
console.error(' reporter: [');
|
|
1214
|
+
console.error(' [\'@testlens/playwright-reporter\', {');
|
|
1215
|
+
console.error(' caCertificate: \'/path/to/your/ca-certificate.pem\'');
|
|
1216
|
+
console.error(' }]');
|
|
1217
|
+
console.error(' ]');
|
|
1218
|
+
console.error('');
|
|
1219
|
+
console.error('3. Contact your network administrator if you\'re behind a corporate proxy');
|
|
1220
|
+
console.error(' that uses a custom CA certificate.');
|
|
1221
|
+
console.error('');
|
|
1222
|
+
console.error('⚠️ WARNING: Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables SSL verification');
|
|
1223
|
+
console.error(' and is insecure. Only use this as a last resort in development.');
|
|
1224
|
+
console.error('');
|
|
1225
|
+
console.error('='.repeat(80));
|
|
1226
|
+
console.error('');
|
|
1227
|
+
} else {
|
|
1228
|
+
console.error('Failed to send spec code blocks:', errorData || error?.message || 'Unknown error');
|
|
1229
|
+
}
|
|
1026
1230
|
}
|
|
1027
1231
|
}
|
|
1028
1232
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alternative-path/testlens-playwright-reporter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
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",
|