@devicecloud.dev/dcd 3.7.11 → 4.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/dist/commands/cloud.d.ts +36 -42
- package/dist/commands/cloud.js +88 -54
- package/dist/commands/status.d.ts +13 -13
- package/dist/commands/status.js +66 -58
- package/dist/commands/upload.d.ts +3 -3
- package/dist/commands/upload.js +2 -2
- package/dist/constants.d.ts +33 -27
- package/dist/constants.js +76 -54
- package/dist/gateways/api-gateway.d.ts +35 -0
- package/dist/gateways/{ApiGateway.js → api-gateway.js} +65 -60
- package/dist/gateways/{SupabaseGateway.d.ts → supabase-gateway.d.ts} +2 -2
- package/dist/gateways/{SupabaseGateway.js → supabase-gateway.js} +7 -4
- package/dist/methods.d.ts +2 -2
- package/dist/methods.js +21 -22
- package/dist/plan.d.ts +1 -1
- package/dist/plan.js +5 -5
- package/dist/planMethods.d.ts +0 -3
- package/dist/planMethods.js +1 -1
- package/dist/types/device.types.d.ts +6 -6
- package/dist/types/device.types.js +6 -6
- package/dist/types/schema.types.d.ts +669 -0
- package/dist/types/schema.types.js +6 -0
- package/dist/utils/compatibility.d.ts +1 -1
- package/dist/utils/compatibility.js +2 -2
- package/oclif.manifest.json +110 -91
- package/package.json +18 -17
- package/dist/gateways/ApiGateway.d.ts +0 -35
package/dist/commands/status.js
CHANGED
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const constants_1 = require("../constants");
|
|
5
|
-
const
|
|
5
|
+
const api_gateway_1 = require("../gateways/api-gateway");
|
|
6
6
|
const methods_1 = require("../methods");
|
|
7
7
|
class Status extends core_1.Command {
|
|
8
8
|
static description = 'Get the status of an upload by name or upload ID';
|
|
9
|
+
static enableJsonFlag = true;
|
|
9
10
|
static examples = [
|
|
10
11
|
'<%= config.bin %> <%= command.id %> --name my-upload-name',
|
|
11
12
|
'<%= config.bin %> <%= command.id %> --upload-id 123e4567-e89b-12d3-a456-426614174000 --json',
|
|
12
13
|
];
|
|
13
|
-
static enableJsonFlag = true;
|
|
14
14
|
static flags = {
|
|
15
|
+
apiKey: constants_1.flags.apiKey,
|
|
16
|
+
apiUrl: constants_1.flags.apiUrl,
|
|
15
17
|
json: core_1.Flags.boolean({
|
|
16
18
|
description: 'output in json format',
|
|
17
19
|
}),
|
|
@@ -23,29 +25,18 @@ class Status extends core_1.Command {
|
|
|
23
25
|
description: 'UUID of the upload to check status for',
|
|
24
26
|
exclusive: ['name'],
|
|
25
27
|
}),
|
|
26
|
-
apiKey: constants_1.flags.apiKey,
|
|
27
|
-
apiUrl: constants_1.flags.apiUrl,
|
|
28
28
|
};
|
|
29
|
-
|
|
30
|
-
switch (status) {
|
|
31
|
-
case 'PASSED':
|
|
32
|
-
return '✓';
|
|
33
|
-
case 'FAILED':
|
|
34
|
-
return '✗';
|
|
35
|
-
case 'CANCELLED':
|
|
36
|
-
return '⊘';
|
|
37
|
-
case 'PENDING':
|
|
38
|
-
return '⋯';
|
|
39
|
-
default:
|
|
40
|
-
return '?';
|
|
41
|
-
}
|
|
42
|
-
}
|
|
29
|
+
// eslint-disable-next-line complexity
|
|
43
30
|
async run() {
|
|
44
31
|
const { flags } = await this.parse(Status);
|
|
45
|
-
const {
|
|
32
|
+
const { apiKey: apiKeyFlag, apiUrl, json, name, 'upload-id': uploadId, } = flags;
|
|
46
33
|
const apiKey = apiKeyFlag || process.env.DEVICE_CLOUD_API_KEY;
|
|
47
34
|
if (!apiKey) {
|
|
48
|
-
this.error('API
|
|
35
|
+
this.error('API key is required. Please provide it via --api-key flag or DEVICE_CLOUD_API_KEY environment variable.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (name && uploadId) {
|
|
39
|
+
this.error('Cannot provide both --name and --upload-id. These options are mutually exclusive.');
|
|
49
40
|
return;
|
|
50
41
|
}
|
|
51
42
|
if (!name && !uploadId) {
|
|
@@ -56,7 +47,7 @@ class Status extends core_1.Command {
|
|
|
56
47
|
let status = null;
|
|
57
48
|
for (let attempt = 1; attempt <= 5; attempt++) {
|
|
58
49
|
try {
|
|
59
|
-
status = (await
|
|
50
|
+
status = (await api_gateway_1.ApiGateway.getUploadStatus(apiUrl, apiKey, {
|
|
60
51
|
name,
|
|
61
52
|
uploadId,
|
|
62
53
|
}));
|
|
@@ -66,7 +57,9 @@ class Status extends core_1.Command {
|
|
|
66
57
|
lastError = error;
|
|
67
58
|
if (attempt < 5) {
|
|
68
59
|
this.log(`Network error on attempt ${attempt}/5. Retrying...`);
|
|
69
|
-
await new Promise((resolve) =>
|
|
60
|
+
await new Promise((resolve) => {
|
|
61
|
+
setTimeout(resolve, 1000 * attempt);
|
|
62
|
+
});
|
|
70
63
|
}
|
|
71
64
|
}
|
|
72
65
|
}
|
|
@@ -74,51 +67,47 @@ class Status extends core_1.Command {
|
|
|
74
67
|
const errorMessage = `Failed to get status after 5 attempts. Check your network. Last error: ${lastError?.message || 'Unknown error'}`;
|
|
75
68
|
if (json) {
|
|
76
69
|
return {
|
|
70
|
+
attempts: 5,
|
|
71
|
+
error: errorMessage,
|
|
77
72
|
status: 'FAILED',
|
|
78
73
|
tests: [],
|
|
79
|
-
error: errorMessage,
|
|
80
|
-
attempts: 5,
|
|
81
74
|
};
|
|
82
75
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
76
|
+
this.error(errorMessage);
|
|
77
|
+
return;
|
|
87
78
|
}
|
|
88
79
|
try {
|
|
89
80
|
if (json) {
|
|
90
81
|
return status;
|
|
91
82
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this.log('');
|
|
121
|
-
});
|
|
83
|
+
this.log('\n📊 Upload Status');
|
|
84
|
+
this.log('═'.repeat(80));
|
|
85
|
+
// Display overall status
|
|
86
|
+
const overallSymbol = this.getStatusSymbol(status.status);
|
|
87
|
+
this.log(`${overallSymbol} Status: ${status.status}`);
|
|
88
|
+
if (status.uploadId) {
|
|
89
|
+
this.log(`🆔 Upload ID: ${status.uploadId}`);
|
|
90
|
+
}
|
|
91
|
+
if (status.appBinaryId) {
|
|
92
|
+
this.log(`📱 Binary ID: ${status.appBinaryId}`);
|
|
93
|
+
}
|
|
94
|
+
if (status.consoleUrl) {
|
|
95
|
+
this.log(`🔗 Console: ${status.consoleUrl}`);
|
|
96
|
+
}
|
|
97
|
+
if (status.tests.length > 0) {
|
|
98
|
+
this.log('\n📋 Test Results');
|
|
99
|
+
this.log('─'.repeat(80));
|
|
100
|
+
for (const item of status.tests) {
|
|
101
|
+
const symbol = this.getStatusSymbol(item.status);
|
|
102
|
+
this.log(`${symbol} ${item.name}`);
|
|
103
|
+
this.log(` Status: ${item.status}`);
|
|
104
|
+
if (item.status === 'FAILED' && item.failReason) {
|
|
105
|
+
this.log(` Fail reason: ${item.failReason}`);
|
|
106
|
+
}
|
|
107
|
+
if (item.durationSeconds) {
|
|
108
|
+
this.log(` Duration: ${(0, methods_1.formatDurationSeconds)(item.durationSeconds)}`);
|
|
109
|
+
}
|
|
110
|
+
this.log('');
|
|
122
111
|
}
|
|
123
112
|
}
|
|
124
113
|
}
|
|
@@ -126,5 +115,24 @@ class Status extends core_1.Command {
|
|
|
126
115
|
this.error(`Failed to get status: ${error.message}`);
|
|
127
116
|
}
|
|
128
117
|
}
|
|
118
|
+
getStatusSymbol(status) {
|
|
119
|
+
switch (status) {
|
|
120
|
+
case 'PASSED': {
|
|
121
|
+
return '✓';
|
|
122
|
+
}
|
|
123
|
+
case 'FAILED': {
|
|
124
|
+
return '✗';
|
|
125
|
+
}
|
|
126
|
+
case 'CANCELLED': {
|
|
127
|
+
return '⊘';
|
|
128
|
+
}
|
|
129
|
+
case 'PENDING': {
|
|
130
|
+
return '⋯';
|
|
131
|
+
}
|
|
132
|
+
default: {
|
|
133
|
+
return '?';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
129
137
|
}
|
|
130
138
|
exports.default = Status;
|
|
@@ -4,14 +4,14 @@ export default class Upload extends Command {
|
|
|
4
4
|
appFile: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
5
|
};
|
|
6
6
|
static description: string;
|
|
7
|
+
static enableJsonFlag: boolean;
|
|
7
8
|
static examples: string[];
|
|
8
9
|
static flags: {
|
|
9
|
-
apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string
|
|
10
|
+
apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
11
|
apiUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
12
|
'ignore-sha-check': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
13
|
};
|
|
13
|
-
static enableJsonFlag: boolean;
|
|
14
14
|
run(): Promise<{
|
|
15
15
|
appBinaryId: string;
|
|
16
|
-
}
|
|
16
|
+
}>;
|
|
17
17
|
}
|
package/dist/commands/upload.js
CHANGED
|
@@ -7,11 +7,12 @@ class Upload extends core_1.Command {
|
|
|
7
7
|
static args = {
|
|
8
8
|
appFile: core_1.Args.string({
|
|
9
9
|
description: 'The binary file to upload (e.g. test.apk for android or test.app/.zip for ios)',
|
|
10
|
-
required: true,
|
|
11
10
|
name: 'App file',
|
|
11
|
+
required: true,
|
|
12
12
|
}),
|
|
13
13
|
};
|
|
14
14
|
static description = 'Upload an app binary to devicecloud.dev';
|
|
15
|
+
static enableJsonFlag = true;
|
|
15
16
|
static examples = [
|
|
16
17
|
'<%= config.bin %> <%= command.id %> path/to/app.apk',
|
|
17
18
|
'<%= config.bin %> <%= command.id %> path/to/app.zip --api-key YOUR_API_KEY',
|
|
@@ -21,7 +22,6 @@ class Upload extends core_1.Command {
|
|
|
21
22
|
apiUrl: constants_1.flags.apiUrl,
|
|
22
23
|
'ignore-sha-check': constants_1.flags['ignore-sha-check'],
|
|
23
24
|
};
|
|
24
|
-
static enableJsonFlag = true;
|
|
25
25
|
async run() {
|
|
26
26
|
try {
|
|
27
27
|
const { args, flags } = await this.parse(Upload);
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,41 +1,47 @@
|
|
|
1
|
+
export declare const SUPPORTED_MAESTRO_VERSIONS: string[];
|
|
2
|
+
export declare const DEFAULT_MAESTRO_VERSION = "1.41.0";
|
|
3
|
+
export declare const getLatestMaestroVersion: () => string;
|
|
4
|
+
export declare const resolveMaestroVersion: (version?: string) => string;
|
|
1
5
|
export declare const flags: {
|
|
2
6
|
'additional-app-binary-ids': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
3
7
|
'additional-app-files': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
4
|
-
'android-api-level': import("@oclif/core/lib/interfaces").OptionFlag<string
|
|
5
|
-
'android-device': import("@oclif/core/lib/interfaces").OptionFlag<string
|
|
6
|
-
|
|
7
|
-
'show-crosshairs': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
-
apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
+
'android-api-level': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
'android-device': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
apiKey: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
11
|
apiUrl: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
-
'app-binary-id': import("@oclif/core/lib/interfaces").OptionFlag<string
|
|
11
|
-
'app-file': import("@oclif/core/lib/interfaces").OptionFlag<string
|
|
12
|
+
'app-binary-id': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
'app-file': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
'artifacts-path': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
15
|
async: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
config: import("@oclif/core/lib/interfaces").OptionFlag<string
|
|
14
|
-
'device-locale': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
-
'download-artifacts': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
-
'artifacts-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
+
config: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
17
|
debug: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
18
|
-
|
|
18
|
+
'device-locale': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
'download-artifacts': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
env: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
22
|
'exclude-flows': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
23
|
'exclude-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
-
flows: import("@oclif/core/lib/interfaces").OptionFlag<string
|
|
24
|
+
flows: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
25
|
'google-play': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
23
|
-
'include-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
26
|
'ignore-sha-check': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
25
|
-
'
|
|
26
|
-
'ios-
|
|
27
|
-
'
|
|
27
|
+
'include-tags': import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
28
|
+
'ios-device': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
|
+
'ios-version': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
30
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
31
|
+
'json-file': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
32
|
+
'json-file-name': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
28
33
|
'maestro-version': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
metadata: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
35
|
+
mitmHost: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
36
|
+
mitmPath: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
37
|
+
'moropo-v1-api-key': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
38
|
+
name: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
39
|
+
orientation: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
33
40
|
quiet: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
34
|
-
|
|
41
|
+
report: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
42
|
+
retry: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
35
43
|
'runner-type': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
'
|
|
39
|
-
'moropo-v1-api-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
40
|
-
'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
44
|
+
'show-crosshairs': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
45
|
+
'skip-chrome-onboarding': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
46
|
+
'x86-arch': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
41
47
|
};
|
package/dist/constants.js
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.flags = void 0;
|
|
3
|
+
exports.flags = exports.resolveMaestroVersion = exports.getLatestMaestroVersion = exports.DEFAULT_MAESTRO_VERSION = exports.SUPPORTED_MAESTRO_VERSIONS = void 0;
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
5
|
const device_types_1 = require("./types/device.types");
|
|
6
|
+
// Centralized maestro version definitions - single source of truth
|
|
7
|
+
exports.SUPPORTED_MAESTRO_VERSIONS = [
|
|
8
|
+
'1.39.0',
|
|
9
|
+
'1.39.1',
|
|
10
|
+
'1.39.2',
|
|
11
|
+
'1.39.4',
|
|
12
|
+
'1.39.5',
|
|
13
|
+
'1.39.7',
|
|
14
|
+
'1.39.13',
|
|
15
|
+
'1.40.0',
|
|
16
|
+
'1.40.1',
|
|
17
|
+
'1.40.2',
|
|
18
|
+
'1.40.3',
|
|
19
|
+
'1.41.0',
|
|
20
|
+
];
|
|
21
|
+
exports.DEFAULT_MAESTRO_VERSION = '1.41.0';
|
|
22
|
+
const getLatestMaestroVersion = () => exports.SUPPORTED_MAESTRO_VERSIONS.at(-1);
|
|
23
|
+
exports.getLatestMaestroVersion = getLatestMaestroVersion;
|
|
24
|
+
const resolveMaestroVersion = (version) => {
|
|
25
|
+
if (version === 'latest') {
|
|
26
|
+
return (0, exports.getLatestMaestroVersion)();
|
|
27
|
+
}
|
|
28
|
+
return version || exports.DEFAULT_MAESTRO_VERSION;
|
|
29
|
+
};
|
|
30
|
+
exports.resolveMaestroVersion = resolveMaestroVersion;
|
|
6
31
|
exports.flags = {
|
|
7
32
|
'additional-app-binary-ids': core_1.Flags.string({
|
|
8
33
|
default: [],
|
|
@@ -26,14 +51,6 @@ exports.flags = {
|
|
|
26
51
|
description: '[Android only] Android device to run your flow against',
|
|
27
52
|
options: Object.values(device_types_1.EAndroidDevices),
|
|
28
53
|
}),
|
|
29
|
-
'skip-chrome-onboarding': core_1.Flags.boolean({
|
|
30
|
-
description: '[Android only] Skip Chrome browser onboarding screens when running tests',
|
|
31
|
-
default: false,
|
|
32
|
-
}),
|
|
33
|
-
'show-crosshairs': core_1.Flags.boolean({
|
|
34
|
-
description: '[Android only] Display crosshairs for screen interactions during test execution',
|
|
35
|
-
default: false,
|
|
36
|
-
}),
|
|
37
54
|
apiKey: core_1.Flags.string({
|
|
38
55
|
aliases: ['api-key'],
|
|
39
56
|
description: 'API key for devicecloud.dev (find this in the console UI). You can also set the DEVICE_CLOUD_API_KEY environment variable.',
|
|
@@ -52,12 +69,20 @@ exports.flags = {
|
|
|
52
69
|
aliases: ['app-file'],
|
|
53
70
|
description: 'App binary to run your flows against',
|
|
54
71
|
}),
|
|
72
|
+
'artifacts-path': core_1.Flags.string({
|
|
73
|
+
dependsOn: ['download-artifacts'],
|
|
74
|
+
description: 'Custom file path for downloaded artifacts (default: ./artifacts.zip)',
|
|
75
|
+
}),
|
|
55
76
|
async: core_1.Flags.boolean({
|
|
56
77
|
description: 'Immediately return (exit code 0) from the command without waiting for the results of the run (useful for saving CI minutes)',
|
|
57
78
|
}),
|
|
58
79
|
config: core_1.Flags.file({
|
|
59
80
|
description: 'Path to custom config.yaml file. If not provided, defaults to config.yaml in root flows folders.',
|
|
60
81
|
}),
|
|
82
|
+
debug: core_1.Flags.boolean({
|
|
83
|
+
default: false,
|
|
84
|
+
description: 'Enable detailed debug logging for troubleshooting issues',
|
|
85
|
+
}),
|
|
61
86
|
'device-locale': core_1.Flags.string({
|
|
62
87
|
description: 'Locale that will be set to a device, ISO-639-1 code and uppercase ISO-3166-1 code e.g. "de_DE" for Germany',
|
|
63
88
|
}),
|
|
@@ -65,13 +90,9 @@ exports.flags = {
|
|
|
65
90
|
description: 'Download a zip containing the logs, screenshots and videos for each result in this run. You will debited a $0.01 egress fee for each result. Use --download-artifacts=FAILED for failures only or --download-artifacts=ALL for every result.',
|
|
66
91
|
options: ['ALL', 'FAILED'],
|
|
67
92
|
}),
|
|
68
|
-
'
|
|
69
|
-
description: 'Custom file path for downloaded artifacts (default: ./artifacts.zip)',
|
|
70
|
-
dependsOn: ['download-artifacts'],
|
|
71
|
-
}),
|
|
72
|
-
debug: core_1.Flags.boolean({
|
|
73
|
-
description: 'Enable detailed debug logging for troubleshooting issues',
|
|
93
|
+
'dry-run': core_1.Flags.boolean({
|
|
74
94
|
default: false,
|
|
95
|
+
description: 'Simulate the run without actually triggering the upload/test, useful for debugging workflow issues.',
|
|
75
96
|
}),
|
|
76
97
|
env: core_1.Flags.file({
|
|
77
98
|
char: 'e',
|
|
@@ -102,6 +123,9 @@ exports.flags = {
|
|
|
102
123
|
default: false,
|
|
103
124
|
description: '[Android only] Run your flow against Google Play devices',
|
|
104
125
|
}),
|
|
126
|
+
'ignore-sha-check': core_1.Flags.boolean({
|
|
127
|
+
description: 'Ignore the sha hash check and upload the binary regardless of whether it already exists (not recommended)',
|
|
128
|
+
}),
|
|
105
129
|
'include-tags': core_1.Flags.string({
|
|
106
130
|
aliases: ['include-tags'],
|
|
107
131
|
default: [],
|
|
@@ -110,9 +134,6 @@ exports.flags = {
|
|
|
110
134
|
multipleNonGreedy: true,
|
|
111
135
|
parse: (input) => input.split(','),
|
|
112
136
|
}),
|
|
113
|
-
'ignore-sha-check': core_1.Flags.boolean({
|
|
114
|
-
description: 'Ignore the sha hash check and upload the binary regardless of whether it already exists (not recommended)',
|
|
115
|
-
}),
|
|
116
137
|
'ios-device': core_1.Flags.string({
|
|
117
138
|
description: '[iOS only] iOS device to run your flow against',
|
|
118
139
|
options: Object.values(device_types_1.EiOSDevices),
|
|
@@ -121,35 +142,39 @@ exports.flags = {
|
|
|
121
142
|
description: '[iOS only] iOS version to run your flow against',
|
|
122
143
|
options: Object.values(device_types_1.EiOSVersions),
|
|
123
144
|
}),
|
|
124
|
-
|
|
125
|
-
description: '
|
|
126
|
-
|
|
145
|
+
json: core_1.Flags.boolean({
|
|
146
|
+
description: 'Output results in JSON format - note: will always provide exit code 0',
|
|
147
|
+
}),
|
|
148
|
+
'json-file': core_1.Flags.boolean({
|
|
149
|
+
description: 'Write JSON output to a file. File be called <upload_id>_dcd.json unless you supply the --json-file-name flag - note: will always exit with code 0',
|
|
150
|
+
required: false,
|
|
151
|
+
}),
|
|
152
|
+
'json-file-name': core_1.Flags.string({
|
|
153
|
+
description: 'A custom name for the JSON file (can also include relative path)',
|
|
154
|
+
dependsOn: ['json-file'],
|
|
127
155
|
}),
|
|
128
156
|
'maestro-version': core_1.Flags.string({
|
|
129
157
|
aliases: ['maestroVersion'],
|
|
130
|
-
default:
|
|
158
|
+
default: exports.DEFAULT_MAESTRO_VERSION,
|
|
131
159
|
description: 'Maestro version to run your flow against',
|
|
132
|
-
options: [
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
'1.39.13',
|
|
140
|
-
'1.40.0',
|
|
141
|
-
'1.40.1',
|
|
142
|
-
'1.40.2',
|
|
143
|
-
'1.40.3',
|
|
144
|
-
'1.41.0',
|
|
145
|
-
],
|
|
160
|
+
options: [...exports.SUPPORTED_MAESTRO_VERSIONS, 'latest'],
|
|
161
|
+
}),
|
|
162
|
+
metadata: core_1.Flags.string({
|
|
163
|
+
char: 'm',
|
|
164
|
+
description: 'Arbitrary key-value metadata to include with your test run (format: key=value)',
|
|
165
|
+
multiple: true,
|
|
166
|
+
multipleNonGreedy: true,
|
|
146
167
|
}),
|
|
147
168
|
mitmHost: core_1.Flags.string({
|
|
148
169
|
description: 'used for mitmproxy support, enterprise only, contact support if interested',
|
|
149
170
|
}),
|
|
150
171
|
mitmPath: core_1.Flags.string({
|
|
151
|
-
description: 'used for mitmproxy support, enterprise only, contact support if interested',
|
|
152
172
|
dependsOn: ['mitmHost'],
|
|
173
|
+
description: 'used for mitmproxy support, enterprise only, contact support if interested',
|
|
174
|
+
}),
|
|
175
|
+
'moropo-v1-api-key': core_1.Flags.string({
|
|
176
|
+
description: 'API key for Moropo v1 integration',
|
|
177
|
+
required: false,
|
|
153
178
|
}),
|
|
154
179
|
name: core_1.Flags.string({
|
|
155
180
|
description: 'A custom name for your upload (useful for tagging commits etc)',
|
|
@@ -163,32 +188,29 @@ exports.flags = {
|
|
|
163
188
|
default: false,
|
|
164
189
|
description: 'Quieter console output that wont provide progress updates',
|
|
165
190
|
}),
|
|
191
|
+
report: core_1.Flags.string({
|
|
192
|
+
aliases: ['format'],
|
|
193
|
+
description: 'Runs Maestro with the --format flag, this will generate a report in the specified format',
|
|
194
|
+
options: ['junit', 'html'],
|
|
195
|
+
}),
|
|
166
196
|
retry: core_1.Flags.integer({
|
|
167
197
|
description: 'Automatically retry the run up to the number of times specified (same as pressing retry in the UI) - this is free of charge',
|
|
168
198
|
}),
|
|
169
199
|
'runner-type': core_1.Flags.string({
|
|
170
|
-
description: '[experimental] The type of runner to use - note: anything other than default will incur premium pricing tiers, see https://docs.devicecloud.dev/reference/runner-type for more information',
|
|
171
200
|
default: 'default',
|
|
201
|
+
description: '[experimental] The type of runner to use - note: anything other than default will incur premium pricing tiers, see https://docs.devicecloud.dev/reference/runner-type for more information',
|
|
172
202
|
options: ['default', 'm4', 'm1'],
|
|
173
203
|
}),
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
description: '
|
|
177
|
-
options: ['junit', 'html'],
|
|
178
|
-
}),
|
|
179
|
-
json: core_1.Flags.boolean({
|
|
180
|
-
description: 'Output results in JSON format - note: will always provide exit code 0',
|
|
181
|
-
}),
|
|
182
|
-
'json-file': core_1.Flags.boolean({
|
|
183
|
-
description: 'Write JSON output to a file. If you supply the --name flag, file <name>_dcd.json will be written, otherwise file <upload_id>_dcd.json will be written - note: will always exit with code 0',
|
|
184
|
-
required: false,
|
|
204
|
+
'show-crosshairs': core_1.Flags.boolean({
|
|
205
|
+
default: false,
|
|
206
|
+
description: '[Android only] Display crosshairs for screen interactions during test execution',
|
|
185
207
|
}),
|
|
186
|
-
'
|
|
187
|
-
|
|
188
|
-
|
|
208
|
+
'skip-chrome-onboarding': core_1.Flags.boolean({
|
|
209
|
+
default: false,
|
|
210
|
+
description: '[Android only] Skip Chrome browser onboarding screens when running tests',
|
|
189
211
|
}),
|
|
190
|
-
'
|
|
191
|
-
description: 'Simulate the run without actually triggering the upload/test, useful for debugging workflow issues.',
|
|
212
|
+
'x86-arch': core_1.Flags.boolean({
|
|
192
213
|
default: false,
|
|
214
|
+
description: '[iOS only, experimental] Run your flow against x86 architecture simulator instead of arm64',
|
|
193
215
|
}),
|
|
194
216
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { TAppMetadata } from '../types';
|
|
2
|
+
export declare const ApiGateway: {
|
|
3
|
+
checkForExistingUpload(baseUrl: string, apiKey: string, sha: string): Promise<{
|
|
4
|
+
appBinaryId: string;
|
|
5
|
+
exists: boolean;
|
|
6
|
+
}>;
|
|
7
|
+
downloadArtifactsZip(baseUrl: string, apiKey: string, uploadId: string, results: "ALL" | "FAILED", artifactsPath?: string): Promise<void>;
|
|
8
|
+
finaliseUpload(baseUrl: string, apiKey: string, id: string, metadata: TAppMetadata, path: string, sha: string): Promise<Record<string, never>>;
|
|
9
|
+
getBinaryUploadUrl(baseUrl: string, apiKey: string, platform: "android" | "ios"): Promise<{
|
|
10
|
+
id: string;
|
|
11
|
+
message: string;
|
|
12
|
+
path: string;
|
|
13
|
+
token: string;
|
|
14
|
+
}>;
|
|
15
|
+
getResultsForUpload(baseUrl: string, apiKey: string, uploadId: string): Promise<{
|
|
16
|
+
results?: import("../types/schema.types").components["schemas"]["TResultResponse"][];
|
|
17
|
+
statusCode?: number;
|
|
18
|
+
}>;
|
|
19
|
+
getUploadStatus(baseUrl: string, apiKey: string, options: {
|
|
20
|
+
name?: string;
|
|
21
|
+
uploadId?: string;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
status: "CANCELLED" | "FAILED" | "PASSED" | "PENDING";
|
|
24
|
+
tests: Array<{
|
|
25
|
+
durationSeconds?: number;
|
|
26
|
+
failReason?: string;
|
|
27
|
+
name: string;
|
|
28
|
+
status: "CANCELLED" | "FAILED" | "PASSED" | "PENDING";
|
|
29
|
+
}>;
|
|
30
|
+
}>;
|
|
31
|
+
uploadFlow(baseUrl: string, apiKey: string, testFormData: FormData): Promise<{
|
|
32
|
+
message?: string;
|
|
33
|
+
results?: import("../types/schema.types").components["schemas"]["IDBResult"][];
|
|
34
|
+
}>;
|
|
35
|
+
};
|