@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.
Files changed (41) hide show
  1. package/cli/commands/build-commands/kumohub.js +46 -4
  2. package/cli/commands/test-utils/TestSuiteController.js +18 -2
  3. package/cli/commands/test.js +42 -6
  4. package/package.json +31 -29
  5. package/src/app/lib/stores/settings-cloud-store.js +28 -25
  6. package/src/app/lib/stores/settings-network-store.js +0 -1
  7. package/src/app/lib/stores/test-config-store.js +152 -19
  8. package/src/app/lib/stores/util/iniParser.js +46 -0
  9. package/src/app/lib/stores/util/iniParser.spec.js +72 -0
  10. package/src/app/lib/utils/updater.js +0 -0
  11. package/src/app/main-process/{runtime-manager.js → editor-manager.js} +44 -8
  12. package/src/app/main-process/main-window.js +6 -2
  13. package/src/app/main-process/modal-home.js +6 -2
  14. package/src/app/main-process/modal-newproject.js +6 -2
  15. package/src/app/main-process/modal-nodelibrary.js +6 -2
  16. package/src/app/main-process/modal-welcome.js +8 -3
  17. package/src/app/main.js +18 -14
  18. package/src/app/preload.js +33 -13
  19. package/src/app/ui/editor-client/public/red/red.js +398 -226
  20. package/src/app/ui/editor-client/public/red/red.min.js +1 -1
  21. package/src/app/ui/editor-client/public/red/style.min.css +1 -1
  22. package/src/app/ui/editor-client/public/vendor/ace/worker-jsonata.js +1 -1
  23. package/src/app/ui/editor-client/public/vendor/jsonata/jsonata.min.js +1 -1
  24. package/src/app/ui/editor-client/public/vendor/kumologica/http-test-case.js +113 -0
  25. package/src/app/ui/editor-client/public/vendor/xterm/lib/xterm.js +1 -1
  26. package/src/app/ui/editor-client/src/js/ui/editor.js +2 -1
  27. package/src/app/ui/editor-client/src/js/ui/editors/js.js +3 -2
  28. package/src/app/ui/editor-client/src/js/ui/header.js +1 -1
  29. package/src/app/ui/editor-client/src/js/ui/logviewer.js +1 -1
  30. package/src/app/ui/editor-client/src/js/ui/project-info.js +3 -1
  31. package/src/app/ui/editor-client/src/js/ui/tab-azure.js +3 -3
  32. package/src/app/ui/editor-client/src/js/ui/tab-info.js +1 -1
  33. package/src/app/ui/editor-client/src/js/ui/tab-kumohub.js +26 -7
  34. package/src/app/ui/editor-client/src/js/ui/tab-test.js +134 -62
  35. package/src/app/ui/editor-client/src/js/ui/ui-settings.js +220 -143
  36. package/src/app/ui/editor-client/src/js/ui/view.js +5 -5
  37. package/src/app/ui/editor-client/src/sass/editor.scss +1 -0
  38. package/src/app/ui/editor-client/src/sass/palette.scss +15 -0
  39. package/src/app/ui/editor-client/src/sass/tab-test.scss +9 -4
  40. package/src/app/ui/editor-client/src/sass/ui-settings.scss +7 -1
  41. 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 = 'Build kumohub artefacrs remote named <name> for repo at url <url>'
3
- exports.builder = {}
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
- console.log('adding remote %s at url %s', argv.name, argv.url)
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', {
@@ -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
- const errors = await testSuiteController.runTestSuite(); // no need to wait for response
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.10",
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
- "@kumologica/builder": "3.0.10",
68
- "@kumologica/runtime": "3.0.10",
69
- "@kumologica/devkit": "3.0.10",
70
- "adm-zip": "^0.4.13",
71
- "ajv": "^8.10.0",
72
- "aws-sdk": "^2.513.0",
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": "^1.19.0",
76
- "chalk": "^2.4.2",
77
- "child_process": "^1.0.2",
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": "11.0.1",
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": "^1.0.1",
89
+ "extract-json-from-string": "1.0.1",
89
90
  "fs-extra": "8.1.0",
90
- "glob": "^7.1.6",
91
+ "glob": "7.1.6",
91
92
  "got": "11.8.2",
92
93
  "hash-sum": "2.0.0",
93
- "http-shutdown": "^1.2.1",
94
+ "http-shutdown": "1.2.1",
94
95
  "iconv-lite": "0.5.0",
95
96
  "ini": "^2.0.0",
96
- "js-yaml": "^3.13.1",
97
- "jsonata": "^1.7.0",
98
- "jsonpath": "^1.0.2",
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": "^0.1.1",
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": "^2.88.0",
110
- "rimraf": "^3.0.0",
111
- "shell-path": "^2.1.0",
112
- "simplemde": "^1.11.2",
113
- "smoketail": "^0.2.2",
114
- "socket.io": "^2.3.0",
115
- "util": "^0.12.1",
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": "^7.1.1",
118
- "xterm": "^4.1.0",
119
- "xterm-addon-fit": "^0.2.1",
120
- "yargs": "^17.3.1"
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 = `// 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
- // Azure with terraform:
8
- // using a Service Principal with a Client Secret follow:
9
- // https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret
10
-
11
- // Examples:
12
- //
13
- // [kumohub.default]
14
- // username = your-username
15
- // password = your-password
16
- // subscription = kumohub-subscription-id
17
-
18
- // [aws.development]
19
- // profile = your-defined-aws-profile
20
-
21
- //
22
- // [azure.default]
23
- // subscription_id = 00000000-0000-0000-0000-000000000000
24
- // client_id = 00000000-0000-0000-0000-000000000000
25
- // client_secret = 0000000000000000000000000000000
26
- // tenant_id = 00000000-0000-0000-0000-000000000000
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');
@@ -94,7 +94,6 @@ class NetworkConfigStore {
94
94
 
95
95
  getProxyDetails() {
96
96
  let config = this.parseConfigFile();
97
- console.log('[settings-network-store] config=', config);
98
97
 
99
98
  // Make sure the section is present
100
99
  if (!config.proxy){
@@ -1,26 +1,159 @@
1
- // properties
2
- const defaultKeys = {
3
- test: {}
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
- const Store = require('./store');
7
-
8
- class TestConfigStore extends Store {
9
-
10
- constructor(defaults) {
11
- super({ ...defaults, configName: '.kumologica/test-config', defaults: {}});
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
- getTestConfig() {
15
- return super.get('test');
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
- setTestConfig(value) {
19
- super.set('test', value);
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
- module.exports = {
24
- TestConfigStore
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