@devicecloud.dev/dcd 2.0.0-rc.2 → 2.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.js +16 -9
- package/dist/constants.js +2 -1
- package/dist/index.js +0 -1
- package/dist/methods.d.ts +0 -1
- package/dist/plan.js +49 -49
- package/dist/planMethods.js +7 -6
- package/oclif.manifest.json +5 -3
- package/package.json +2 -2
package/dist/commands/cloud.js
CHANGED
|
@@ -97,7 +97,7 @@ class Cloud extends core_1.Command {
|
|
|
97
97
|
}
|
|
98
98
|
catch (error) {
|
|
99
99
|
console.error(error);
|
|
100
|
-
// eslint-disable-next-line
|
|
100
|
+
// eslint-disable-next-line unicorn/no-process-exit
|
|
101
101
|
process.exit(2);
|
|
102
102
|
}
|
|
103
103
|
const { allExcludeTags, allIncludeTags, flowsToRun: testFileNames, referencedFiles, sequence, } = executionPlan;
|
|
@@ -108,7 +108,7 @@ class Cloud extends core_1.Command {
|
|
|
108
108
|
let commonRoot = path.parse(process.cwd()).root;
|
|
109
109
|
const folders = pathsShortestToLongest[0].split(path.sep);
|
|
110
110
|
for (const [index] of folders.entries()) {
|
|
111
|
-
const folderPath = folders.slice(0, index
|
|
111
|
+
const folderPath = folders.slice(0, index).join(path.sep);
|
|
112
112
|
const isRoot = pathsShortestToLongest.every((file) => file.startsWith(folderPath));
|
|
113
113
|
if (isRoot)
|
|
114
114
|
commonRoot = folderPath;
|
|
@@ -137,8 +137,9 @@ class Cloud extends core_1.Command {
|
|
|
137
137
|
Submitting new job
|
|
138
138
|
→ Flow(s): ${flowFile}
|
|
139
139
|
→ App: ${appBinaryId || finalAppFile}
|
|
140
|
-
${
|
|
141
|
-
`→ Additional app(s): ${additionalAppBinaryIds} ${additionalAppFiles}`
|
|
140
|
+
${additionalAppBinaryIds.length > 0 || additionalAppFiles.length > 0
|
|
141
|
+
? `→ Additional app(s): ${additionalAppBinaryIds} ${additionalAppFiles}`
|
|
142
|
+
: ''}
|
|
142
143
|
|
|
143
144
|
With options
|
|
144
145
|
→ ${flagLogs.join(`
|
|
@@ -185,18 +186,24 @@ class Cloud extends core_1.Command {
|
|
|
185
186
|
testFormData.set('sequentialFlows', JSON.stringify(sequentialFlows));
|
|
186
187
|
testFormData.set('env', JSON.stringify(envObject));
|
|
187
188
|
testFormData.set('googlePlay', googlePlay ? 'true' : 'false');
|
|
188
|
-
|
|
189
|
-
additionalAppBinaryIds: finalAdditionalBinaryIds,
|
|
189
|
+
const config = {
|
|
190
190
|
allExcludeTags,
|
|
191
191
|
allIncludeTags,
|
|
192
192
|
continueOnFailure,
|
|
193
193
|
deviceLocale,
|
|
194
194
|
maestroVersion,
|
|
195
195
|
orientation,
|
|
196
|
-
raw,
|
|
196
|
+
raw: JSON.stringify(raw),
|
|
197
197
|
uploadedBinaryIds,
|
|
198
198
|
version: this.config.version,
|
|
199
|
-
}
|
|
199
|
+
};
|
|
200
|
+
if (finalAdditionalBinaryIds?.length > 0) {
|
|
201
|
+
config.additionalAppBinaryIds = finalAdditionalBinaryIds;
|
|
202
|
+
}
|
|
203
|
+
if (uploadedBinaryIds?.length > 0) {
|
|
204
|
+
config.uploadedBinaryIds = uploadedBinaryIds;
|
|
205
|
+
}
|
|
206
|
+
testFormData.set('config', JSON.stringify(config));
|
|
200
207
|
if (androidApiLevel)
|
|
201
208
|
testFormData.set('androidApiLevel', androidApiLevel.toString());
|
|
202
209
|
if (androidDevice)
|
|
@@ -277,7 +284,7 @@ class Cloud extends core_1.Command {
|
|
|
277
284
|
}
|
|
278
285
|
}
|
|
279
286
|
if (updatedResults.some((result) => result.status === 'FAILED')) {
|
|
280
|
-
// eslint-disable-next-line
|
|
287
|
+
// eslint-disable-next-line unicorn/no-process-exit
|
|
281
288
|
process.exit(2);
|
|
282
289
|
}
|
|
283
290
|
sequentialPollFaillures = 0;
|
package/dist/constants.js
CHANGED
|
@@ -19,7 +19,7 @@ exports.flags = {
|
|
|
19
19
|
}),
|
|
20
20
|
'android-api-level': core_1.Flags.integer({
|
|
21
21
|
description: '[Android only] Android API level to run your flow against',
|
|
22
|
-
options: ['33', '34'],
|
|
22
|
+
options: ['33', '34', '35'],
|
|
23
23
|
}),
|
|
24
24
|
'android-device': core_1.Flags.string({
|
|
25
25
|
description: '[Android only] Android device to run your flow against',
|
|
@@ -139,6 +139,7 @@ exports.flags = {
|
|
|
139
139
|
'1.37.8',
|
|
140
140
|
'1.37.9',
|
|
141
141
|
'1.38.1',
|
|
142
|
+
'1.39.0',
|
|
142
143
|
],
|
|
143
144
|
}),
|
|
144
145
|
name: core_1.Flags.string({
|
package/dist/index.js
CHANGED
package/dist/methods.d.ts
CHANGED
package/dist/plan.js
CHANGED
|
@@ -1,49 +1,70 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.plan =
|
|
3
|
+
exports.plan = plan;
|
|
4
4
|
const glob_1 = require("glob");
|
|
5
5
|
const fs = require("node:fs");
|
|
6
6
|
const path = require("node:path");
|
|
7
7
|
const planMethods_1 = require("./planMethods");
|
|
8
|
-
async function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const { config, testSteps } = (0, planMethods_1.readTestYamlFileAsJson)(
|
|
8
|
+
async function checkDependencies(input) {
|
|
9
|
+
const checkedDependencies = [];
|
|
10
|
+
const uncheckedDependencies = [input];
|
|
11
|
+
while (uncheckedDependencies.length > 0) {
|
|
12
|
+
const fileToCheck = uncheckedDependencies.shift();
|
|
13
|
+
const { config, testSteps } = (0, planMethods_1.readTestYamlFileAsJson)(fileToCheck);
|
|
14
14
|
const { allErrors, allFiles } = (0, planMethods_1.processDependencies)({
|
|
15
15
|
config,
|
|
16
|
-
input,
|
|
16
|
+
input: fileToCheck,
|
|
17
17
|
testSteps,
|
|
18
18
|
});
|
|
19
19
|
if (allErrors.length > 0) {
|
|
20
20
|
throw new Error('The following flow files are not present in the filesystem: \n' +
|
|
21
21
|
allErrors.join('\n'));
|
|
22
22
|
}
|
|
23
|
+
for (const file of allFiles) {
|
|
24
|
+
if (!(0, planMethods_1.isFlowFile)(file)) {
|
|
25
|
+
// js/media files don't have dependencies
|
|
26
|
+
checkedDependencies.push(file);
|
|
27
|
+
}
|
|
28
|
+
if (!checkedDependencies.includes(file)) {
|
|
29
|
+
uncheckedDependencies.push(file);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!checkedDependencies.includes(fileToCheck)) {
|
|
33
|
+
checkedDependencies.push(fileToCheck);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return checkedDependencies;
|
|
37
|
+
}
|
|
38
|
+
function filterFlowFiles(unfilteredFlowFiles, excludeFlows) {
|
|
39
|
+
if (excludeFlows) {
|
|
40
|
+
return unfilteredFlowFiles.filter((file) => !excludeFlows.some((flow) => file.startsWith(path.resolve(flow))));
|
|
41
|
+
}
|
|
42
|
+
return unfilteredFlowFiles;
|
|
43
|
+
}
|
|
44
|
+
function getWorkspaceConfig(input, unfilteredFlowFiles) {
|
|
45
|
+
const configFilePath = unfilteredFlowFiles.find((file) => file === input + 'config.yaml' || file === input + 'config.yml');
|
|
46
|
+
return configFilePath
|
|
47
|
+
? (0, planMethods_1.readYamlFileAsJson)(configFilePath)
|
|
48
|
+
: {};
|
|
49
|
+
}
|
|
50
|
+
async function plan(input, includeTags, excludeTags, excludeFlows) {
|
|
51
|
+
if (!fs.existsSync(input)) {
|
|
52
|
+
throw new Error(`Flow path does not exist: ${path.resolve(input)}`);
|
|
53
|
+
}
|
|
54
|
+
if (fs.lstatSync(input).isFile()) {
|
|
55
|
+
const checkedDependancies = await checkDependencies(input);
|
|
23
56
|
return {
|
|
24
57
|
flowsToRun: [input],
|
|
25
|
-
referencedFiles: [...new Set(
|
|
58
|
+
referencedFiles: [...new Set(checkedDependancies)],
|
|
26
59
|
totalFlowFiles: 1,
|
|
27
60
|
};
|
|
28
61
|
}
|
|
29
|
-
// raw list of all yaml files in workspace directory
|
|
30
62
|
let unfilteredFlowFiles = await (0, planMethods_1.readDirectory)(input, planMethods_1.isFlowFile);
|
|
31
63
|
if (unfilteredFlowFiles.length === 0) {
|
|
32
64
|
throw new Error(`Flow directory does not contain any Flow files: ${path.resolve(input)}`);
|
|
33
65
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
for (const flow of excludeFlows) {
|
|
37
|
-
unfilteredFlowFiles = unfilteredFlowFiles.filter((file) => !file.startsWith(path.resolve(flow)));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
// if config file present at top level, use it
|
|
41
|
-
const configFilePath = unfilteredFlowFiles.find((file) => file === input + 'config.yaml' || file === input + 'config.yml');
|
|
42
|
-
// remove all config files from the list to prevent processing them
|
|
43
|
-
unfilteredFlowFiles = unfilteredFlowFiles.filter((file) => !(file.endsWith('config.yaml') || file.endsWith('config.yml')));
|
|
44
|
-
const workspaceConfig = configFilePath
|
|
45
|
-
? (0, planMethods_1.readYamlFileAsJson)(configFilePath)
|
|
46
|
-
: {};
|
|
66
|
+
unfilteredFlowFiles = filterFlowFiles(unfilteredFlowFiles, excludeFlows);
|
|
67
|
+
const workspaceConfig = getWorkspaceConfig(input, unfilteredFlowFiles);
|
|
47
68
|
if (workspaceConfig.flows) {
|
|
48
69
|
const globs = workspaceConfig.flows.map((glob) => glob);
|
|
49
70
|
const matchedFiles = await (0, glob_1.glob)(globs, {
|
|
@@ -62,34 +83,14 @@ async function plan(input, includeTags, excludeTags, excludeFlows) {
|
|
|
62
83
|
: new Error(`Workspace does not contain any Flows: ${path.resolve(input)}`);
|
|
63
84
|
throw error;
|
|
64
85
|
}
|
|
65
|
-
const
|
|
86
|
+
const configPerFlowFile =
|
|
66
87
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
67
88
|
unfilteredFlowFiles.reduce((acc, filePath) => {
|
|
68
|
-
const { config
|
|
69
|
-
acc
|
|
70
|
-
acc.testStepsPerFlowFile[filePath] = testSteps;
|
|
89
|
+
const { config } = (0, planMethods_1.readTestYamlFileAsJson)(filePath);
|
|
90
|
+
acc[filePath] = config;
|
|
71
91
|
return acc;
|
|
72
|
-
}, {
|
|
73
|
-
|
|
74
|
-
testStepsPerFlowFile: {},
|
|
75
|
-
});
|
|
76
|
-
let errors = [];
|
|
77
|
-
let allFiles = [];
|
|
78
|
-
for (const [filePath, testSteps] of Object.entries(testStepsPerFlowFile)) {
|
|
79
|
-
if (!testSteps)
|
|
80
|
-
break;
|
|
81
|
-
const { allErrors: errs, allFiles: deps } = (0, planMethods_1.processDependencies)({
|
|
82
|
-
config: configPerFlowFile[filePath],
|
|
83
|
-
input: filePath,
|
|
84
|
-
testSteps,
|
|
85
|
-
});
|
|
86
|
-
allFiles = [...allFiles, ...deps];
|
|
87
|
-
errors = [...errors, ...errs];
|
|
88
|
-
}
|
|
89
|
-
if (errors.length > 0) {
|
|
90
|
-
throw new Error('The following flow files are not present in the provided directory: \n' +
|
|
91
|
-
errors.join('\n'));
|
|
92
|
-
}
|
|
92
|
+
}, {});
|
|
93
|
+
const allFiles = await Promise.all(unfilteredFlowFiles.map((filePath) => checkDependencies(filePath))).then((results) => [...new Set(results.flat())]);
|
|
93
94
|
const allIncludeTags = [
|
|
94
95
|
...includeTags,
|
|
95
96
|
...(workspaceConfig.includeTags || []),
|
|
@@ -131,4 +132,3 @@ async function plan(input, includeTags, excludeTags, excludeFlows) {
|
|
|
131
132
|
totalFlowFiles: unfilteredFlowFiles.length,
|
|
132
133
|
};
|
|
133
134
|
}
|
|
134
|
-
exports.plan = plan;
|
package/dist/planMethods.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.processDependencies = exports.checkIfFilesExistInWorkspace = exports.
|
|
3
|
+
exports.processDependencies = exports.checkIfFilesExistInWorkspace = exports.readTestYamlFileAsJson = exports.readYamlFileAsJson = void 0;
|
|
4
|
+
exports.getFlowsToRunInSequence = getFlowsToRunInSequence;
|
|
5
|
+
exports.isFlowFile = isFlowFile;
|
|
6
|
+
exports.readDirectory = readDirectory;
|
|
4
7
|
/* eslint-disable unicorn/filename-case */
|
|
5
8
|
const yaml = require("js-yaml");
|
|
6
9
|
const fs = require("node:fs");
|
|
@@ -28,11 +31,9 @@ function getFlowsToRunInSequence(paths, flowOrder) {
|
|
|
28
31
|
return [];
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
|
-
exports.getFlowsToRunInSequence = getFlowsToRunInSequence;
|
|
32
34
|
function isFlowFile(filePath) {
|
|
33
35
|
return filePath.endsWith('.yaml') || filePath.endsWith('.yml');
|
|
34
36
|
}
|
|
35
|
-
exports.isFlowFile = isFlowFile;
|
|
36
37
|
const readYamlFileAsJson = (filePath) => {
|
|
37
38
|
const yamlText = fs.readFileSync(filePath, 'utf8');
|
|
38
39
|
return yaml.load(yamlText);
|
|
@@ -71,7 +72,6 @@ async function readDirectory(dir, filterFunction) {
|
|
|
71
72
|
}));
|
|
72
73
|
return files.flat().filter(Boolean);
|
|
73
74
|
}
|
|
74
|
-
exports.readDirectory = readDirectory;
|
|
75
75
|
const checkIfFilesExistInWorkspace = (commandName, command, absoluteFilePath) => {
|
|
76
76
|
const errors = [];
|
|
77
77
|
const files = [];
|
|
@@ -85,8 +85,9 @@ const checkIfFilesExistInWorkspace = (commandName, command, absoluteFilePath) =>
|
|
|
85
85
|
files.push(absoluteFilePath);
|
|
86
86
|
};
|
|
87
87
|
// simple command
|
|
88
|
-
if (typeof command === 'string')
|
|
89
|
-
processFilePath(command);
|
|
88
|
+
if (typeof command === 'string') {
|
|
89
|
+
processFilePath(path.normalize(directory + '/' + command));
|
|
90
|
+
}
|
|
90
91
|
// array command
|
|
91
92
|
if (Array.isArray(command)) {
|
|
92
93
|
for (const file of command) {
|
package/oclif.manifest.json
CHANGED
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"multiple": false,
|
|
43
43
|
"options": [
|
|
44
44
|
"33",
|
|
45
|
-
"34"
|
|
45
|
+
"34",
|
|
46
|
+
"35"
|
|
46
47
|
],
|
|
47
48
|
"type": "option"
|
|
48
49
|
},
|
|
@@ -243,7 +244,8 @@
|
|
|
243
244
|
"1.37.7",
|
|
244
245
|
"1.37.8",
|
|
245
246
|
"1.37.9",
|
|
246
|
-
"1.38.1"
|
|
247
|
+
"1.38.1",
|
|
248
|
+
"1.39.0"
|
|
247
249
|
],
|
|
248
250
|
"type": "option"
|
|
249
251
|
},
|
|
@@ -291,5 +293,5 @@
|
|
|
291
293
|
]
|
|
292
294
|
}
|
|
293
295
|
},
|
|
294
|
-
"version": "2.0.0
|
|
296
|
+
"version": "2.0.0"
|
|
295
297
|
}
|
package/package.json
CHANGED
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"private": false,
|
|
67
67
|
"repository": {
|
|
68
68
|
"type": "git",
|
|
69
|
-
"url": "
|
|
69
|
+
"url": "https://devicecloud.dev"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"dcd": "./bin/dev.js",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
|
|
81
81
|
"version": "oclif readme && git add README.md"
|
|
82
82
|
},
|
|
83
|
-
"version": "2.0.0
|
|
83
|
+
"version": "2.0.0",
|
|
84
84
|
"bugs": {
|
|
85
85
|
"url": "https://discord.gg/gm3mJwcNw8"
|
|
86
86
|
},
|