@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.
@@ -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 no-process-exit, unicorn/no-process-exit
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 + 1).join(path.sep);
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
- ${Boolean(additionalAppBinaryIds || additionalAppFiles) &&
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
- testFormData.set('config', JSON.stringify({
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 no-process-exit, unicorn/no-process-exit
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
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.run = void 0;
4
3
  var core_1 = require("@oclif/core");
5
4
  Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
package/dist/methods.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import * as archiver from 'archiver';
3
2
  import { paths } from '../../api/schema.types';
4
3
  import { TAppMetadata } from './types';
package/dist/plan.js CHANGED
@@ -1,49 +1,70 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.plan = void 0;
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 plan(input, includeTags, excludeTags, excludeFlows) {
9
- if (!fs.existsSync(input)) {
10
- throw new Error(`Flow path does not exist: ${path.resolve(input)}`);
11
- }
12
- if (fs.lstatSync(input).isFile()) {
13
- const { config, testSteps } = (0, planMethods_1.readTestYamlFileAsJson)(input);
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(allFiles)],
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
- // filter out files that match the exclude list
35
- if (excludeFlows) {
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 { configPerFlowFile, testStepsPerFlowFile } =
86
+ const configPerFlowFile =
66
87
  // eslint-disable-next-line unicorn/no-array-reduce
67
88
  unfilteredFlowFiles.reduce((acc, filePath) => {
68
- const { config, testSteps } = (0, planMethods_1.readTestYamlFileAsJson)(filePath);
69
- acc.configPerFlowFile[filePath] = config;
70
- acc.testStepsPerFlowFile[filePath] = testSteps;
89
+ const { config } = (0, planMethods_1.readTestYamlFileAsJson)(filePath);
90
+ acc[filePath] = config;
71
91
  return acc;
72
- }, {
73
- configPerFlowFile: {},
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;
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.processDependencies = exports.checkIfFilesExistInWorkspace = exports.readDirectory = exports.readTestYamlFileAsJson = exports.readYamlFileAsJson = exports.isFlowFile = exports.getFlowsToRunInSequence = void 0;
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) {
@@ -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-rc.2"
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": "@devicecloud.dev/dcd"
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-rc.2",
83
+ "version": "2.0.0",
84
84
  "bugs": {
85
85
  "url": "https://discord.gg/gm3mJwcNw8"
86
86
  },