@kumologica/sdk 3.0.10 → 3.0.13
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/cli/commands/build-commands/kumohub.js +46 -4
- package/cli/commands/test-utils/TestSuiteController.js +18 -2
- package/cli/commands/test.js +42 -6
- package/package.json +31 -29
- package/src/app/lib/stores/settings-cloud-store.js +28 -25
- package/src/app/lib/stores/settings-network-store.js +0 -1
- package/src/app/lib/stores/test-config-store.js +152 -19
- package/src/app/lib/stores/util/iniParser.js +46 -0
- package/src/app/lib/stores/util/iniParser.spec.js +72 -0
- package/src/app/lib/utils/updater.js +0 -0
- package/src/app/main-process/{runtime-manager.js → editor-manager.js} +44 -8
- package/src/app/main-process/main-window.js +6 -2
- package/src/app/main-process/modal-home.js +6 -2
- package/src/app/main-process/modal-newproject.js +6 -2
- package/src/app/main-process/modal-nodelibrary.js +6 -2
- package/src/app/main-process/modal-welcome.js +8 -3
- package/src/app/main.js +18 -14
- package/src/app/preload.js +33 -13
- package/src/app/ui/editor-client/public/red/red.js +398 -226
- package/src/app/ui/editor-client/public/red/red.min.js +1 -1
- package/src/app/ui/editor-client/public/red/style.min.css +1 -1
- package/src/app/ui/editor-client/public/vendor/ace/worker-jsonata.js +1 -1
- package/src/app/ui/editor-client/public/vendor/jsonata/jsonata.min.js +1 -1
- package/src/app/ui/editor-client/public/vendor/kumologica/http-test-case.js +113 -0
- package/src/app/ui/editor-client/public/vendor/xterm/lib/xterm.js +1 -1
- package/src/app/ui/editor-client/src/js/ui/editor.js +2 -1
- package/src/app/ui/editor-client/src/js/ui/editors/js.js +3 -2
- package/src/app/ui/editor-client/src/js/ui/header.js +1 -1
- package/src/app/ui/editor-client/src/js/ui/logviewer.js +1 -1
- package/src/app/ui/editor-client/src/js/ui/project-info.js +3 -1
- package/src/app/ui/editor-client/src/js/ui/tab-azure.js +3 -3
- package/src/app/ui/editor-client/src/js/ui/tab-info.js +1 -1
- package/src/app/ui/editor-client/src/js/ui/tab-kumohub.js +26 -7
- package/src/app/ui/editor-client/src/js/ui/tab-test.js +134 -62
- package/src/app/ui/editor-client/src/js/ui/ui-settings.js +220 -143
- package/src/app/ui/editor-client/src/js/ui/view.js +5 -5
- package/src/app/ui/editor-client/src/sass/editor.scss +1 -0
- package/src/app/ui/editor-client/src/sass/palette.scss +15 -0
- package/src/app/ui/editor-client/src/sass/tab-test.scss +9 -4
- package/src/app/ui/editor-client/src/sass/ui-settings.scss +7 -1
- package/src/app/ui/editor-client/src/vendor/kumologica/http-test-case.js +113 -0
|
@@ -1,7 +1,49 @@
|
|
|
1
|
-
exports.command = 'kumohub
|
|
2
|
-
exports.desc =
|
|
3
|
-
|
|
1
|
+
exports.command = 'kumohub';
|
|
2
|
+
exports.desc = `Builds kumohub binaries:
|
|
3
|
+
* generates kumohub artefacts
|
|
4
|
+
* runs npm install
|
|
5
|
+
* creates zip file
|
|
6
|
+
|
|
7
|
+
Documentation:
|
|
8
|
+
https://docs.kumologica.com/docs/references/cli/BuildKumohub.html`;
|
|
9
|
+
|
|
10
|
+
exports.builder = {
|
|
11
|
+
"flow-file-name": {
|
|
12
|
+
describe: "The name of kumologica flow file.\n Auto search if not provided.\n ",
|
|
13
|
+
type: 'string',
|
|
14
|
+
alias: 'f',
|
|
15
|
+
nargs: 1
|
|
16
|
+
},
|
|
17
|
+
"project-directory": {
|
|
18
|
+
describe: "The root directory of project.\n Current working directory if not provided.\n",
|
|
19
|
+
type: 'string',
|
|
20
|
+
alias: 'd',
|
|
21
|
+
nargs: 1
|
|
22
|
+
},
|
|
23
|
+
"zip-file-name": {
|
|
24
|
+
describe: "The name of zip file to be created",
|
|
25
|
+
type: 'string',
|
|
26
|
+
default: 'lambda.zip',
|
|
27
|
+
alias: 'z',
|
|
28
|
+
nargs: 1
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function display(argv) {
|
|
33
|
+
console.log(`\nBuilding kumohub artefacts with following parameters: \n`);
|
|
34
|
+
console.log('project-directory: %s', argv["project-directory"]||'');
|
|
35
|
+
console.log('flow-file-name: %s', argv["flow-file-name"]||'');
|
|
36
|
+
console.log('zip-file-name: %s', argv["zip-file-name"]||'');
|
|
37
|
+
}
|
|
4
38
|
|
|
5
39
|
exports.handler = function (argv) {
|
|
6
|
-
|
|
40
|
+
display(argv);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const { build } = require('@kumologica/builder');
|
|
44
|
+
build('kumohub', argv);
|
|
45
|
+
} catch (e) {
|
|
46
|
+
console.log(`${e.message}`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
7
49
|
}
|
|
@@ -5,6 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const chalk = require('chalk');
|
|
6
6
|
const { error } = require('./util/output');
|
|
7
7
|
const got = require('got');
|
|
8
|
+
const { logError } = require('../utils');
|
|
8
9
|
const log = console.log;
|
|
9
10
|
|
|
10
11
|
|
|
@@ -128,6 +129,7 @@ class TestReporter {
|
|
|
128
129
|
this._testCases.push(testCase);
|
|
129
130
|
}
|
|
130
131
|
|
|
132
|
+
|
|
131
133
|
findTestCase(testCaseId){
|
|
132
134
|
let tcfound = this._testCases.filter(tc => tc._testCaseId === testCaseId);
|
|
133
135
|
if (tcfound.length === 0) {
|
|
@@ -139,7 +141,7 @@ class TestReporter {
|
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
printTestCaseHeader(description, target) {
|
|
142
|
-
let prettyName = `${description} > ${target}
|
|
144
|
+
let prettyName = `${description}`; // mvp: only full flow being targeted > ${target}
|
|
143
145
|
const sep = '=';
|
|
144
146
|
let underline = sep.repeat(prettyName.length);
|
|
145
147
|
let headerLine = `- ${prettyName}\n ${underline}`;
|
|
@@ -307,12 +309,26 @@ class TestSuiteController {
|
|
|
307
309
|
return flowFileJson.filter((node) => node.type === 'TestCase' || node.type === 'HTTPTestCase');
|
|
308
310
|
}
|
|
309
311
|
|
|
310
|
-
async runTestSuite() {
|
|
312
|
+
async runTestSuite(testcase) {
|
|
311
313
|
const flowFileAbsPath = path.join(
|
|
312
314
|
this._appServer.settings.userDir,
|
|
313
315
|
this._appServer.settings.flowFile
|
|
314
316
|
);
|
|
315
317
|
let testCases = this.findTestCasesFromFlow(flowFileAbsPath);
|
|
318
|
+
if (!testCases || (testCases && testCases.length === 0)) {
|
|
319
|
+
logError(`No testcases found on flow file: ${flowFileAbsPath}`);
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// If defined, filter the testcase that you want to test
|
|
324
|
+
if (testcase) {
|
|
325
|
+
testCases = testCases.filter(tc => tc.name.toLowerCase() === testcase.toLowerCase());
|
|
326
|
+
if (testCases && testCases.length === 0){
|
|
327
|
+
logError(`TestCase: "${testcase}" cannot be found`);
|
|
328
|
+
process.exit(1);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
}
|
|
316
332
|
|
|
317
333
|
// === Starting the testSuite ===
|
|
318
334
|
this._appServer.events.emit('runtime-event', {
|
package/cli/commands/test.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const { Select } = require('enquirer');
|
|
2
3
|
const fs = require('fs');
|
|
3
4
|
const { logError } = require('./utils');
|
|
4
5
|
const path = require('path');
|
|
@@ -10,7 +11,7 @@ const { codegen } = require('@kumologica/builder');
|
|
|
10
11
|
const log = console.log;
|
|
11
12
|
const APP_SERVER_PORT = 1990;
|
|
12
13
|
|
|
13
|
-
async function runTest(flowFilePath) {
|
|
14
|
+
async function runTest(flowFilePath, testcase, iterative) {
|
|
14
15
|
log(`\n> Starting runtime on port ${APP_SERVER_PORT}...`);
|
|
15
16
|
|
|
16
17
|
let appServer = new AppServer({
|
|
@@ -27,8 +28,34 @@ async function runTest(flowFilePath) {
|
|
|
27
28
|
await appServer.start();
|
|
28
29
|
log(`> FlowFile to be tested: ${chalk.bold(path.resolve(flowFilePath))} \n`);
|
|
29
30
|
let testSuiteController = new TestSuiteController(appServer);
|
|
30
|
-
|
|
31
|
+
let testcasesAvailable = testSuiteController.findTestCasesFromFlow(flowFilePath).map(tc => {
|
|
32
|
+
return tc.name;
|
|
33
|
+
})
|
|
34
|
+
testcasesAvailable.push('Run all TestCases...');
|
|
35
|
+
// Iterative ?
|
|
36
|
+
// Check if iterative testing has been selected
|
|
37
|
+
if (iterative) {
|
|
38
|
+
const prompt = new Select({
|
|
39
|
+
name: 'testcase',
|
|
40
|
+
message: 'What testcase do you want to run?',
|
|
41
|
+
choices: testcasesAvailable
|
|
42
|
+
});
|
|
43
|
+
await prompt.run()
|
|
44
|
+
.then(tc => {
|
|
45
|
+
if (tc === 'Run all TestCases...'){
|
|
46
|
+
testcase = null;
|
|
47
|
+
}else {
|
|
48
|
+
testcase = tc;
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
.catch(err => {
|
|
52
|
+
logError(`Error found while running tests on iterative mode due to: `, err.message);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
31
57
|
|
|
58
|
+
const errors = await testSuiteController.runTestSuite(testcase); // no need to wait for response
|
|
32
59
|
process.exit(errors > 0);
|
|
33
60
|
} catch (err) {
|
|
34
61
|
log(
|
|
@@ -53,15 +80,24 @@ function isDirectory(dir) {
|
|
|
53
80
|
|
|
54
81
|
exports.command = 'test [project_directory]';
|
|
55
82
|
exports.desc = `Run test suite`;
|
|
56
|
-
|
|
57
83
|
exports.builder = (yargs) => {
|
|
58
84
|
yargs.positional(`project_directory`, {
|
|
59
85
|
type: 'string',
|
|
60
86
|
describe: 'Path to a valid kumologica project directory or flow file. (Optional)'
|
|
61
87
|
})
|
|
88
|
+
yargs.option(`testcase`, {
|
|
89
|
+
describe: "Testcase name to run",
|
|
90
|
+
type: 'string',
|
|
91
|
+
alias: 't',
|
|
92
|
+
nargs: 1
|
|
93
|
+
});
|
|
94
|
+
yargs.option(`iterative`, {
|
|
95
|
+
describe: "Manually select the testcase to run from all available testcases",
|
|
96
|
+
type: 'boolean',
|
|
97
|
+
alias: 'i'
|
|
98
|
+
});
|
|
62
99
|
}
|
|
63
|
-
|
|
64
|
-
exports.handler = ({ project_directory }) => {
|
|
100
|
+
exports.handler = ({ project_directory, testcase, iterative }) => {
|
|
65
101
|
let projectDirOrFile = project_directory || process.cwd();
|
|
66
102
|
let projectFlowPath = projectDirOrFile;
|
|
67
103
|
|
|
@@ -82,7 +118,7 @@ exports.handler = ({ project_directory }) => {
|
|
|
82
118
|
}
|
|
83
119
|
|
|
84
120
|
try {
|
|
85
|
-
runTest(projectFlowPath);
|
|
121
|
+
runTest(projectFlowPath, testcase, iterative);
|
|
86
122
|
} catch (e) {
|
|
87
123
|
logError(e.message);
|
|
88
124
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"productName": "Kumologica Designer",
|
|
4
4
|
"copyright": "Copyright 2020 Kumologica Pty Ltd, All Rights Reserved.",
|
|
5
5
|
"author": "Kumologica Pty Ltd <contact@kumologica.com>",
|
|
6
|
-
"version": "3.0.
|
|
6
|
+
"version": "3.0.13",
|
|
7
7
|
"description": "Kumologica Designer, harnessing Serverless for your cloud integration needs",
|
|
8
8
|
"main": "src/app/main.js",
|
|
9
9
|
"files": [
|
|
@@ -64,60 +64,62 @@
|
|
|
64
64
|
},
|
|
65
65
|
"license": "Proprietary",
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@
|
|
68
|
-
"@kumologica/
|
|
69
|
-
"@kumologica/devkit": "3.0.
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
67
|
+
"@electron/remote": "^2.0.8",
|
|
68
|
+
"@kumologica/builder": "3.0.13",
|
|
69
|
+
"@kumologica/devkit": "3.0.13",
|
|
70
|
+
"@kumologica/runtime": "3.0.13",
|
|
71
|
+
"adm-zip": "0.4.13",
|
|
72
|
+
"ajv": "8.10.0",
|
|
73
|
+
"aws-sdk": "2.513.0",
|
|
73
74
|
"basic-auth": "2.0.1",
|
|
74
75
|
"bcryptjs": "2.4.3",
|
|
75
|
-
"body-parser": "
|
|
76
|
-
"chalk": "
|
|
77
|
-
"child_process": "
|
|
76
|
+
"body-parser": "1.19.0",
|
|
77
|
+
"chalk": "2.4.2",
|
|
78
|
+
"child_process": "1.0.2",
|
|
78
79
|
"clone": "2.1.2",
|
|
79
80
|
"cookie-parser": "1.4.4",
|
|
80
81
|
"cors": "^2.8.5",
|
|
81
82
|
"dagre": "^0.8.5",
|
|
82
83
|
"debounce": "^1.2.0",
|
|
83
|
-
"electron": "
|
|
84
|
+
"electron": "19.0.0",
|
|
84
85
|
"electron-updater": "4.3.9",
|
|
85
86
|
"enquirer": "^2.3.1",
|
|
86
87
|
"express": "4.17.3",
|
|
87
88
|
"express-session": "1.16.2",
|
|
88
|
-
"extract-json-from-string": "
|
|
89
|
+
"extract-json-from-string": "1.0.1",
|
|
89
90
|
"fs-extra": "8.1.0",
|
|
90
|
-
"glob": "
|
|
91
|
+
"glob": "7.1.6",
|
|
91
92
|
"got": "11.8.2",
|
|
92
93
|
"hash-sum": "2.0.0",
|
|
93
|
-
"http-shutdown": "
|
|
94
|
+
"http-shutdown": "1.2.1",
|
|
94
95
|
"iconv-lite": "0.5.0",
|
|
95
96
|
"ini": "^2.0.0",
|
|
96
|
-
"js-yaml": "
|
|
97
|
-
"jsonata": "
|
|
98
|
-
"jsonpath": "
|
|
97
|
+
"js-yaml": "3.13.1",
|
|
98
|
+
"jsonata": "1.7.0",
|
|
99
|
+
"jsonpath": "1.0.2",
|
|
99
100
|
"memorystore": "1.6.1",
|
|
100
101
|
"mime": "2.4.4",
|
|
101
102
|
"minimist": "^1.2.3",
|
|
102
103
|
"multer": "1.4.1",
|
|
103
104
|
"mustache": "3.0.1",
|
|
104
105
|
"oauth2orize": "1.11.0",
|
|
105
|
-
"os": "
|
|
106
|
+
"os": "0.1.1",
|
|
106
107
|
"passport": "0.4.0",
|
|
107
108
|
"passport-http-bearer": "1.0.1",
|
|
108
109
|
"passport-oauth2-client-password": "0.1.2",
|
|
109
|
-
"request": "
|
|
110
|
-
"rimraf": "
|
|
111
|
-
"shell-path": "
|
|
112
|
-
"simplemde": "
|
|
113
|
-
"smoketail": "
|
|
114
|
-
"socket.io": "
|
|
115
|
-
"
|
|
110
|
+
"request": "2.88.0",
|
|
111
|
+
"rimraf": "3.0.0",
|
|
112
|
+
"shell-path": "2.1.0",
|
|
113
|
+
"simplemde": "1.11.2",
|
|
114
|
+
"smoketail": "0.2.2",
|
|
115
|
+
"socket.io": "2.3.0",
|
|
116
|
+
"tcp-port-used": "1.0.2",
|
|
117
|
+
"util": "0.12.1",
|
|
116
118
|
"when": "3.7.8",
|
|
117
|
-
"ws": "
|
|
118
|
-
"xterm": "
|
|
119
|
-
"xterm-addon-fit": "
|
|
120
|
-
"yargs": "
|
|
119
|
+
"ws": "7.1.1",
|
|
120
|
+
"xterm": "4.1.0",
|
|
121
|
+
"xterm-addon-fit": "0.2.1",
|
|
122
|
+
"yargs": "17.3.1"
|
|
121
123
|
},
|
|
122
124
|
"devDependencies": {
|
|
123
125
|
"@types/node": "^12.6.8",
|
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
// properties: ~/.kumologica/credentials
|
|
2
2
|
|
|
3
|
-
const defaultContent =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
3
|
+
const defaultContent = `; This file contains all your sensitive credential information
|
|
4
|
+
; about your cloud connections used by Kumologica Designer.
|
|
5
|
+
; For more information visit https://docs.kumologica.com/settings
|
|
6
|
+
;
|
|
7
|
+
; Examples:
|
|
8
|
+
|
|
9
|
+
; =============== Kumohub Details =======================
|
|
10
|
+
; Follow the format for this section as: "kumohub.<alias>"
|
|
11
|
+
; =======================================================
|
|
12
|
+
; [kumohub.default]
|
|
13
|
+
; username = your-username
|
|
14
|
+
; password = your-password
|
|
15
|
+
; subscription = kumohub-subscription-id
|
|
16
|
+
|
|
17
|
+
; ============= AWS Cloud Details =======================
|
|
18
|
+
; Follow the format for this section as: "aws.<alias>"
|
|
19
|
+
; =======================================================
|
|
20
|
+
; [aws.development]
|
|
21
|
+
; profile = your-defined-aws-profile
|
|
22
|
+
|
|
23
|
+
; ============= Azure Cloud Details =====================
|
|
24
|
+
; Follow the format for this section as: "azure.<alias>"
|
|
25
|
+
; =======================================================
|
|
26
|
+
; [azure.default]
|
|
27
|
+
; subscription_id = 00000000-0000-0000-0000-000000000000
|
|
28
|
+
; client_id = 00000000-0000-0000-0000-000000000000
|
|
29
|
+
; client_secret = 0000000000000000000000000000000
|
|
30
|
+
; tenant_id = 00000000-0000-0000-0000-000000000000
|
|
28
31
|
`
|
|
29
32
|
|
|
30
33
|
const os = require('os');
|
|
@@ -1,26 +1,159 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const {
|
|
2
|
+
getVariablesByConfigAndSection,
|
|
3
|
+
getSectionsByText
|
|
4
|
+
} = require('./util/iniParser');
|
|
5
|
+
|
|
6
|
+
const NO_ENVIRONMENT = "__no_environment__";
|
|
7
|
+
|
|
8
|
+
const KEYS = {
|
|
9
|
+
ROOT_KEY: "test",
|
|
10
|
+
ENVIRONMENTS: "environments",
|
|
11
|
+
TESTCASE_OLD: "test",
|
|
12
|
+
PROPERTIES_OLD: "properties",
|
|
13
|
+
TESTCASE: "testcase",
|
|
14
|
+
ENVIRONMENT: "environment"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const DEFAULT_ENVIRONMENTS = [
|
|
18
|
+
"; ===========================================================",
|
|
19
|
+
"; Environment variables must be defined under one section",
|
|
20
|
+
"; You can define as many sections as you need.",
|
|
21
|
+
"; (Remove the semicolons to uncomment the lines)",
|
|
22
|
+
"; ===========================================================",
|
|
23
|
+
"",
|
|
24
|
+
"; Example:",
|
|
25
|
+
"",
|
|
26
|
+
"; [development] ",
|
|
27
|
+
"; KUMOLOGICA_LOGLEVEL=DEBUG",
|
|
28
|
+
"; VAR_1=VALUE_1",
|
|
29
|
+
"",
|
|
30
|
+
"; [test]",
|
|
31
|
+
"; KUMOLOGICA_LOGLEVEL=ERROR",
|
|
32
|
+
"; VAR_1=VALUE_1",
|
|
33
|
+
]
|
|
5
34
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
35
|
+
const Store = require('./store');
|
|
36
|
+
|
|
37
|
+
class TestConfigStore extends Store {
|
|
38
|
+
|
|
39
|
+
constructor(defaults) {
|
|
40
|
+
super({ ...defaults, configName: '.kumologica/test-config', defaults: {}});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getConfigFileFullPath() {
|
|
44
|
+
return this.path;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getTestConfig() {
|
|
48
|
+
let config = super.get(KEYS.ROOT_KEY);
|
|
49
|
+
|
|
50
|
+
// Decorate with default environments if not persisted
|
|
51
|
+
config = this.convertToLatestVersion(config);
|
|
52
|
+
|
|
53
|
+
// check whether is first time, i.e. config is empty
|
|
54
|
+
if (!config) {
|
|
55
|
+
config = {};
|
|
56
|
+
config[KEYS.TESTCASE] = "__runAll";
|
|
57
|
+
config[KEYS.ENVIRONMENT] = NO_ENVIRONMENT;
|
|
58
|
+
config[KEYS.ENVIRONMENTS] = DEFAULT_ENVIRONMENTS;
|
|
59
|
+
super.set(KEYS.ROOT_KEY, config);
|
|
12
60
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
61
|
+
|
|
62
|
+
return config;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
convertToLatestVersion(config) {
|
|
66
|
+
let newConfig = config;
|
|
67
|
+
if (newConfig){
|
|
68
|
+
if (newConfig.hasOwnProperty(KEYS.TESTCASE_OLD)){
|
|
69
|
+
// replace: "config.test" -> "config.testcase"
|
|
70
|
+
newConfig[KEYS.TESTCASE] = newConfig[KEYS.TESTCASE_OLD];
|
|
71
|
+
delete newConfig[KEYS.TESTCASE_OLD];
|
|
72
|
+
// select "config.environment" = no_environment
|
|
73
|
+
newConfig[KEYS.ENVIRONMENT] = NO_ENVIRONMENT;
|
|
74
|
+
// append the old properties to the new environment
|
|
75
|
+
newConfig[KEYS.ENVIRONMENTS] = DEFAULT_ENVIRONMENTS;
|
|
76
|
+
if (newConfig.hasOwnProperty(KEYS.PROPERTIES_OLD)){
|
|
77
|
+
let props = newConfig[KEYS.PROPERTIES_OLD];
|
|
78
|
+
newConfig[KEYS.ENVIRONMENTS].push('[old-properties]');
|
|
79
|
+
for (const [key, value] of Object.entries(props)) {
|
|
80
|
+
newConfig[KEYS.ENVIRONMENTS].push(`${key}=${value}`);
|
|
81
|
+
}
|
|
82
|
+
delete newConfig[KEYS.PROPERTIES_OLD];
|
|
83
|
+
// persist the new model
|
|
84
|
+
super.set(KEYS.ROOT_KEY, newConfig);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
16
87
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
88
|
+
return newConfig;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
saveTestValuesIntoConfig(value) {
|
|
92
|
+
let config = this.getTestConfig();
|
|
93
|
+
config[KEYS.ENVIRONMENT] = this.listEnvironments().includes(value[KEYS.ENVIRONMENT])?value[KEYS.ENVIRONMENT]: NO_ENVIRONMENT;
|
|
94
|
+
config[KEYS.TESTCASE] = value[KEYS.TESTCASE];
|
|
95
|
+
super.set(KEYS.ROOT_KEY, config);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
saveEnvironmentSectionIntoConfig(text) {
|
|
99
|
+
let config = this.getTestConfig();
|
|
100
|
+
config[KEYS.ENVIRONMENTS] = this.convertTextIntoArray(text);
|
|
101
|
+
super.set(KEYS.ROOT_KEY, config);
|
|
102
|
+
// If selected environment is not longer available, lets default it to no_environment
|
|
103
|
+
if (!this.listEnvironments().includes(config[KEYS.ENVIRONMENT])) {
|
|
104
|
+
config[KEYS.ENVIRONMENTS] = this.convertTextIntoArray(text);
|
|
105
|
+
config[KEYS.ENVIRONMENT] = NO_ENVIRONMENT;
|
|
106
|
+
super.set(KEYS.ROOT_KEY, config);
|
|
20
107
|
}
|
|
21
108
|
}
|
|
22
109
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
110
|
+
getEnvironmentSectionFromConfig() {
|
|
111
|
+
return this.convertArrayIntoText(this.getTestConfig()[KEYS.ENVIRONMENTS]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getLatestSelectedEnvironment() {
|
|
115
|
+
let config = this.getTestConfig();
|
|
116
|
+
return (config.hasOwnProperty(KEYS.ENVIRONMENT))? config[KEYS.ENVIRONMENT]: NO_ENVIRONMENT;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getLatestSelectedTestCase() {
|
|
120
|
+
let config = this.getTestConfig();
|
|
121
|
+
if (config){
|
|
122
|
+
if (config.hasOwnProperty(KEYS.TESTCASE)) {
|
|
123
|
+
return config[KEYS.TESTCASE];
|
|
124
|
+
} else if (config.hasOwnProperty(KEYS.TESTCASE_OLD)) {
|
|
125
|
+
return config[KEYS.TESTCASE_OLD];
|
|
126
|
+
} else {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
listEnvironments() {
|
|
134
|
+
let enviromentAsText = this.convertArrayIntoText(this.getTestConfig()[KEYS.ENVIRONMENTS])
|
|
135
|
+
return getSectionsByText(enviromentAsText);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
listVariablesByEnvironment(section) {
|
|
139
|
+
let environmentSelected = section;
|
|
140
|
+
if (!environmentSelected) {
|
|
141
|
+
environmentSelected = this.getLatestSelectedEnvironment();
|
|
142
|
+
}
|
|
143
|
+
let aEnvironments = this.getTestConfig()[KEYS.ENVIRONMENTS];
|
|
144
|
+
return getVariablesByConfigAndSection(this.convertArrayIntoText(aEnvironments), environmentSelected);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
convertTextIntoArray(text){
|
|
148
|
+
let lines = text.split(/\r\n|\n/);
|
|
149
|
+
return lines.map(l => l.trim());
|
|
150
|
+
}
|
|
151
|
+
convertArrayIntoText(lines) {
|
|
152
|
+
return lines.join('\r\n');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = {
|
|
157
|
+
TestConfigStore
|
|
158
|
+
};
|
|
26
159
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const ini = require('ini');
|
|
2
|
+
|
|
3
|
+
function parseStringToConfig(text) {
|
|
4
|
+
let config = ini.parse(text);
|
|
5
|
+
return config;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getSectionsByText(text) {
|
|
9
|
+
let config = parseStringToConfig(text);
|
|
10
|
+
let keys = [];
|
|
11
|
+
if (config) {
|
|
12
|
+
keys = Object.keys(config);
|
|
13
|
+
keys= keys.filter(section => isValidSection(section, config))
|
|
14
|
+
}
|
|
15
|
+
return keys;
|
|
16
|
+
}
|
|
17
|
+
function getVariablesByConfigAndSection(environmentsAsText, section){
|
|
18
|
+
let oEnvironments = parseStringToConfig(environmentsAsText);
|
|
19
|
+
let variables = [];
|
|
20
|
+
|
|
21
|
+
if (oEnvironments){
|
|
22
|
+
if (oEnvironments[section]){
|
|
23
|
+
for (const [key, value] of Object.entries(oEnvironments[section])) {
|
|
24
|
+
variables.push({ key, value })
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
return variables;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isValidSection(section, config) {
|
|
34
|
+
return (
|
|
35
|
+
section !== '__no_environment__' &&
|
|
36
|
+
!section.trim().startsWith('//') &&
|
|
37
|
+
!section.trim().startsWith('#') &&
|
|
38
|
+
typeof config[section] == 'object' && Object.entries(config[section]).length > 0
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
parseStringToConfig,
|
|
44
|
+
getSectionsByText,
|
|
45
|
+
getVariablesByConfigAndSection
|
|
46
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
const chai = require('chai');
|
|
3
|
+
const {
|
|
4
|
+
parseStringToConfig,
|
|
5
|
+
getSectionsByText,
|
|
6
|
+
getVariablesByConfigAndSection } = require('./iniParser');
|
|
7
|
+
|
|
8
|
+
let assert = chai.assert;
|
|
9
|
+
|
|
10
|
+
const ENVIRONMENTS_WITH_COMMENTS = `
|
|
11
|
+
// comment
|
|
12
|
+
; hola amigos
|
|
13
|
+
; this is comments
|
|
14
|
+
[dev]
|
|
15
|
+
url=http://dev.good.url.com
|
|
16
|
+
private=false
|
|
17
|
+
[test]
|
|
18
|
+
url=http://test.good.url.com
|
|
19
|
+
private=true
|
|
20
|
+
`;
|
|
21
|
+
const ENVIRONMENTS_WITHOUT_SECTIONS = ``;
|
|
22
|
+
|
|
23
|
+
const ENVIRONMENTS_WRONG_FORMAT = `
|
|
24
|
+
// comment
|
|
25
|
+
; hola amigos
|
|
26
|
+
; this is comments
|
|
27
|
+
[dev]
|
|
28
|
+
url
|
|
29
|
+
private = false
|
|
30
|
+
USER == test123
|
|
31
|
+
password=asdfa salutation=hello
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
const ENVIRONMENTS_MISSING_SECTION = `
|
|
35
|
+
// comment
|
|
36
|
+
; hola amigos
|
|
37
|
+
; this is comments
|
|
38
|
+
;;[dev]
|
|
39
|
+
url = true
|
|
40
|
+
|
|
41
|
+
[test]
|
|
42
|
+
url = hola
|
|
43
|
+
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
describe('parse correctly a environment section', () => {
|
|
47
|
+
it('happy path', () => {
|
|
48
|
+
let config = parseStringToConfig(ENVIRONMENTS_WITH_COMMENTS)
|
|
49
|
+
let sections = getSectionsByText(ENVIRONMENTS_WITH_COMMENTS);
|
|
50
|
+
assert.equal(sections.length, 2);
|
|
51
|
+
|
|
52
|
+
let vars = getVariablesByConfigAndSection(config, sections[0]);
|
|
53
|
+
assert.equal(vars.length, 2);
|
|
54
|
+
});
|
|
55
|
+
it('No sections available', () => {
|
|
56
|
+
let sections = getSectionsByText(ENVIRONMENTS_WITHOUT_SECTIONS);
|
|
57
|
+
assert.equal(sections.length, 0);
|
|
58
|
+
});
|
|
59
|
+
it('Variables not correct', () => {
|
|
60
|
+
let config = parseStringToConfig(ENVIRONMENTS_WRONG_FORMAT)
|
|
61
|
+
let sections = getSectionsByText(ENVIRONMENTS_WRONG_FORMAT);
|
|
62
|
+
let vars = getVariablesByConfigAndSection(config, sections[0]);
|
|
63
|
+
assert.equal(vars.length, 4);
|
|
64
|
+
})
|
|
65
|
+
it('Detecting missing sections', () => {
|
|
66
|
+
let sections = getSectionsByText(ENVIRONMENTS_MISSING_SECTION);
|
|
67
|
+
console.log(sections);
|
|
68
|
+
//let vars = getVariablesByConfigAndSection(config, sections[0]);
|
|
69
|
+
//assert.equal(vars.length, 4);
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
});
|
|
File without changes
|