@testdino/playwright 1.0.9 → 1.0.11
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/bin/tdpw.js +2 -2
- package/dist/cli/index.mjs +44 -21
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +304 -162
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +204 -77
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +0 -929
- package/dist/cli/index.js.map +0 -1
package/dist/cli/index.js
DELETED
|
@@ -1,929 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
var commander = require('commander');
|
|
5
|
-
var fs = require('fs');
|
|
6
|
-
var path = require('path');
|
|
7
|
-
var url = require('url');
|
|
8
|
-
var jiti = require('jiti');
|
|
9
|
-
var crypto = require('crypto');
|
|
10
|
-
var os = require('os');
|
|
11
|
-
var chalk = require('chalk');
|
|
12
|
-
var execa = require('execa');
|
|
13
|
-
|
|
14
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
15
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
|
-
|
|
17
|
-
var jiti__default = /*#__PURE__*/_interopDefault(jiti);
|
|
18
|
-
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
19
|
-
|
|
20
|
-
// src/cli/errors.ts
|
|
21
|
-
var TestDinoError = class extends Error {
|
|
22
|
-
constructor(message) {
|
|
23
|
-
super(message);
|
|
24
|
-
this.name = "TestDinoError";
|
|
25
|
-
Error.captureStackTrace(this, this.constructor);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
var TokenMissingError = class extends TestDinoError {
|
|
29
|
-
constructor() {
|
|
30
|
-
const message = `Token is required to run tests with TestDino
|
|
31
|
-
|
|
32
|
-
Provide token via:
|
|
33
|
-
\u2022 CLI flag: npx tdpw test --token <your-token>
|
|
34
|
-
\u2022 Environment: export TESTDINO_TOKEN=<your-token>
|
|
35
|
-
\u2022 Config file: Create testdino.config.ts with token
|
|
36
|
-
|
|
37
|
-
Get your token at: https://testdino.com/settings`;
|
|
38
|
-
super(message);
|
|
39
|
-
this.name = "TokenMissingError";
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
var ConfigSyntaxError = class extends TestDinoError {
|
|
43
|
-
constructor(configPath, originalError) {
|
|
44
|
-
const message = `Failed to load ${configPath}
|
|
45
|
-
|
|
46
|
-
${originalError.message}
|
|
47
|
-
|
|
48
|
-
Fix the syntax error and try again.`;
|
|
49
|
-
super(message);
|
|
50
|
-
this.name = "ConfigSyntaxError";
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
var InvalidServerUrlError = class extends TestDinoError {
|
|
54
|
-
constructor(url) {
|
|
55
|
-
const message = `Invalid server URL: ${url}
|
|
56
|
-
|
|
57
|
-
Server URL must be a valid HTTP or HTTPS URL.
|
|
58
|
-
|
|
59
|
-
Examples:
|
|
60
|
-
\u2022 https://api.testdino.com
|
|
61
|
-
\u2022 https://api-v0.testdino.com
|
|
62
|
-
\u2022 https://global.testdino.com`;
|
|
63
|
-
super(message);
|
|
64
|
-
this.name = "InvalidServerUrlError";
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// src/cli/config-loader.ts
|
|
69
|
-
var CONFIG_FILENAMES = ["testdino.config.ts", "testdino.config.js"];
|
|
70
|
-
var ConfigLoader = class {
|
|
71
|
-
cwd;
|
|
72
|
-
constructor(cwd = process.cwd()) {
|
|
73
|
-
this.cwd = cwd;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Load config file from current directory or parent directories
|
|
77
|
-
*/
|
|
78
|
-
async load() {
|
|
79
|
-
const configPath = this.findConfigFile();
|
|
80
|
-
if (!configPath) {
|
|
81
|
-
return { config: {} };
|
|
82
|
-
}
|
|
83
|
-
try {
|
|
84
|
-
const config = this.loadConfigFile(configPath);
|
|
85
|
-
return { config, configPath };
|
|
86
|
-
} catch (error) {
|
|
87
|
-
throw new ConfigSyntaxError(configPath, error instanceof Error ? error : new Error(String(error)));
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Find config file by searching up directory tree
|
|
92
|
-
* Stops at .git directory
|
|
93
|
-
*/
|
|
94
|
-
findConfigFile() {
|
|
95
|
-
let currentDir = this.cwd;
|
|
96
|
-
while (true) {
|
|
97
|
-
for (const filename of CONFIG_FILENAMES) {
|
|
98
|
-
const configPath = path.join(currentDir, filename);
|
|
99
|
-
if (fs.existsSync(configPath)) {
|
|
100
|
-
return configPath;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
const gitDir = path.join(currentDir, ".git");
|
|
104
|
-
if (fs.existsSync(gitDir) && fs.statSync(gitDir).isDirectory()) {
|
|
105
|
-
for (const filename of CONFIG_FILENAMES) {
|
|
106
|
-
const configPath = path.join(currentDir, filename);
|
|
107
|
-
if (fs.existsSync(configPath)) {
|
|
108
|
-
return configPath;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
const parentDir = path.dirname(currentDir);
|
|
114
|
-
if (parentDir === currentDir) {
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
currentDir = parentDir;
|
|
118
|
-
}
|
|
119
|
-
return void 0;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Load and parse config file using jiti
|
|
123
|
-
*/
|
|
124
|
-
loadConfigFile(configPath) {
|
|
125
|
-
const jitiLoader = jiti__default.default(path.dirname(configPath), {
|
|
126
|
-
interopDefault: true,
|
|
127
|
-
cache: false,
|
|
128
|
-
extensions: [".ts", ".js"]
|
|
129
|
-
});
|
|
130
|
-
let loaded;
|
|
131
|
-
try {
|
|
132
|
-
const resolved = jitiLoader.esmResolve(configPath, { try: true });
|
|
133
|
-
if (!resolved) {
|
|
134
|
-
throw new Error(`Could not resolve config file: ${configPath}`);
|
|
135
|
-
}
|
|
136
|
-
const resolvedPath = typeof resolved === "string" ? resolved : url.fileURLToPath(resolved);
|
|
137
|
-
loaded = jitiLoader(resolvedPath);
|
|
138
|
-
} catch (error) {
|
|
139
|
-
throw new Error(`Syntax error: ${error instanceof Error ? error.message : String(error)}`);
|
|
140
|
-
}
|
|
141
|
-
let config;
|
|
142
|
-
if (loaded && typeof loaded === "object" && "__esModule" in loaded) {
|
|
143
|
-
config = loaded.default;
|
|
144
|
-
} else if (loaded && typeof loaded === "object" && "default" in loaded) {
|
|
145
|
-
config = loaded.default;
|
|
146
|
-
} else {
|
|
147
|
-
config = loaded;
|
|
148
|
-
}
|
|
149
|
-
if (config === null || config === void 0) {
|
|
150
|
-
return {};
|
|
151
|
-
}
|
|
152
|
-
if (typeof config === "function") {
|
|
153
|
-
try {
|
|
154
|
-
config = config();
|
|
155
|
-
} catch (error) {
|
|
156
|
-
throw new Error(`Error executing config function: ${error instanceof Error ? error.message : String(error)}`);
|
|
157
|
-
}
|
|
158
|
-
if (config instanceof Promise) {
|
|
159
|
-
throw new Error("Async config functions are not supported");
|
|
160
|
-
}
|
|
161
|
-
if (config === null || config === void 0) {
|
|
162
|
-
return {};
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
if (config && typeof config !== "object") {
|
|
166
|
-
throw new Error("Config must be an object");
|
|
167
|
-
}
|
|
168
|
-
return config ?? {};
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
var PLAYWRIGHT_CONFIG_FILENAMES = ["playwright.config.ts", "playwright.config.js"];
|
|
172
|
-
var TESTDINO_REPORTER_NAMES = ["@testdino/playwright", "testdino-playwright", "TestdinoReporter"];
|
|
173
|
-
function isValidThreshold(value) {
|
|
174
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 100;
|
|
175
|
-
}
|
|
176
|
-
var ConfigDetector = class {
|
|
177
|
-
cwd;
|
|
178
|
-
constructor(cwd = process.cwd()) {
|
|
179
|
-
this.cwd = cwd;
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Detect TestdinoReporter in Playwright config
|
|
183
|
-
*/
|
|
184
|
-
async detect() {
|
|
185
|
-
const configPath = this.findPlaywrightConfig();
|
|
186
|
-
if (!configPath) {
|
|
187
|
-
return { hasReporter: false };
|
|
188
|
-
}
|
|
189
|
-
try {
|
|
190
|
-
const config = this.loadPlaywrightConfig(configPath);
|
|
191
|
-
const result = this.extractTestdinoReporter(config);
|
|
192
|
-
return {
|
|
193
|
-
...result,
|
|
194
|
-
configPath
|
|
195
|
-
};
|
|
196
|
-
} catch (error) {
|
|
197
|
-
throw new ConfigSyntaxError(configPath, error instanceof Error ? error : new Error(String(error)));
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Find playwright.config.[ts|js] in current directory
|
|
202
|
-
*/
|
|
203
|
-
findPlaywrightConfig() {
|
|
204
|
-
for (const filename of PLAYWRIGHT_CONFIG_FILENAMES) {
|
|
205
|
-
const configPath = path.join(this.cwd, filename);
|
|
206
|
-
if (fs.existsSync(configPath)) {
|
|
207
|
-
return configPath;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return void 0;
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Load and parse Playwright config using jiti
|
|
214
|
-
*/
|
|
215
|
-
loadPlaywrightConfig(configPath) {
|
|
216
|
-
const jitiLoader = jiti__default.default(path.dirname(configPath), {
|
|
217
|
-
interopDefault: true,
|
|
218
|
-
cache: false,
|
|
219
|
-
extensions: [".ts", ".js"]
|
|
220
|
-
});
|
|
221
|
-
let loaded;
|
|
222
|
-
try {
|
|
223
|
-
const resolved = jitiLoader.esmResolve(configPath, { try: true });
|
|
224
|
-
if (!resolved) {
|
|
225
|
-
throw new Error(`Could not resolve Playwright config: ${configPath}`);
|
|
226
|
-
}
|
|
227
|
-
const resolvedPath = typeof resolved === "string" ? resolved : url.fileURLToPath(resolved);
|
|
228
|
-
loaded = jitiLoader(resolvedPath);
|
|
229
|
-
} catch (error) {
|
|
230
|
-
throw new Error(`Syntax error: ${error instanceof Error ? error.message : String(error)}`);
|
|
231
|
-
}
|
|
232
|
-
let config;
|
|
233
|
-
if (loaded && typeof loaded === "object" && "__esModule" in loaded) {
|
|
234
|
-
config = loaded.default;
|
|
235
|
-
} else if (loaded && typeof loaded === "object" && "default" in loaded) {
|
|
236
|
-
config = loaded.default;
|
|
237
|
-
} else {
|
|
238
|
-
config = loaded;
|
|
239
|
-
}
|
|
240
|
-
if (typeof config === "function") {
|
|
241
|
-
try {
|
|
242
|
-
config = config();
|
|
243
|
-
} catch (error) {
|
|
244
|
-
throw new Error(`Error executing config function: ${error instanceof Error ? error.message : String(error)}`);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
if (!config || typeof config !== "object") {
|
|
248
|
-
throw new Error("Playwright config must be an object");
|
|
249
|
-
}
|
|
250
|
-
return config;
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Extract TestdinoReporter configuration from Playwright config
|
|
254
|
-
*/
|
|
255
|
-
extractTestdinoReporter(config) {
|
|
256
|
-
const { reporter } = config;
|
|
257
|
-
if (!reporter) {
|
|
258
|
-
return { hasReporter: false };
|
|
259
|
-
}
|
|
260
|
-
if (typeof reporter === "string") {
|
|
261
|
-
if (this.isTestdinoReporter(reporter)) {
|
|
262
|
-
return { hasReporter: true, options: {} };
|
|
263
|
-
}
|
|
264
|
-
return { hasReporter: false };
|
|
265
|
-
}
|
|
266
|
-
if (Array.isArray(reporter) && reporter.length > 0) {
|
|
267
|
-
if (typeof reporter[0] === "string") {
|
|
268
|
-
const [name, options] = reporter;
|
|
269
|
-
if (this.isTestdinoReporter(name)) {
|
|
270
|
-
return {
|
|
271
|
-
hasReporter: true,
|
|
272
|
-
options: this.extractOptions(options)
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
for (const item of reporter) {
|
|
277
|
-
if (typeof item === "string") {
|
|
278
|
-
if (this.isTestdinoReporter(item)) {
|
|
279
|
-
return { hasReporter: true, options: {} };
|
|
280
|
-
}
|
|
281
|
-
} else if (Array.isArray(item) && item.length > 0) {
|
|
282
|
-
const [name, options] = item;
|
|
283
|
-
if (this.isTestdinoReporter(name)) {
|
|
284
|
-
return {
|
|
285
|
-
hasReporter: true,
|
|
286
|
-
options: this.extractOptions(options)
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return { hasReporter: false };
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Check if reporter name matches TestdinoReporter
|
|
296
|
-
*/
|
|
297
|
-
isTestdinoReporter(name) {
|
|
298
|
-
return TESTDINO_REPORTER_NAMES.some((testdinoName) => name === testdinoName || name.includes(testdinoName));
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Extract and validate TestdinoConfig options
|
|
302
|
-
*/
|
|
303
|
-
extractOptions(options) {
|
|
304
|
-
if (!options || typeof options !== "object") {
|
|
305
|
-
return {};
|
|
306
|
-
}
|
|
307
|
-
const config = {};
|
|
308
|
-
if ("token" in options && typeof options.token === "string") {
|
|
309
|
-
config.token = options.token;
|
|
310
|
-
}
|
|
311
|
-
if ("serverUrl" in options && typeof options.serverUrl === "string") {
|
|
312
|
-
config.serverUrl = options.serverUrl;
|
|
313
|
-
}
|
|
314
|
-
if ("ciRunId" in options && typeof options.ciRunId === "string") {
|
|
315
|
-
config.ciRunId = options.ciRunId;
|
|
316
|
-
}
|
|
317
|
-
if ("debug" in options && typeof options.debug === "boolean") {
|
|
318
|
-
config.debug = options.debug;
|
|
319
|
-
}
|
|
320
|
-
if ("coverage" in options && typeof options.coverage === "object" && options.coverage !== null) {
|
|
321
|
-
config.coverage = this.extractCoverageConfig(options.coverage);
|
|
322
|
-
}
|
|
323
|
-
return config;
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Extract and validate CoverageConfig from reporter options
|
|
327
|
-
*/
|
|
328
|
-
extractCoverageConfig(raw) {
|
|
329
|
-
const config = {
|
|
330
|
-
enabled: typeof raw.enabled === "boolean" ? raw.enabled : false
|
|
331
|
-
};
|
|
332
|
-
if (Array.isArray(raw.include)) {
|
|
333
|
-
config.include = raw.include.filter((p) => typeof p === "string");
|
|
334
|
-
}
|
|
335
|
-
if (Array.isArray(raw.exclude)) {
|
|
336
|
-
config.exclude = raw.exclude.filter((p) => typeof p === "string");
|
|
337
|
-
}
|
|
338
|
-
if (typeof raw.thresholds === "object" && raw.thresholds !== null) {
|
|
339
|
-
const t = raw.thresholds;
|
|
340
|
-
config.thresholds = {};
|
|
341
|
-
if (isValidThreshold(t.statements)) config.thresholds.statements = t.statements;
|
|
342
|
-
if (isValidThreshold(t.branches)) config.thresholds.branches = t.branches;
|
|
343
|
-
if (isValidThreshold(t.functions)) config.thresholds.functions = t.functions;
|
|
344
|
-
if (isValidThreshold(t.lines)) config.thresholds.lines = t.lines;
|
|
345
|
-
}
|
|
346
|
-
return config;
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
var ConfigMerger = class _ConfigMerger {
|
|
350
|
-
static DEFAULT_SERVER_URL = "https://api.testdino.com";
|
|
351
|
-
/**
|
|
352
|
-
* Merge configurations from all sources
|
|
353
|
-
* Priority (highest to lowest):
|
|
354
|
-
* 1. CLI flags
|
|
355
|
-
* 2. testdino.config.[ts|js]
|
|
356
|
-
* 3. playwright.config reporter options
|
|
357
|
-
* 4. Environment variables
|
|
358
|
-
*/
|
|
359
|
-
merge(sources) {
|
|
360
|
-
const { env = {}, playwrightConfig = {}, testdinoConfig = {}, cliOptions = {} } = sources;
|
|
361
|
-
const token = this.selectValue(cliOptions.token, testdinoConfig.token, playwrightConfig.token, env.token);
|
|
362
|
-
const serverUrl = this.selectValue(cliOptions.serverUrl, testdinoConfig.serverUrl, playwrightConfig.serverUrl, env.serverUrl) || _ConfigMerger.DEFAULT_SERVER_URL;
|
|
363
|
-
const ciRunId = this.selectValue(cliOptions.ciRunId, testdinoConfig.ciRunId, playwrightConfig.ciRunId) || this.generateCiRunId();
|
|
364
|
-
const debug = this.selectValue(cliOptions.debug, testdinoConfig.debug, playwrightConfig.debug, env.debug) ?? false;
|
|
365
|
-
const artifacts = cliOptions.noArtifacts === true ? false : this.selectValue(testdinoConfig.artifacts, playwrightConfig.artifacts) ?? true;
|
|
366
|
-
const coverage = this.mergeCoverageConfig(cliOptions.coverage, testdinoConfig.coverage, playwrightConfig.coverage);
|
|
367
|
-
const mergedConfig = {
|
|
368
|
-
token,
|
|
369
|
-
serverUrl,
|
|
370
|
-
ciRunId,
|
|
371
|
-
debug,
|
|
372
|
-
artifacts,
|
|
373
|
-
...coverage ? { coverage } : {}
|
|
374
|
-
};
|
|
375
|
-
this.validate(mergedConfig);
|
|
376
|
-
return mergedConfig;
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Merge coverage configuration from CLI flag and config files.
|
|
380
|
-
* CLI --coverage only toggles enabled; other fields come from config files.
|
|
381
|
-
*/
|
|
382
|
-
mergeCoverageConfig(cliCoverage, testdinoCoverage, playwrightCoverage) {
|
|
383
|
-
const baseConfig = testdinoCoverage ?? playwrightCoverage;
|
|
384
|
-
if (!baseConfig && cliCoverage === void 0) return void 0;
|
|
385
|
-
if (cliCoverage !== void 0) {
|
|
386
|
-
return { ...baseConfig || { enabled: false }, enabled: cliCoverage };
|
|
387
|
-
}
|
|
388
|
-
return baseConfig;
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Select first non-undefined value from arguments
|
|
392
|
-
*/
|
|
393
|
-
selectValue(...values) {
|
|
394
|
-
return values.find((value) => value !== void 0 && value !== null);
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* Generate a unique CI run ID
|
|
398
|
-
*/
|
|
399
|
-
generateCiRunId() {
|
|
400
|
-
return `run-${crypto.randomUUID()}`;
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* Validate merged configuration
|
|
404
|
-
*/
|
|
405
|
-
validate(config) {
|
|
406
|
-
if (!config.token || typeof config.token !== "string" || config.token.trim().length === 0) {
|
|
407
|
-
throw new TokenMissingError();
|
|
408
|
-
}
|
|
409
|
-
if (config.serverUrl) {
|
|
410
|
-
if (typeof config.serverUrl !== "string" || !this.isValidUrl(config.serverUrl)) {
|
|
411
|
-
throw new InvalidServerUrlError(config.serverUrl);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Check if string is a valid URL
|
|
417
|
-
*/
|
|
418
|
-
isValidUrl(urlString) {
|
|
419
|
-
try {
|
|
420
|
-
const url = new URL(urlString);
|
|
421
|
-
return url.protocol === "http:" || url.protocol === "https:";
|
|
422
|
-
} catch {
|
|
423
|
-
return false;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
/**
|
|
427
|
-
* Get environment variables as config
|
|
428
|
-
*/
|
|
429
|
-
static getEnvConfig() {
|
|
430
|
-
const config = {};
|
|
431
|
-
if (process.env.TESTDINO_TOKEN) {
|
|
432
|
-
config.token = process.env.TESTDINO_TOKEN;
|
|
433
|
-
}
|
|
434
|
-
if (process.env.TESTDINO_SERVER_URL) {
|
|
435
|
-
config.serverUrl = process.env.TESTDINO_SERVER_URL;
|
|
436
|
-
}
|
|
437
|
-
if (process.env.TESTDINO_DEBUG) {
|
|
438
|
-
config.debug = process.env.TESTDINO_DEBUG === "true" || process.env.TESTDINO_DEBUG === "1";
|
|
439
|
-
}
|
|
440
|
-
return config;
|
|
441
|
-
}
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
// src/cli/arg-filter.ts
|
|
445
|
-
var TESTDINO_FLAGS = ["--token", "-t", "--ci-run-id", "--server-url", "--debug", "--no-artifacts", "--coverage"];
|
|
446
|
-
var FLAGS_WITH_VALUES = ["--token", "-t", "--ci-run-id", "--server-url"];
|
|
447
|
-
var ArgFilter = class {
|
|
448
|
-
/**
|
|
449
|
-
* Filter TestDino-specific arguments from the argument list
|
|
450
|
-
* Removes both flags and their values
|
|
451
|
-
*
|
|
452
|
-
* @param args - Raw command line arguments
|
|
453
|
-
* @returns Filtered arguments safe to pass to Playwright
|
|
454
|
-
*/
|
|
455
|
-
filter(args) {
|
|
456
|
-
const result = [];
|
|
457
|
-
let skipNext = false;
|
|
458
|
-
for (let i = 0; i < args.length; i++) {
|
|
459
|
-
const arg = args[i];
|
|
460
|
-
if (skipNext) {
|
|
461
|
-
skipNext = false;
|
|
462
|
-
continue;
|
|
463
|
-
}
|
|
464
|
-
if (this.isTestdinoFlag(arg)) {
|
|
465
|
-
if (this.isFlagWithValue(arg) && !arg.includes("=")) {
|
|
466
|
-
skipNext = true;
|
|
467
|
-
}
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
if (this.isTestdinoFlagWithEquals(arg)) {
|
|
471
|
-
continue;
|
|
472
|
-
}
|
|
473
|
-
result.push(arg);
|
|
474
|
-
}
|
|
475
|
-
return result;
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Check if argument is a TestDino flag
|
|
479
|
-
*/
|
|
480
|
-
isTestdinoFlag(arg) {
|
|
481
|
-
const flagName = arg.split("=")[0];
|
|
482
|
-
return TESTDINO_FLAGS.includes(flagName);
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Check if argument is a TestDino flag with = syntax
|
|
486
|
-
*/
|
|
487
|
-
isTestdinoFlagWithEquals(arg) {
|
|
488
|
-
if (!arg.includes("=")) {
|
|
489
|
-
return false;
|
|
490
|
-
}
|
|
491
|
-
const flagName = arg.split("=")[0];
|
|
492
|
-
return TESTDINO_FLAGS.includes(flagName);
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* Check if flag takes a value
|
|
496
|
-
*/
|
|
497
|
-
isFlagWithValue(arg) {
|
|
498
|
-
const flagName = arg.split("=")[0];
|
|
499
|
-
return FLAGS_WITH_VALUES.includes(flagName);
|
|
500
|
-
}
|
|
501
|
-
/**
|
|
502
|
-
* Get list of TestDino flags (for reference/testing)
|
|
503
|
-
*/
|
|
504
|
-
static getTestdinoFlags() {
|
|
505
|
-
return [...TESTDINO_FLAGS];
|
|
506
|
-
}
|
|
507
|
-
};
|
|
508
|
-
|
|
509
|
-
// src/utils/index.ts
|
|
510
|
-
function isDebugEnabled() {
|
|
511
|
-
return process.env.TESTDINO_DEBUG === "true" || process.env.TESTDINO_DEBUG === "1" || process.env.DEBUG === "true";
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// src/cli/logger.ts
|
|
515
|
-
var Logger = class {
|
|
516
|
-
debugEnabled;
|
|
517
|
-
constructor(debugEnabled = false) {
|
|
518
|
-
this.debugEnabled = debugEnabled;
|
|
519
|
-
}
|
|
520
|
-
/**
|
|
521
|
-
* Enable or disable debug logging
|
|
522
|
-
*/
|
|
523
|
-
setDebug(enabled) {
|
|
524
|
-
this.debugEnabled = enabled;
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* Log error message
|
|
528
|
-
*/
|
|
529
|
-
error(message, error) {
|
|
530
|
-
console.error(chalk__default.default.red(`
|
|
531
|
-
\u2716 Error: ${message}`));
|
|
532
|
-
if (error && this.debugEnabled) {
|
|
533
|
-
console.error(chalk__default.default.dim("\nStack trace:"));
|
|
534
|
-
console.error(chalk__default.default.dim(error.stack || error.message));
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Log warning message
|
|
539
|
-
*/
|
|
540
|
-
warn(message) {
|
|
541
|
-
console.warn(chalk__default.default.yellow(`\u26A0\uFE0F Warning: ${message}`));
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Log info message
|
|
545
|
-
*/
|
|
546
|
-
info(message) {
|
|
547
|
-
console.log(chalk__default.default.blue(`\u2139\uFE0F ${message}`));
|
|
548
|
-
}
|
|
549
|
-
/**
|
|
550
|
-
* Log success message
|
|
551
|
-
*/
|
|
552
|
-
success(message) {
|
|
553
|
-
console.log(chalk__default.default.green(`\u2713 ${message}`));
|
|
554
|
-
}
|
|
555
|
-
/**
|
|
556
|
-
* Log debug message (only if debug is enabled)
|
|
557
|
-
*/
|
|
558
|
-
debug(message) {
|
|
559
|
-
if (this.debugEnabled) {
|
|
560
|
-
console.log(chalk__default.default.dim(`[DEBUG] ${message}`));
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* Log a blank line
|
|
565
|
-
*/
|
|
566
|
-
newline() {
|
|
567
|
-
console.log();
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Log a section header
|
|
571
|
-
*/
|
|
572
|
-
section(title) {
|
|
573
|
-
console.log(chalk__default.default.bold.cyan(`
|
|
574
|
-
${title}`));
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* Log a list item
|
|
578
|
-
*/
|
|
579
|
-
listItem(text) {
|
|
580
|
-
console.log(` \u2022 ${text}`);
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* Log code/command
|
|
584
|
-
*/
|
|
585
|
-
code(text) {
|
|
586
|
-
console.log(chalk__default.default.gray(` ${text}`));
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* Format error for display
|
|
590
|
-
*/
|
|
591
|
-
formatError(error) {
|
|
592
|
-
if (this.debugEnabled && error.stack) {
|
|
593
|
-
return error.stack;
|
|
594
|
-
}
|
|
595
|
-
return error.message;
|
|
596
|
-
}
|
|
597
|
-
/**
|
|
598
|
-
* Log TestDino CLI banner
|
|
599
|
-
*/
|
|
600
|
-
banner(version) {
|
|
601
|
-
console.log(
|
|
602
|
-
chalk__default.default.cyan(`
|
|
603
|
-
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
604
|
-
\u2551 \u2551
|
|
605
|
-
\u2551 ${chalk__default.default.bold("TestDino Playwright")} v${version.padEnd(36)}\u2551
|
|
606
|
-
\u2551 ${chalk__default.default.dim("https://testdino.com")} \u2551
|
|
607
|
-
\u2551 \u2551
|
|
608
|
-
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
609
|
-
`)
|
|
610
|
-
);
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
|
-
new Logger(isDebugEnabled());
|
|
614
|
-
|
|
615
|
-
// src/cli/temp-config.ts
|
|
616
|
-
var TempConfigManager = class {
|
|
617
|
-
tempFiles = /* @__PURE__ */ new Set();
|
|
618
|
-
cleanupHandlersRegistered = false;
|
|
619
|
-
exitHandler;
|
|
620
|
-
sigintHandler;
|
|
621
|
-
sigtermHandler;
|
|
622
|
-
uncaughtExceptionHandler;
|
|
623
|
-
unhandledRejectionHandler;
|
|
624
|
-
logger;
|
|
625
|
-
constructor(logger3) {
|
|
626
|
-
this.logger = logger3 ?? new Logger();
|
|
627
|
-
}
|
|
628
|
-
/**
|
|
629
|
-
* Create a temporary config file with the merged configuration
|
|
630
|
-
* @param config - Merged configuration to write
|
|
631
|
-
* @returns Temp config info with path and config
|
|
632
|
-
*/
|
|
633
|
-
create(config) {
|
|
634
|
-
const tempPath = this.generateTempPath();
|
|
635
|
-
try {
|
|
636
|
-
const configJson = JSON.stringify(config, null, 2);
|
|
637
|
-
fs.writeFileSync(tempPath, configJson, "utf-8");
|
|
638
|
-
this.tempFiles.add(tempPath);
|
|
639
|
-
if (!this.cleanupHandlersRegistered) {
|
|
640
|
-
this.registerCleanupHandlers();
|
|
641
|
-
this.cleanupHandlersRegistered = true;
|
|
642
|
-
}
|
|
643
|
-
return {
|
|
644
|
-
path: tempPath,
|
|
645
|
-
config
|
|
646
|
-
};
|
|
647
|
-
} catch (error) {
|
|
648
|
-
throw new Error(
|
|
649
|
-
`Failed to create temp config file: ${tempPath}
|
|
650
|
-
${error instanceof Error ? error.message : String(error)}`
|
|
651
|
-
);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
/**
|
|
655
|
-
* Clean up a specific temp config file
|
|
656
|
-
* @param tempPath - Path to temp file to clean up
|
|
657
|
-
*/
|
|
658
|
-
cleanup(tempPath) {
|
|
659
|
-
try {
|
|
660
|
-
if (fs.existsSync(tempPath)) {
|
|
661
|
-
fs.unlinkSync(tempPath);
|
|
662
|
-
}
|
|
663
|
-
this.tempFiles.delete(tempPath);
|
|
664
|
-
} catch {
|
|
665
|
-
this.logger.warn(`Failed to cleanup temp file: ${tempPath}`);
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
|
-
* Clean up all tracked temp files
|
|
670
|
-
*/
|
|
671
|
-
cleanupAll() {
|
|
672
|
-
for (const tempPath of this.tempFiles) {
|
|
673
|
-
this.cleanup(tempPath);
|
|
674
|
-
}
|
|
675
|
-
this.tempFiles.clear();
|
|
676
|
-
}
|
|
677
|
-
/**
|
|
678
|
-
* Remove all event handlers (for testing)
|
|
679
|
-
*/
|
|
680
|
-
removeHandlers() {
|
|
681
|
-
if (this.exitHandler) {
|
|
682
|
-
process.removeListener("exit", this.exitHandler);
|
|
683
|
-
}
|
|
684
|
-
if (this.sigintHandler) {
|
|
685
|
-
process.removeListener("SIGINT", this.sigintHandler);
|
|
686
|
-
}
|
|
687
|
-
if (this.sigtermHandler) {
|
|
688
|
-
process.removeListener("SIGTERM", this.sigtermHandler);
|
|
689
|
-
}
|
|
690
|
-
if (this.uncaughtExceptionHandler) {
|
|
691
|
-
process.removeListener("uncaughtException", this.uncaughtExceptionHandler);
|
|
692
|
-
}
|
|
693
|
-
if (this.unhandledRejectionHandler) {
|
|
694
|
-
process.removeListener("unhandledRejection", this.unhandledRejectionHandler);
|
|
695
|
-
}
|
|
696
|
-
this.cleanupHandlersRegistered = false;
|
|
697
|
-
}
|
|
698
|
-
/**
|
|
699
|
-
* Generate unique temp file path
|
|
700
|
-
*/
|
|
701
|
-
generateTempPath() {
|
|
702
|
-
const filename = `testdino-config-${crypto.randomUUID()}.json`;
|
|
703
|
-
return path.join(os.tmpdir(), filename);
|
|
704
|
-
}
|
|
705
|
-
/**
|
|
706
|
-
* Register cleanup handlers for process exit and signals
|
|
707
|
-
*/
|
|
708
|
-
registerCleanupHandlers() {
|
|
709
|
-
this.exitHandler = () => {
|
|
710
|
-
this.cleanupAll();
|
|
711
|
-
};
|
|
712
|
-
process.on("exit", this.exitHandler);
|
|
713
|
-
this.sigintHandler = () => {
|
|
714
|
-
if (this.sigintHandler) {
|
|
715
|
-
process.removeListener("SIGINT", this.sigintHandler);
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
process.on("SIGINT", this.sigintHandler);
|
|
719
|
-
this.sigtermHandler = () => {
|
|
720
|
-
if (this.sigtermHandler) {
|
|
721
|
-
process.removeListener("SIGTERM", this.sigtermHandler);
|
|
722
|
-
}
|
|
723
|
-
};
|
|
724
|
-
process.on("SIGTERM", this.sigtermHandler);
|
|
725
|
-
this.uncaughtExceptionHandler = (error) => {
|
|
726
|
-
this.logger.error("Uncaught exception", error);
|
|
727
|
-
this.cleanupAll();
|
|
728
|
-
process.exit(1);
|
|
729
|
-
};
|
|
730
|
-
process.on("uncaughtException", this.uncaughtExceptionHandler);
|
|
731
|
-
this.unhandledRejectionHandler = (reason) => {
|
|
732
|
-
this.logger.error("Unhandled rejection", reason instanceof Error ? reason : void 0);
|
|
733
|
-
this.cleanupAll();
|
|
734
|
-
process.exit(1);
|
|
735
|
-
};
|
|
736
|
-
process.on("unhandledRejection", this.unhandledRejectionHandler);
|
|
737
|
-
}
|
|
738
|
-
/**
|
|
739
|
-
* Get list of tracked temp files (for testing)
|
|
740
|
-
*/
|
|
741
|
-
getTempFiles() {
|
|
742
|
-
return Array.from(this.tempFiles);
|
|
743
|
-
}
|
|
744
|
-
};
|
|
745
|
-
var PlaywrightSpawner = class {
|
|
746
|
-
logger;
|
|
747
|
-
constructor(logger3) {
|
|
748
|
-
this.logger = logger3 ?? new Logger();
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* Spawn Playwright test process
|
|
752
|
-
* @param options - Spawn options
|
|
753
|
-
* @returns Spawn result with exit code
|
|
754
|
-
*/
|
|
755
|
-
async spawn(options) {
|
|
756
|
-
const { args, tempConfigPath, config, cwd = process.cwd() } = options;
|
|
757
|
-
try {
|
|
758
|
-
const env = {
|
|
759
|
-
...process.env,
|
|
760
|
-
TESTDINO_CLI_CONFIG_PATH: tempConfigPath,
|
|
761
|
-
TESTDINO_TOKEN: config.token,
|
|
762
|
-
TESTDINO_SERVER_URL: config.serverUrl,
|
|
763
|
-
TESTDINO_CI_RUN_ID: config.ciRunId,
|
|
764
|
-
TESTDINO_DEBUG: config.debug ? "true" : "false"
|
|
765
|
-
};
|
|
766
|
-
const playwrightArgs = ["playwright", "test", "--reporter", "@testdino/playwright", ...args];
|
|
767
|
-
const result = await execa.execa("npx", playwrightArgs, {
|
|
768
|
-
stdio: "inherit",
|
|
769
|
-
// Forward stdout/stderr in real-time
|
|
770
|
-
cwd,
|
|
771
|
-
env,
|
|
772
|
-
reject: false
|
|
773
|
-
// Don't throw on non-zero exit codes
|
|
774
|
-
});
|
|
775
|
-
const exitCode = result.exitCode ?? 0;
|
|
776
|
-
return {
|
|
777
|
-
exitCode,
|
|
778
|
-
success: exitCode === 0
|
|
779
|
-
};
|
|
780
|
-
} catch (error) {
|
|
781
|
-
return this.handleSpawnError(error);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
/**
|
|
785
|
-
* Handle spawn errors
|
|
786
|
-
*/
|
|
787
|
-
handleSpawnError(error) {
|
|
788
|
-
const execaError = error;
|
|
789
|
-
if (execaError.code === "ENOENT") {
|
|
790
|
-
this.logger.error("Failed to spawn Playwright");
|
|
791
|
-
this.logger.newline();
|
|
792
|
-
this.logger.info("Playwright is not installed or npx is not available.");
|
|
793
|
-
this.logger.newline();
|
|
794
|
-
this.logger.section("To install Playwright:");
|
|
795
|
-
this.logger.code("npm install -D @playwright/test");
|
|
796
|
-
this.logger.code("npx playwright install");
|
|
797
|
-
return {
|
|
798
|
-
exitCode: 1,
|
|
799
|
-
success: false
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
if (execaError.code === "EACCES") {
|
|
803
|
-
this.logger.error("Permission denied when trying to spawn Playwright");
|
|
804
|
-
this.logger.newline();
|
|
805
|
-
this.logger.info("Please check file permissions and try again.");
|
|
806
|
-
return {
|
|
807
|
-
exitCode: 1,
|
|
808
|
-
success: false
|
|
809
|
-
};
|
|
810
|
-
}
|
|
811
|
-
this.logger.error("Failed to spawn Playwright");
|
|
812
|
-
this.logger.newline();
|
|
813
|
-
this.logger.info(`Error: ${execaError.message || String(error)}`);
|
|
814
|
-
return {
|
|
815
|
-
exitCode: 1,
|
|
816
|
-
success: false
|
|
817
|
-
};
|
|
818
|
-
}
|
|
819
|
-
};
|
|
820
|
-
|
|
821
|
-
// src/cli/commands/test.ts
|
|
822
|
-
var TestCommand = class {
|
|
823
|
-
configLoader;
|
|
824
|
-
configDetector;
|
|
825
|
-
configMerger;
|
|
826
|
-
argFilter;
|
|
827
|
-
tempConfigManager;
|
|
828
|
-
playwrightSpawner;
|
|
829
|
-
constructor(configLoader, configDetector, configMerger, argFilter, tempConfigManager, playwrightSpawner, logger3) {
|
|
830
|
-
this.configLoader = configLoader || new ConfigLoader();
|
|
831
|
-
this.configDetector = configDetector || new ConfigDetector();
|
|
832
|
-
this.configMerger = configMerger || new ConfigMerger();
|
|
833
|
-
this.argFilter = argFilter || new ArgFilter();
|
|
834
|
-
this.tempConfigManager = tempConfigManager || new TempConfigManager(logger3);
|
|
835
|
-
this.playwrightSpawner = playwrightSpawner || new PlaywrightSpawner(logger3);
|
|
836
|
-
}
|
|
837
|
-
/**
|
|
838
|
-
* Execute the test command
|
|
839
|
-
* @param options - CLI options from commander
|
|
840
|
-
* @param args - Remaining arguments to pass to Playwright
|
|
841
|
-
* @returns Spawn result with exit code
|
|
842
|
-
*/
|
|
843
|
-
async execute(options, args) {
|
|
844
|
-
let tempConfigPath;
|
|
845
|
-
try {
|
|
846
|
-
const testdinoConfigResult = await this.configLoader.load();
|
|
847
|
-
const playwrightConfigResult = await this.configDetector.detect();
|
|
848
|
-
const envConfig = ConfigMerger.getEnvConfig();
|
|
849
|
-
const mergedConfig = this.configMerger.merge({
|
|
850
|
-
env: envConfig,
|
|
851
|
-
playwrightConfig: playwrightConfigResult.options,
|
|
852
|
-
testdinoConfig: testdinoConfigResult.config,
|
|
853
|
-
cliOptions: options
|
|
854
|
-
});
|
|
855
|
-
const tempConfigInfo = this.tempConfigManager.create(mergedConfig);
|
|
856
|
-
tempConfigPath = tempConfigInfo.path;
|
|
857
|
-
const filteredArgs = this.argFilter.filter(args);
|
|
858
|
-
const result = await this.playwrightSpawner.spawn({
|
|
859
|
-
args: filteredArgs,
|
|
860
|
-
tempConfigPath,
|
|
861
|
-
config: mergedConfig
|
|
862
|
-
});
|
|
863
|
-
return result;
|
|
864
|
-
} finally {
|
|
865
|
-
if (tempConfigPath) {
|
|
866
|
-
this.tempConfigManager.cleanup(tempConfigPath);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
};
|
|
871
|
-
|
|
872
|
-
// src/cli/index.ts
|
|
873
|
-
var __filename$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)));
|
|
874
|
-
var __dirname$1 = path.dirname(__filename$1);
|
|
875
|
-
function getVersion() {
|
|
876
|
-
try {
|
|
877
|
-
const packagePath = path.join(__dirname$1, "../../package.json");
|
|
878
|
-
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
|
|
879
|
-
return packageJson.version;
|
|
880
|
-
} catch {
|
|
881
|
-
return "0.0.0";
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
var logger2 = new Logger(isDebugEnabled());
|
|
885
|
-
function buildProgram() {
|
|
886
|
-
const program = new commander.Command().name("tdpw").description("Run Playwright tests with TestDino reporting").version(getVersion(), "-v, --version", "Output the current version").helpOption("-h, --help", "Display help for command");
|
|
887
|
-
program.command("test").description("Run Playwright tests with TestDino reporter").option("-t, --token <token>", "TestDino authentication token").option("--ci-run-id <id>", "CI run ID for grouping test runs").option("--server-url <url>", "TestDino server URL").option("--debug", "Enable debug logging").option("--no-artifacts", "Disable artifact uploads (screenshots, videos, traces)").option("--coverage", "Enable code coverage collection").allowUnknownOption().allowExcessArguments().action(async (options, command) => {
|
|
888
|
-
if (options.debug) {
|
|
889
|
-
logger2.setDebug(true);
|
|
890
|
-
}
|
|
891
|
-
try {
|
|
892
|
-
const args = command.args || [];
|
|
893
|
-
const testCommand = new TestCommand();
|
|
894
|
-
const result = await testCommand.execute(options, args);
|
|
895
|
-
process.exit(result.exitCode);
|
|
896
|
-
} catch (error) {
|
|
897
|
-
if (error instanceof TestDinoError) {
|
|
898
|
-
logger2.error(error.message);
|
|
899
|
-
} else {
|
|
900
|
-
logger2.error(
|
|
901
|
-
error instanceof Error ? error.message : String(error),
|
|
902
|
-
error instanceof Error ? error : void 0
|
|
903
|
-
);
|
|
904
|
-
}
|
|
905
|
-
process.exit(1);
|
|
906
|
-
}
|
|
907
|
-
});
|
|
908
|
-
return program;
|
|
909
|
-
}
|
|
910
|
-
async function main() {
|
|
911
|
-
try {
|
|
912
|
-
logger2.banner(getVersion());
|
|
913
|
-
const program = buildProgram();
|
|
914
|
-
await program.parseAsync(process.argv);
|
|
915
|
-
} catch (error) {
|
|
916
|
-
if (error instanceof TestDinoError) {
|
|
917
|
-
logger2.error(error.message);
|
|
918
|
-
} else {
|
|
919
|
-
logger2.error(error instanceof Error ? error.message : String(error), error instanceof Error ? error : void 0);
|
|
920
|
-
}
|
|
921
|
-
process.exit(1);
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
main().catch((error) => {
|
|
925
|
-
logger2.error("Unexpected error", error instanceof Error ? error : void 0);
|
|
926
|
-
process.exit(1);
|
|
927
|
-
});
|
|
928
|
-
//# sourceMappingURL=index.js.map
|
|
929
|
-
//# sourceMappingURL=index.js.map
|