@devicecloud.dev/dcd 0.0.4 → 0.0.5
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 +13 -7
- package/dist/methods.d.ts +1 -0
- package/dist/methods.js +13 -1
- package/dist/plan.js +18 -43
- package/dist/planMethods.d.ts +11 -0
- package/dist/planMethods.js +28 -2
- package/oclif.manifest.json +2 -2
- package/package.json +1 -1
package/dist/commands/cloud.js
CHANGED
|
@@ -36,7 +36,7 @@ var EiOSDevices;
|
|
|
36
36
|
class Cloud extends core_1.Command {
|
|
37
37
|
static args = {
|
|
38
38
|
firstFile: core_1.Args.string({
|
|
39
|
-
description: 'The binary file of the app to run your flow against, e.g.
|
|
39
|
+
description: 'The binary file of the app to run your flow against, e.g. test.apk for android or test.app/.zip for ios',
|
|
40
40
|
hidden: true,
|
|
41
41
|
name: 'App file',
|
|
42
42
|
}),
|
|
@@ -98,8 +98,8 @@ class Cloud extends core_1.Command {
|
|
|
98
98
|
if (!(flowFile && finalAppFile)) {
|
|
99
99
|
throw new Error('You must provide a flow file and an app binary id');
|
|
100
100
|
}
|
|
101
|
-
if (!
|
|
102
|
-
throw new Error('App file must be a .apk or .zip file');
|
|
101
|
+
if (!['apk', '.app', '.zip'].some((ext) => finalAppFile.endsWith(ext))) {
|
|
102
|
+
throw new Error('App file must be a .apk for android or .app/.zip file for iOS');
|
|
103
103
|
}
|
|
104
104
|
if (finalAppFile.endsWith('.zip')) {
|
|
105
105
|
await (0, methods_1.verifyAppZip)(finalAppFile);
|
|
@@ -125,10 +125,16 @@ class Cloud extends core_1.Command {
|
|
|
125
125
|
if (!finalBinaryId) {
|
|
126
126
|
core_1.ux.action.start('Uploading binary', 'Initializing', { stdout: true });
|
|
127
127
|
const binaryFormData = new FormData();
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
128
|
+
if (finalAppFile?.endsWith('.app')) {
|
|
129
|
+
const zippedAppBlob = await (0, methods_1.compressFolderToBlob)(finalAppFile);
|
|
130
|
+
binaryFormData.set('file', zippedAppBlob, finalAppFile + '.zip');
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
const binaryBlob = new Blob([await (0, promises_1.readFile)(finalAppFile)], {
|
|
134
|
+
type: mimeTypeLookupByExtension[finalAppFile.split('.').pop()],
|
|
135
|
+
});
|
|
136
|
+
binaryFormData.set('file', binaryBlob, finalAppFile);
|
|
137
|
+
}
|
|
132
138
|
const options = {
|
|
133
139
|
body: binaryFormData,
|
|
134
140
|
headers: { 'x-app-api-key': apiKey },
|
package/dist/methods.d.ts
CHANGED
|
@@ -11,5 +11,6 @@ export declare const typeSafeGet: <T extends keyof paths>(baseUrl: string, path:
|
|
|
11
11
|
}) => Promise<paths[T]["get"]["responses"]["200"]["content"]["application/json"]>;
|
|
12
12
|
export declare const toBuffer: (archive: archiver.Archiver) => Promise<Buffer>;
|
|
13
13
|
export declare const compressDir: (sourceDir: string) => Promise<Buffer>;
|
|
14
|
+
export declare const compressFolderToBlob: (sourceDir: string) => Promise<Blob>;
|
|
14
15
|
export declare const compressFilesFromRelativePath: (path: string, files: string[]) => Promise<Buffer>;
|
|
15
16
|
export declare const verifyAppZip: (zipPath: string) => Promise<void>;
|
package/dist/methods.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.verifyAppZip = exports.compressFilesFromRelativePath = exports.compressDir = exports.toBuffer = exports.typeSafeGet = exports.typeSafePost = void 0;
|
|
3
|
+
exports.verifyAppZip = exports.compressFilesFromRelativePath = exports.compressFolderToBlob = exports.compressDir = exports.toBuffer = exports.typeSafeGet = exports.typeSafePost = void 0;
|
|
4
4
|
const archiver = require("archiver");
|
|
5
5
|
// import { writeFile } from 'node:fs/promises';
|
|
6
6
|
const nodePath = require("node:path");
|
|
@@ -68,6 +68,18 @@ const compressDir = async (sourceDir) => {
|
|
|
68
68
|
return buffer;
|
|
69
69
|
};
|
|
70
70
|
exports.compressDir = compressDir;
|
|
71
|
+
const compressFolderToBlob = async (sourceDir) => {
|
|
72
|
+
const archive = archiver('zip', {
|
|
73
|
+
zlib: { level: 9 },
|
|
74
|
+
});
|
|
75
|
+
archive.on('error', (err) => {
|
|
76
|
+
throw err;
|
|
77
|
+
});
|
|
78
|
+
archive.directory(sourceDir, sourceDir.split('/').pop());
|
|
79
|
+
const buffer = await (0, exports.toBuffer)(archive);
|
|
80
|
+
return new Blob([buffer], { type: 'application/zip' });
|
|
81
|
+
};
|
|
82
|
+
exports.compressFolderToBlob = compressFolderToBlob;
|
|
71
83
|
const compressFilesFromRelativePath = async (path, files) => {
|
|
72
84
|
const archive = archiver('zip', {
|
|
73
85
|
zlib: { level: 9 },
|
package/dist/plan.js
CHANGED
|
@@ -1,32 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.plan = void 0;
|
|
4
|
-
/* eslint-disable complexity */
|
|
5
4
|
const glob_1 = require("glob");
|
|
6
5
|
const fs = require("node:fs");
|
|
7
6
|
const path = require("node:path");
|
|
8
7
|
const planMethods_1 = require("./planMethods");
|
|
9
|
-
const commandsThatRequireFiles = new Set(['addMedia', 'runFlow', 'runScript']);
|
|
10
8
|
async function plan(input, includeTags, excludeTags) {
|
|
11
9
|
if (!fs.existsSync(input)) {
|
|
12
10
|
throw new Error(`Flow path does not exist: ${path.resolve(input)}`);
|
|
13
11
|
}
|
|
14
12
|
if (fs.lstatSync(input).isFile()) {
|
|
15
|
-
const directory = path.dirname(input);
|
|
16
|
-
const { testSteps } = (0, planMethods_1.readTestYamlFileAsJson)(input);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (commandsThatRequireFiles.has(commandName)) {
|
|
24
|
-
const { errors: newErrors, files } = (0, planMethods_1.checkIfFilesExistInWorkspace)(commandName, commandValue, path.normalize(input), directory + '/');
|
|
25
|
-
errors = [...errors, ...newErrors];
|
|
26
|
-
allFiles = [...allFiles, ...files];
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
13
|
+
const directory = path.dirname(input) + '/';
|
|
14
|
+
const { config, testSteps } = (0, planMethods_1.readTestYamlFileAsJson)(input);
|
|
15
|
+
const { allFiles, errors } = (0, planMethods_1.processDependencies)({
|
|
16
|
+
config,
|
|
17
|
+
directory,
|
|
18
|
+
input,
|
|
19
|
+
testSteps,
|
|
20
|
+
});
|
|
30
21
|
if (errors.length > 0) {
|
|
31
22
|
throw new Error('The following flow files are not present in the provided directory: \n' +
|
|
32
23
|
errors.join('\n'));
|
|
@@ -84,20 +75,17 @@ async function plan(input, includeTags, excludeTags) {
|
|
|
84
75
|
});
|
|
85
76
|
let errors = [];
|
|
86
77
|
let allFiles = [];
|
|
87
|
-
for (const [filePath,
|
|
88
|
-
if (!
|
|
78
|
+
for (const [filePath, testSteps] of Object.entries(testStepsPerFlowFile)) {
|
|
79
|
+
if (!testSteps)
|
|
89
80
|
break;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
81
|
+
const { allFiles: deps, errors: errs } = (0, planMethods_1.processDependencies)({
|
|
82
|
+
config: configPerFlowFile[path.relative(cleanPath, filePath)],
|
|
83
|
+
directory: cleanPath,
|
|
84
|
+
input: filePath,
|
|
85
|
+
testSteps,
|
|
86
|
+
});
|
|
87
|
+
allFiles = [...allFiles, ...deps];
|
|
88
|
+
errors = [...errors, ...errs];
|
|
101
89
|
}
|
|
102
90
|
if (errors.length > 0) {
|
|
103
91
|
throw new Error('The following flow files are not present in the provided directory: \n' +
|
|
@@ -132,19 +120,6 @@ async function plan(input, includeTags, excludeTags) {
|
|
|
132
120
|
?.map((flowOrder) => (0, planMethods_1.getFlowsToRunInSequence)(pathsByName, [flowOrder]))
|
|
133
121
|
.flat() || [];
|
|
134
122
|
const normalFlows = allFlows.filter((flow) => !flowsToRunInSequence.includes(flow));
|
|
135
|
-
// for (const filePath of allFlows) {
|
|
136
|
-
// const commands = YamlCommandReader.readCommands(filePath).filter(
|
|
137
|
-
// (command) => command.addMediaCommand,
|
|
138
|
-
// );
|
|
139
|
-
// const mediaPaths = commands.flatMap(
|
|
140
|
-
// (command) => command.addMediaCommand.mediaPaths,
|
|
141
|
-
// );
|
|
142
|
-
// YamlCommandsPathValidator.validatePathsExistInWorkspace(
|
|
143
|
-
// input,
|
|
144
|
-
// filePath,
|
|
145
|
-
// mediaPaths,
|
|
146
|
-
// );
|
|
147
|
-
// }
|
|
148
123
|
return {
|
|
149
124
|
allExcludeTags,
|
|
150
125
|
allIncludeTags,
|
package/dist/planMethods.d.ts
CHANGED
|
@@ -15,3 +15,14 @@ export declare const checkIfFilesExistInWorkspace: (commandName: string, command
|
|
|
15
15
|
errors: string[];
|
|
16
16
|
files: string[];
|
|
17
17
|
};
|
|
18
|
+
interface IProcessDependencies {
|
|
19
|
+
config?: Record<string, unknown> | null;
|
|
20
|
+
directory: string;
|
|
21
|
+
input: string;
|
|
22
|
+
testSteps: Record<string, unknown>[];
|
|
23
|
+
}
|
|
24
|
+
export declare const processDependencies: ({ config, directory, input, testSteps, }: IProcessDependencies) => {
|
|
25
|
+
allFiles: string[];
|
|
26
|
+
errors: string[];
|
|
27
|
+
};
|
|
28
|
+
export {};
|
package/dist/planMethods.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.checkIfFilesExistInWorkspace = exports.walk = exports.readTestYamlFileAsJson = exports.readYamlFileAsJson = exports.isFlowFile = exports.getFlowsToRunInSequence = void 0;
|
|
3
|
+
exports.processDependencies = exports.checkIfFilesExistInWorkspace = exports.walk = exports.readTestYamlFileAsJson = exports.readYamlFileAsJson = exports.isFlowFile = exports.getFlowsToRunInSequence = void 0;
|
|
4
4
|
/* eslint-disable unicorn/filename-case */
|
|
5
5
|
const yaml = require("js-yaml");
|
|
6
6
|
const fs = require("node:fs");
|
|
7
7
|
const path = require("node:path");
|
|
8
|
+
const commandsThatRequireFiles = new Set(['addMedia', 'runFlow', 'runScript']);
|
|
8
9
|
function getFlowsToRunInSequence(paths, flowOrder) {
|
|
9
10
|
if (flowOrder.length === 0)
|
|
10
11
|
return [];
|
|
@@ -77,7 +78,7 @@ const checkIfFilesExistInWorkspace = (commandName, command, filePath, cleanPath)
|
|
|
77
78
|
const errors = [];
|
|
78
79
|
const files = [];
|
|
79
80
|
const directory = path.dirname(filePath);
|
|
80
|
-
const buildError = (error) => `Flow file "${filePath}" has a command "${commandName}" that references a ${error}
|
|
81
|
+
const buildError = (error) => `Flow file "${filePath.replace(cleanPath, './')}" has a command "${commandName}" that references a ${error} ${JSON.stringify(command)}`;
|
|
81
82
|
const processFilePath = (relativePath) => {
|
|
82
83
|
const absoluteFilePath = path.resolve(directory, relativePath);
|
|
83
84
|
const error = checkFile(absoluteFilePath, cleanPath);
|
|
@@ -107,3 +108,28 @@ const checkFile = (filePath, cleanPath) => {
|
|
|
107
108
|
if (!filePath.startsWith(cleanPath))
|
|
108
109
|
return `file outside the workspace`;
|
|
109
110
|
};
|
|
111
|
+
const processDependencies = ({ config, directory, input, testSteps, }) => {
|
|
112
|
+
let errors = [];
|
|
113
|
+
let allFiles = [];
|
|
114
|
+
const { onFlowComplete, onFlowStart } = config ?? {};
|
|
115
|
+
const stepsArray = [testSteps];
|
|
116
|
+
if (onFlowStart)
|
|
117
|
+
stepsArray.push(onFlowStart);
|
|
118
|
+
if (onFlowComplete)
|
|
119
|
+
stepsArray.push(onFlowComplete);
|
|
120
|
+
for (const steps of stepsArray) {
|
|
121
|
+
for (const command of steps) {
|
|
122
|
+
if (typeof command === 'string')
|
|
123
|
+
continue;
|
|
124
|
+
for (const [commandName, commandValue] of Object.entries(command)) {
|
|
125
|
+
if (commandsThatRequireFiles.has(commandName)) {
|
|
126
|
+
const { errors: newErrors, files } = (0, exports.checkIfFilesExistInWorkspace)(commandName, commandValue, path.normalize(input), directory);
|
|
127
|
+
errors = [...errors, ...newErrors];
|
|
128
|
+
allFiles = [...allFiles, ...files];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return { allFiles, errors };
|
|
134
|
+
};
|
|
135
|
+
exports.processDependencies = processDependencies;
|
package/oclif.manifest.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"aliases": [],
|
|
5
5
|
"args": {
|
|
6
6
|
"firstFile": {
|
|
7
|
-
"description": "The binary file of the app to run your flow against, e.g.
|
|
7
|
+
"description": "The binary file of the app to run your flow against, e.g. test.apk for android or test.app/.zip for ios",
|
|
8
8
|
"hidden": true,
|
|
9
9
|
"name": "firstFile"
|
|
10
10
|
},
|
|
@@ -220,5 +220,5 @@
|
|
|
220
220
|
]
|
|
221
221
|
}
|
|
222
222
|
},
|
|
223
|
-
"version": "0.0.
|
|
223
|
+
"version": "0.0.5"
|
|
224
224
|
}
|