@testingbot/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +375 -0
- package/dist/auth.d.ts +16 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +47 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +329 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +20 -0
- package/dist/models/credentials.d.ts +9 -0
- package/dist/models/credentials.d.ts.map +1 -0
- package/dist/models/credentials.js +20 -0
- package/dist/models/espresso_options.d.ts +116 -0
- package/dist/models/espresso_options.d.ts.map +1 -0
- package/dist/models/espresso_options.js +194 -0
- package/dist/models/maestro_options.d.ts +101 -0
- package/dist/models/maestro_options.d.ts.map +1 -0
- package/dist/models/maestro_options.js +176 -0
- package/dist/models/testingbot_error.d.ts +3 -0
- package/dist/models/testingbot_error.d.ts.map +1 -0
- package/dist/models/testingbot_error.js +5 -0
- package/dist/models/xcuitest_options.d.ts +88 -0
- package/dist/models/xcuitest_options.d.ts.map +1 -0
- package/dist/models/xcuitest_options.js +146 -0
- package/dist/providers/espresso.d.ts +67 -0
- package/dist/providers/espresso.d.ts.map +1 -0
- package/dist/providers/espresso.js +527 -0
- package/dist/providers/login.d.ts +18 -0
- package/dist/providers/login.d.ts.map +1 -0
- package/dist/providers/login.js +284 -0
- package/dist/providers/maestro.d.ts +92 -0
- package/dist/providers/maestro.d.ts.map +1 -0
- package/dist/providers/maestro.js +1010 -0
- package/dist/providers/xcuitest.d.ts +67 -0
- package/dist/providers/xcuitest.d.ts.map +1 -0
- package/dist/providers/xcuitest.js +529 -0
- package/dist/upload.d.ts +21 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +94 -0
- package/dist/utils/file-type-detector.d.ts +15 -0
- package/dist/utils/file-type-detector.d.ts.map +1 -0
- package/dist/utils/file-type-detector.js +38 -0
- package/dist/utils/platform.d.ts +26 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +58 -0
- package/dist/utils.d.ts +15 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +48 -0
- package/package.json +78 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const commander_1 = require("commander");
|
|
7
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
8
|
+
const auth_1 = __importDefault(require("./auth"));
|
|
9
|
+
const espresso_1 = __importDefault(require("./providers/espresso"));
|
|
10
|
+
const espresso_options_1 = __importDefault(require("./models/espresso_options"));
|
|
11
|
+
const xcuitest_options_1 = __importDefault(require("./models/xcuitest_options"));
|
|
12
|
+
const xcuitest_1 = __importDefault(require("./providers/xcuitest"));
|
|
13
|
+
const package_json_1 = __importDefault(require("../package.json"));
|
|
14
|
+
const maestro_options_1 = __importDefault(require("./models/maestro_options"));
|
|
15
|
+
const maestro_1 = __importDefault(require("./providers/maestro"));
|
|
16
|
+
const login_1 = __importDefault(require("./providers/login"));
|
|
17
|
+
const program = new commander_1.Command();
|
|
18
|
+
program
|
|
19
|
+
.name('testingbot')
|
|
20
|
+
.version(package_json_1.default.version, '-v, --version', 'Show version number')
|
|
21
|
+
.description('CLI tool to run Espresso, XCUITest and Maestro tests on TestingBot cloud');
|
|
22
|
+
const espressoCommand = program
|
|
23
|
+
.command('espresso')
|
|
24
|
+
.description('Run Espresso tests on TestingBot.')
|
|
25
|
+
.argument('[appFile]', 'Path to application APK file')
|
|
26
|
+
.argument('[testAppFile]', 'Path to test APK file containing Espresso tests')
|
|
27
|
+
// App and test options
|
|
28
|
+
.option('--app <path>', 'Path to application APK file.')
|
|
29
|
+
.option('--test-app <path>', 'Path to test APK file containing Espresso tests.')
|
|
30
|
+
// Device configuration
|
|
31
|
+
.option('--device <device>', 'Device name to use for testing (e.g., "Pixel 6", "Samsung.*").')
|
|
32
|
+
.option('--platform-version <version>', 'Android OS version (e.g., "12", "13").')
|
|
33
|
+
.option('--real-device', 'Use a real device instead of an emulator.')
|
|
34
|
+
.option('--tablet-only', 'Only allocate tablet devices.')
|
|
35
|
+
.option('--phone-only', 'Only allocate phone devices.')
|
|
36
|
+
.option('--locale <locale>', 'Device locale (e.g., "en_US", "de_DE").')
|
|
37
|
+
.option('--timezone <timezone>', 'Device timezone (e.g., "America/New_York", "Europe/London").')
|
|
38
|
+
// Test metadata
|
|
39
|
+
.option('--name <name>', 'Test name for identification in dashboard.')
|
|
40
|
+
.option('--build <build>', 'Build identifier for grouping test runs.')
|
|
41
|
+
// Espresso-specific options
|
|
42
|
+
.option('--test-runner <runner>', 'Custom test instrumentation runner (e.g., "${packageName}/customTestRunner").')
|
|
43
|
+
.option('--class <classes>', 'Run tests in specific classes (comma-separated fully qualified names).', (val) => val.split(',').map((c) => c.trim()))
|
|
44
|
+
.option('--not-class <classes>', 'Exclude tests in specific classes (comma-separated fully qualified names).', (val) => val.split(',').map((c) => c.trim()))
|
|
45
|
+
.option('--package <packages>', 'Run tests in specific packages (comma-separated).', (val) => val.split(',').map((p) => p.trim()))
|
|
46
|
+
.option('--not-package <packages>', 'Exclude tests in specific packages (comma-separated).', (val) => val.split(',').map((p) => p.trim()))
|
|
47
|
+
.option('--annotation <annotations>', 'Run tests with specific annotations (comma-separated).', (val) => val.split(',').map((a) => a.trim()))
|
|
48
|
+
.option('--not-annotation <annotations>', 'Exclude tests with specific annotations (comma-separated).', (val) => val.split(',').map((a) => a.trim()))
|
|
49
|
+
.option('--size <sizes>', 'Run tests by size: small, medium, large (comma-separated).', (val) => val.split(',').map((s) => s.trim().toLowerCase()))
|
|
50
|
+
// Localization
|
|
51
|
+
.option('--language <lang>', 'App language (ISO 639-1 code, e.g., "en", "fr", "de").')
|
|
52
|
+
// Geolocation
|
|
53
|
+
.option('--geo-location <code>', 'Geographic IP location (ISO country code, e.g., "US", "DE").')
|
|
54
|
+
// Network throttling
|
|
55
|
+
.option('--throttle-network <speed>', 'Network throttling: 4G, 3G, Edge, or airplane.', (val) => val)
|
|
56
|
+
// Execution mode
|
|
57
|
+
.option('-q, --quiet', 'Quieter console output without progress updates.')
|
|
58
|
+
.option('--async', 'Start tests and exit immediately without waiting for results.')
|
|
59
|
+
// Report options
|
|
60
|
+
.option('--report <format>', 'Download test report after completion: html or junit.', (val) => val.toLowerCase())
|
|
61
|
+
.option('--report-output-dir <path>', 'Directory to save test reports (required when --report is used).')
|
|
62
|
+
// Authentication
|
|
63
|
+
.option('--api-key <key>', 'TestingBot API key.')
|
|
64
|
+
.option('--api-secret <secret>', 'TestingBot API secret.')
|
|
65
|
+
.action(async (appFileArg, testAppFileArg, args) => {
|
|
66
|
+
try {
|
|
67
|
+
// Positional arguments take precedence, fall back to options
|
|
68
|
+
const app = appFileArg || args.app;
|
|
69
|
+
const testApp = testAppFileArg || args.testApp;
|
|
70
|
+
if (!app || !testApp) {
|
|
71
|
+
espressoCommand.help();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const options = new espresso_options_1.default(app, testApp, args.device, {
|
|
75
|
+
version: args.platformVersion,
|
|
76
|
+
realDevice: args.realDevice,
|
|
77
|
+
tabletOnly: args.tabletOnly,
|
|
78
|
+
phoneOnly: args.phoneOnly,
|
|
79
|
+
name: args.name,
|
|
80
|
+
build: args.build,
|
|
81
|
+
testRunner: args.testRunner,
|
|
82
|
+
class: args.class,
|
|
83
|
+
notClass: args.notClass,
|
|
84
|
+
package: args.package,
|
|
85
|
+
notPackage: args.notPackage,
|
|
86
|
+
annotation: args.annotation,
|
|
87
|
+
notAnnotation: args.notAnnotation,
|
|
88
|
+
size: args.size,
|
|
89
|
+
language: args.language,
|
|
90
|
+
locale: args.locale,
|
|
91
|
+
timeZone: args.timezone,
|
|
92
|
+
geoLocation: args.geoLocation,
|
|
93
|
+
throttleNetwork: args.throttleNetwork,
|
|
94
|
+
quiet: args.quiet,
|
|
95
|
+
async: args.async,
|
|
96
|
+
report: args.report,
|
|
97
|
+
reportOutputDir: args.reportOutputDir,
|
|
98
|
+
});
|
|
99
|
+
const credentials = await auth_1.default.getCredentials({
|
|
100
|
+
apiKey: args.apiKey,
|
|
101
|
+
apiSecret: args.apiSecret,
|
|
102
|
+
});
|
|
103
|
+
if (credentials === null) {
|
|
104
|
+
throw new Error('Please specify credentials via --api-key/--api-secret, TB_KEY/TB_SECRET environment variables, or ~/.testingbot file');
|
|
105
|
+
}
|
|
106
|
+
const espresso = new espresso_1.default(credentials, options);
|
|
107
|
+
const result = await espresso.run();
|
|
108
|
+
if (!result.success) {
|
|
109
|
+
process.exitCode = 1;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
logger_1.default.error(`Espresso error: ${err instanceof Error ? err.message : err}`);
|
|
114
|
+
process.exitCode = 1;
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
.showHelpAfterError(true);
|
|
118
|
+
const maestroCommand = program
|
|
119
|
+
.command('maestro')
|
|
120
|
+
.description('Run Maestro flows on TestingBot.')
|
|
121
|
+
.argument('[appFile]', 'Path to application under test (.apk, .ipa, .app or .zip)')
|
|
122
|
+
.argument('[flows...]', 'Paths to flow files, directories, or glob patterns (can specify multiple)')
|
|
123
|
+
// App and flows options
|
|
124
|
+
.option('--app <path>', 'Path to application under test (.apk, .ipa, .app, or .zip).')
|
|
125
|
+
// Device configuration
|
|
126
|
+
.option('--device <device>', 'Device name to use for testing (e.g., "Pixel 9", "iPhone 17").')
|
|
127
|
+
.option('--platform <platform>', 'Platform name: Android or iOS.', (val) => val)
|
|
128
|
+
.option('--deviceVersion <version>', 'OS version (e.g., "14", "17.2").')
|
|
129
|
+
.option('--real-device', 'Use a real device instead of an emulator/simulator.')
|
|
130
|
+
.option('--orientation <orientation>', 'Screen orientation: PORTRAIT or LANDSCAPE.', (val) => val.toUpperCase())
|
|
131
|
+
.option('--device-locale <locale>', 'Device locale (e.g., "en_US", "de_DE").')
|
|
132
|
+
.option('--timezone <timezone>', 'Device timezone (e.g., "America/New_York", "Europe/London").')
|
|
133
|
+
// Test metadata
|
|
134
|
+
.option('--name <name>', 'Test name for identification in dashboard.')
|
|
135
|
+
.option('--build <build>', 'Build identifier for grouping test runs.')
|
|
136
|
+
// Network and geo
|
|
137
|
+
.option('--throttle-network <speed>', 'Network throttling: 4G, 3G, Edge, airplane, or disable.', (val) => val)
|
|
138
|
+
.option('--geo-country-code <code>', 'Geographic IP location (ISO country code, e.g., "US", "DE").')
|
|
139
|
+
// Flow filtering
|
|
140
|
+
.option('--include-tags <tags>', 'Only run flows with these tags (comma-separated).', (val) => val.split(',').map((t) => t.trim()))
|
|
141
|
+
.option('--exclude-tags <tags>', 'Exclude flows with these tags (comma-separated).', (val) => val.split(',').map((t) => t.trim()))
|
|
142
|
+
// Environment variables
|
|
143
|
+
.option('-e, --env <KEY=VALUE>', 'Environment variable to pass to Maestro flows (can be used multiple times).', (val, acc) => {
|
|
144
|
+
acc.push(val);
|
|
145
|
+
return acc;
|
|
146
|
+
}, [])
|
|
147
|
+
// Maestro configuration
|
|
148
|
+
.option('--maestro-version <version>', 'Maestro version to use (e.g., "2.0.10").')
|
|
149
|
+
// Execution mode
|
|
150
|
+
.option('-q, --quiet', 'Quieter console output without progress updates.')
|
|
151
|
+
.option('--async', 'Start tests and exit immediately without waiting for results.')
|
|
152
|
+
// Report options
|
|
153
|
+
.option('--report <format>', 'Download test report after completion: html or junit.', (val) => val.toLowerCase())
|
|
154
|
+
.option('--report-output-dir <path>', 'Directory to save test reports (required when --report is used).')
|
|
155
|
+
// Artifact download
|
|
156
|
+
.option('--download-artifacts', 'Download test artifacts (logs, screenshots, video) after completion.')
|
|
157
|
+
.option('--artifacts-output-dir <path>', 'Directory to save artifacts zip (defaults to current directory).')
|
|
158
|
+
// Authentication
|
|
159
|
+
.option('--api-key <key>', 'TestingBot API key.')
|
|
160
|
+
.option('--api-secret <secret>', 'TestingBot API secret.')
|
|
161
|
+
.action(async (appFileArg, flowsArgs, args) => {
|
|
162
|
+
try {
|
|
163
|
+
let app;
|
|
164
|
+
let flows;
|
|
165
|
+
if (args.app) {
|
|
166
|
+
// If --app is specified, treat all positional arguments as flows
|
|
167
|
+
app = args.app;
|
|
168
|
+
flows = appFileArg
|
|
169
|
+
? [appFileArg, ...(flowsArgs || [])]
|
|
170
|
+
: flowsArgs || [];
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// Otherwise, first positional is app, rest are flows
|
|
174
|
+
app = appFileArg;
|
|
175
|
+
flows = flowsArgs || [];
|
|
176
|
+
}
|
|
177
|
+
if (!app || flows.length === 0) {
|
|
178
|
+
maestroCommand.help();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Parse environment variables from -e KEY=VALUE format
|
|
182
|
+
const env = {};
|
|
183
|
+
for (const envVar of args.env || []) {
|
|
184
|
+
const eqIndex = envVar.indexOf('=');
|
|
185
|
+
if (eqIndex > 0) {
|
|
186
|
+
const key = envVar.substring(0, eqIndex);
|
|
187
|
+
const value = envVar.substring(eqIndex + 1);
|
|
188
|
+
env[key] = value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const options = new maestro_options_1.default(app, flows, args.device, {
|
|
192
|
+
includeTags: args.includeTags,
|
|
193
|
+
excludeTags: args.excludeTags,
|
|
194
|
+
platformName: args.platform,
|
|
195
|
+
version: args.deviceVersion,
|
|
196
|
+
name: args.name,
|
|
197
|
+
build: args.build,
|
|
198
|
+
orientation: args.orientation,
|
|
199
|
+
locale: args.deviceLocale,
|
|
200
|
+
timeZone: args.timezone,
|
|
201
|
+
throttleNetwork: args.throttleNetwork,
|
|
202
|
+
geoCountryCode: args.geoCountryCode,
|
|
203
|
+
env: Object.keys(env).length > 0 ? env : undefined,
|
|
204
|
+
maestroVersion: args.maestroVersion,
|
|
205
|
+
quiet: args.quiet,
|
|
206
|
+
async: args.async,
|
|
207
|
+
report: args.report,
|
|
208
|
+
reportOutputDir: args.reportOutputDir,
|
|
209
|
+
realDevice: args.realDevice,
|
|
210
|
+
downloadArtifacts: args.downloadArtifacts,
|
|
211
|
+
artifactsOutputDir: args.artifactsOutputDir,
|
|
212
|
+
});
|
|
213
|
+
const credentials = await auth_1.default.getCredentials({
|
|
214
|
+
apiKey: args.apiKey,
|
|
215
|
+
apiSecret: args.apiSecret,
|
|
216
|
+
});
|
|
217
|
+
if (credentials === null) {
|
|
218
|
+
throw new Error('Please specify credentials via --api-key/--api-secret, TB_KEY/TB_SECRET environment variables, or ~/.testingbot file');
|
|
219
|
+
}
|
|
220
|
+
const maestro = new maestro_1.default(credentials, options);
|
|
221
|
+
const result = await maestro.run();
|
|
222
|
+
if (!result.success) {
|
|
223
|
+
process.exitCode = 1;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
logger_1.default.error(`Maestro error: ${err instanceof Error ? err.message : err}`);
|
|
228
|
+
process.exitCode = 1;
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
.showHelpAfterError(true);
|
|
232
|
+
const xcuitestCommand = program
|
|
233
|
+
.command('xcuitest')
|
|
234
|
+
.description('Run XCUITest tests on TestingBot.')
|
|
235
|
+
.argument('[appFile]', 'Path to application IPA file')
|
|
236
|
+
.argument('[testAppFile]', 'Path to test ZIP file containing XCUITests')
|
|
237
|
+
// App and test options
|
|
238
|
+
.option('--app <path>', 'Path to application IPA file.')
|
|
239
|
+
.option('--test-app <path>', 'Path to test ZIP file containing XCUITests.')
|
|
240
|
+
// Device configuration
|
|
241
|
+
.option('--device <device>', 'Device name to use for testing (e.g., "iPhone 15", "iPad.*").')
|
|
242
|
+
.option('--platform-version <version>', 'iOS version (e.g., "17.0", "18.2").')
|
|
243
|
+
.option('--real-device', 'Use a real device instead of a simulator.')
|
|
244
|
+
.option('--tablet-only', 'Only allocate tablet devices.')
|
|
245
|
+
.option('--phone-only', 'Only allocate phone devices.')
|
|
246
|
+
.option('--orientation <orientation>', 'Screen orientation: PORTRAIT or LANDSCAPE.', (val) => val.toUpperCase())
|
|
247
|
+
.option('--locale <locale>', 'Device locale (e.g., "DE", "US").')
|
|
248
|
+
.option('--timezone <timezone>', 'Device timezone (e.g., "New_York", "Europe/London").')
|
|
249
|
+
// Test metadata
|
|
250
|
+
.option('--name <name>', 'Test name for identification in dashboard.')
|
|
251
|
+
.option('--build <build>', 'Build identifier for grouping test runs.')
|
|
252
|
+
// Localization
|
|
253
|
+
.option('--language <lang>', 'App language (ISO 639-1 code, e.g., "en", "fr", "de").')
|
|
254
|
+
// Geolocation
|
|
255
|
+
.option('--geo-location <code>', 'Geographic IP location (ISO country code, e.g., "US", "DE").')
|
|
256
|
+
// Network throttling
|
|
257
|
+
.option('--throttle-network <speed>', 'Network throttling: 4G, 3G, Edge, or airplane.', (val) => val)
|
|
258
|
+
// Execution mode
|
|
259
|
+
.option('-q, --quiet', 'Quieter console output without progress updates.')
|
|
260
|
+
.option('--async', 'Start tests and exit immediately without waiting for results.')
|
|
261
|
+
// Report options
|
|
262
|
+
.option('--report <format>', 'Download test report after completion: html or junit.', (val) => val.toLowerCase())
|
|
263
|
+
.option('--report-output-dir <path>', 'Directory to save test reports (required when --report is used).')
|
|
264
|
+
// Authentication
|
|
265
|
+
.option('--api-key <key>', 'TestingBot API key.')
|
|
266
|
+
.option('--api-secret <secret>', 'TestingBot API secret.')
|
|
267
|
+
.action(async (appFileArg, testAppFileArg, args) => {
|
|
268
|
+
try {
|
|
269
|
+
// Positional arguments take precedence, fall back to options
|
|
270
|
+
const app = appFileArg || args.app;
|
|
271
|
+
const testApp = testAppFileArg || args.testApp;
|
|
272
|
+
if (!app || !testApp) {
|
|
273
|
+
xcuitestCommand.help();
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const options = new xcuitest_options_1.default(app, testApp, args.device, {
|
|
277
|
+
version: args.platformVersion,
|
|
278
|
+
realDevice: args.realDevice,
|
|
279
|
+
tabletOnly: args.tabletOnly,
|
|
280
|
+
phoneOnly: args.phoneOnly,
|
|
281
|
+
name: args.name,
|
|
282
|
+
build: args.build,
|
|
283
|
+
orientation: args.orientation,
|
|
284
|
+
language: args.language,
|
|
285
|
+
locale: args.locale,
|
|
286
|
+
timeZone: args.timezone,
|
|
287
|
+
geoLocation: args.geoLocation,
|
|
288
|
+
throttleNetwork: args.throttleNetwork,
|
|
289
|
+
quiet: args.quiet,
|
|
290
|
+
async: args.async,
|
|
291
|
+
report: args.report,
|
|
292
|
+
reportOutputDir: args.reportOutputDir,
|
|
293
|
+
});
|
|
294
|
+
const credentials = await auth_1.default.getCredentials({
|
|
295
|
+
apiKey: args.apiKey,
|
|
296
|
+
apiSecret: args.apiSecret,
|
|
297
|
+
});
|
|
298
|
+
if (credentials === null) {
|
|
299
|
+
throw new Error('Please specify credentials via --api-key/--api-secret, TB_KEY/TB_SECRET environment variables, or ~/.testingbot file');
|
|
300
|
+
}
|
|
301
|
+
const xcuitest = new xcuitest_1.default(credentials, options);
|
|
302
|
+
const result = await xcuitest.run();
|
|
303
|
+
if (!result.success) {
|
|
304
|
+
process.exitCode = 1;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch (err) {
|
|
308
|
+
logger_1.default.error(`XCUITest error: ${err instanceof Error ? err.message : err}`);
|
|
309
|
+
process.exitCode = 1;
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
.showHelpAfterError(true);
|
|
313
|
+
program
|
|
314
|
+
.command('login')
|
|
315
|
+
.description('Authenticate with TestingBot via browser.')
|
|
316
|
+
.action(async () => {
|
|
317
|
+
try {
|
|
318
|
+
const login = new login_1.default();
|
|
319
|
+
const result = await login.run();
|
|
320
|
+
if (!result.success) {
|
|
321
|
+
process.exitCode = 1;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
catch (err) {
|
|
325
|
+
logger_1.default.error(`Login error: ${err instanceof Error ? err.message : err}`);
|
|
326
|
+
process.exitCode = 1;
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
exports.default = program;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const cli_1 = __importDefault(require("./cli"));
|
|
8
|
+
cli_1.default.parse(process.argv);
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,QAAA,MAAM,MAAM,8BAWV,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const colors_1 = __importDefault(require("colors"));
|
|
7
|
+
const tracer_1 = __importDefault(require("tracer"));
|
|
8
|
+
const logger = tracer_1.default.colorConsole({
|
|
9
|
+
level: 'info',
|
|
10
|
+
format: '{{timestamp}} {{message}}',
|
|
11
|
+
dateformat: 'HH:MM:ss.L',
|
|
12
|
+
filters: [
|
|
13
|
+
{
|
|
14
|
+
warn: colors_1.default.red,
|
|
15
|
+
debug: colors_1.default.blue,
|
|
16
|
+
error: [colors_1.default.red, colors_1.default.bold],
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
});
|
|
20
|
+
exports.default = logger;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/models/credentials.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,WAAW;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;gBAER,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAKtD,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,SAAS,IAAI,MAAM,CAE7B;IAEM,QAAQ,IAAI,MAAM;CAG1B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class Credentials {
|
|
4
|
+
_userName;
|
|
5
|
+
_accessKey;
|
|
6
|
+
constructor(userName, accessKey) {
|
|
7
|
+
this._userName = userName;
|
|
8
|
+
this._accessKey = accessKey;
|
|
9
|
+
}
|
|
10
|
+
get userName() {
|
|
11
|
+
return this._userName;
|
|
12
|
+
}
|
|
13
|
+
get accessKey() {
|
|
14
|
+
return this._accessKey;
|
|
15
|
+
}
|
|
16
|
+
toString() {
|
|
17
|
+
return this.userName + ':' + '*'.repeat(this.accessKey.length);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = Credentials;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export type TestSize = 'small' | 'medium' | 'large';
|
|
2
|
+
export type ReportFormat = 'html' | 'junit';
|
|
3
|
+
export type ThrottleNetwork = '4G' | '3G' | 'Edge' | 'airplane';
|
|
4
|
+
export interface CustomNetworkProfile {
|
|
5
|
+
uploadSpeed: number;
|
|
6
|
+
downloadSpeed: number;
|
|
7
|
+
latency: number;
|
|
8
|
+
loss: number;
|
|
9
|
+
}
|
|
10
|
+
export interface EspressoCapabilities {
|
|
11
|
+
platformName: 'Android';
|
|
12
|
+
deviceName: string;
|
|
13
|
+
version?: string;
|
|
14
|
+
realDevice?: string;
|
|
15
|
+
tabletOnly?: boolean;
|
|
16
|
+
phoneOnly?: boolean;
|
|
17
|
+
name?: string;
|
|
18
|
+
build?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface EspressoRunOptions {
|
|
21
|
+
testRunner?: string;
|
|
22
|
+
class?: string[];
|
|
23
|
+
notClass?: string[];
|
|
24
|
+
package?: string[];
|
|
25
|
+
notPackage?: string[];
|
|
26
|
+
annotation?: string[];
|
|
27
|
+
notAnnotation?: string[];
|
|
28
|
+
size?: TestSize[];
|
|
29
|
+
language?: string;
|
|
30
|
+
locale?: string;
|
|
31
|
+
timeZone?: string;
|
|
32
|
+
geoLocation?: string;
|
|
33
|
+
throttle_network?: ThrottleNetwork | CustomNetworkProfile;
|
|
34
|
+
}
|
|
35
|
+
export default class EspressoOptions {
|
|
36
|
+
private _app;
|
|
37
|
+
private _testApp;
|
|
38
|
+
private _device?;
|
|
39
|
+
private _version?;
|
|
40
|
+
private _realDevice;
|
|
41
|
+
private _tabletOnly;
|
|
42
|
+
private _phoneOnly;
|
|
43
|
+
private _name?;
|
|
44
|
+
private _build?;
|
|
45
|
+
private _testRunner?;
|
|
46
|
+
private _class?;
|
|
47
|
+
private _notClass?;
|
|
48
|
+
private _package?;
|
|
49
|
+
private _notPackage?;
|
|
50
|
+
private _annotation?;
|
|
51
|
+
private _notAnnotation?;
|
|
52
|
+
private _size?;
|
|
53
|
+
private _language?;
|
|
54
|
+
private _locale?;
|
|
55
|
+
private _timeZone?;
|
|
56
|
+
private _geoLocation?;
|
|
57
|
+
private _throttleNetwork?;
|
|
58
|
+
private _quiet;
|
|
59
|
+
private _async;
|
|
60
|
+
private _report?;
|
|
61
|
+
private _reportOutputDir?;
|
|
62
|
+
constructor(app: string, testApp: string, device?: string, options?: {
|
|
63
|
+
version?: string;
|
|
64
|
+
realDevice?: boolean;
|
|
65
|
+
tabletOnly?: boolean;
|
|
66
|
+
phoneOnly?: boolean;
|
|
67
|
+
name?: string;
|
|
68
|
+
build?: string;
|
|
69
|
+
testRunner?: string;
|
|
70
|
+
class?: string[];
|
|
71
|
+
notClass?: string[];
|
|
72
|
+
package?: string[];
|
|
73
|
+
notPackage?: string[];
|
|
74
|
+
annotation?: string[];
|
|
75
|
+
notAnnotation?: string[];
|
|
76
|
+
size?: TestSize[];
|
|
77
|
+
language?: string;
|
|
78
|
+
locale?: string;
|
|
79
|
+
timeZone?: string;
|
|
80
|
+
geoLocation?: string;
|
|
81
|
+
throttleNetwork?: ThrottleNetwork | CustomNetworkProfile;
|
|
82
|
+
quiet?: boolean;
|
|
83
|
+
async?: boolean;
|
|
84
|
+
report?: ReportFormat;
|
|
85
|
+
reportOutputDir?: string;
|
|
86
|
+
});
|
|
87
|
+
get app(): string;
|
|
88
|
+
get testApp(): string;
|
|
89
|
+
get device(): string | undefined;
|
|
90
|
+
get version(): string | undefined;
|
|
91
|
+
get realDevice(): boolean;
|
|
92
|
+
get tabletOnly(): boolean;
|
|
93
|
+
get phoneOnly(): boolean;
|
|
94
|
+
get name(): string | undefined;
|
|
95
|
+
get build(): string | undefined;
|
|
96
|
+
get testRunner(): string | undefined;
|
|
97
|
+
get class(): string[] | undefined;
|
|
98
|
+
get notClass(): string[] | undefined;
|
|
99
|
+
get package(): string[] | undefined;
|
|
100
|
+
get notPackage(): string[] | undefined;
|
|
101
|
+
get annotation(): string[] | undefined;
|
|
102
|
+
get notAnnotation(): string[] | undefined;
|
|
103
|
+
get size(): TestSize[] | undefined;
|
|
104
|
+
get language(): string | undefined;
|
|
105
|
+
get locale(): string | undefined;
|
|
106
|
+
get timeZone(): string | undefined;
|
|
107
|
+
get geoLocation(): string | undefined;
|
|
108
|
+
get throttleNetwork(): ThrottleNetwork | CustomNetworkProfile | undefined;
|
|
109
|
+
get quiet(): boolean;
|
|
110
|
+
get async(): boolean;
|
|
111
|
+
get report(): ReportFormat | undefined;
|
|
112
|
+
get reportOutputDir(): string | undefined;
|
|
113
|
+
getCapabilities(): EspressoCapabilities;
|
|
114
|
+
getEspressoOptions(): EspressoRunOptions | undefined;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=espresso_options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"espresso_options.d.ts","sourceRoot":"","sources":["../../src/models/espresso_options.ts"],"names":[],"mappings":"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"}
|