@kumologica/sdk 3.3.0-beta9 → 3.4.0-beta2

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 (60) hide show
  1. package/cli/commands/open.js +6 -7
  2. package/cli/commands/test-commands/TestSuiteRunner.js +75 -0
  3. package/cli/commands/test-commands/lib/TestCaseRunner.js +105 -0
  4. package/cli/commands/test-commands/lib/index.js +12 -0
  5. package/cli/commands/test-commands/lib/reporters/index.js +120 -0
  6. package/cli/commands/test.js +92 -120
  7. package/package.json +4 -5
  8. package/src/app/lib/stores/store.js +15 -1
  9. package/src/app/lib/stores/user-preference-store.js +2 -0
  10. package/src/app/lib/stores/workspace-preference-store.js +42 -0
  11. package/src/app/main-process/editor-manager.js +11 -51
  12. package/src/app/main-process/main-window.js +10 -0
  13. package/src/app/main-process/menu.js +4 -2
  14. package/src/app/main-process/modal-home.js +5 -7
  15. package/src/app/main-process/modal-newproject.js +4 -6
  16. package/src/app/main-process/modal-newtab.js +4 -6
  17. package/src/app/main-process/modal-nodelibrary.js +4 -6
  18. package/src/app/main-process/modal-welcome.js +5 -8
  19. package/src/app/main.js +3 -1
  20. package/src/app/preload.js +28 -4
  21. package/src/app/ui/editor-api/lib/index.js +6 -9
  22. package/src/app/ui/editor-client/public/red/red.js +434 -176
  23. package/src/app/ui/editor-client/public/red/red.min.js +3 -3
  24. package/src/app/ui/editor-client/public/red/style.min.css +1 -1
  25. package/src/app/ui/editor-client/public/vendor/vendor.css +21 -1
  26. package/src/app/ui/editor-client/src/js/red.js +1 -1
  27. package/src/app/ui/editor-client/src/js/ui/clipboard.js +8 -0
  28. package/src/app/ui/editor-client/src/js/ui/header.js +2 -40
  29. package/src/app/ui/editor-client/src/js/ui/palette-explorer.js +328 -0
  30. package/src/app/ui/editor-client/src/js/ui/palette.js +10 -8
  31. package/src/app/ui/editor-client/src/js/ui/project-info.js +10 -8
  32. package/src/app/ui/editor-client/src/js/ui/search.js +147 -44
  33. package/src/app/ui/editor-client/src/js/ui/ui-settings.js +1 -1
  34. package/src/app/ui/editor-client/src/js/ui/view.js +2 -5
  35. package/src/app/ui/editor-client/src/js/validators.js +2 -2
  36. package/src/app/ui/editor-client/src/sass/dropdownMenu.scss +1 -1
  37. package/src/app/ui/editor-client/src/sass/editor.scss +1 -0
  38. package/src/app/ui/editor-client/src/sass/header.scss +16 -7
  39. package/src/app/ui/editor-client/src/sass/palette.scss +46 -5
  40. package/src/app/ui/editor-client/src/sass/project-info.scss +4 -3
  41. package/src/app/ui/editor-client/src/sass/search.scss +49 -21
  42. package/src/app/ui/editor-client/src/sass/style.scss +1 -0
  43. package/src/app/ui/editor-client/src/sass/ui/common/editableList.scss +3 -3
  44. package/src/app/ui/editor-client/src/sass/ui/common/searchBox.scss +1 -2
  45. package/src/app/ui/editor-client/src/sass/ui-settings.scss +5 -3
  46. package/src/app/ui/editor-client/src/vendor/jqtree/jqtree.css +21 -1
  47. package/src/app/ui/editor-client/templates/index.mst +89 -79
  48. package/src/server/DesignerServer.js +161 -0
  49. package/src/server/certificate.pem +23 -0
  50. package/src/server/private-key.pem +28 -0
  51. package/cli/commands/test-utils/TestSuiteController.js +0 -363
  52. package/cli/commands/test-utils/TestSuiteController.test.js +0 -171
  53. package/cli/commands/test-utils/util/output.js +0 -14
  54. package/cli/commands/test-utils/util/updates/index.js +0 -17
  55. package/cli/commands/test-utils/util/updates/pkg.js +0 -13
  56. package/cli/commands/test-utils/util/updates/templates/default-settings.js +0 -209
  57. package/src/app/ui/editor-client/src/js/ui/palette-navigator.js +0 -144
  58. /package/cli/commands/{test-utils → test-commands/lib}/fixtures/example3-flow.json +0 -0
  59. /package/cli/commands/{test-utils → test-commands/lib}/fixtures/package.json +0 -0
  60. /package/cli/commands/{test-utils → test-commands/lib}/fixtures/s3-event.js +0 -0
@@ -1,363 +0,0 @@
1
- const EventEmitter = require('events').EventEmitter;
2
- const { performance } = require('perf_hooks');
3
- const fs = require('fs');
4
- const path = require('path');
5
- const chalk = require('chalk');
6
- const { error } = require('./util/output');
7
- const got = require('got');
8
- const log = console.log;
9
-
10
-
11
- const runtimeEvents = {
12
- TEST_TESTSUITE_START: 'test:testsuite-start',
13
- TEST_TESTSUITE_END: 'test:testsuite-end',
14
- TEST_TESTCASE_START: 'test:testcase-start',
15
- TEST_TESTCASE_END: 'test:testcase-end',
16
- TEST_TESTCASE_END_WITH_ERROR: 'test:testcase-end-with-error',
17
- };
18
-
19
- const internalEvents = {
20
- TEST_RUNNER_STOP: '__testrunner-stop__',
21
- };
22
-
23
- // Keep the counter of testcases to wait before sending signal to stop the testsuite
24
- let remainingTestCases = 0;
25
-
26
- const STATUS_PASSED = 'passed';
27
- const STATUS_FAILED = 'failed';
28
-
29
- class TestCase {
30
- constructor(testCaseId, testCaseDescription, testCaseTarget) {
31
- this._testCaseId = testCaseId;
32
- this._testCaseDescription = testCaseDescription;
33
- this._testCaseTarget = testCaseTarget;
34
- this._assertionResults = [];
35
- this._status = STATUS_PASSED;
36
- }
37
- attachAssertions(assertions) {
38
- this._assertionResults = assertions;
39
- if (this._assertionResults){
40
- let failedAssertions = this._assertionResults.filter(ar => ar.status === STATUS_FAILED);
41
- if (failedAssertions.length >= 1){
42
- this._status = STATUS_FAILED;
43
- } else {
44
- this._status = STATUS_PASSED;
45
- }
46
-
47
- } else {
48
- this._status = STATUS_PASSED;
49
- }
50
- }
51
-
52
- }
53
-
54
- class TestReporter {
55
- constructor(runtimeEventEmitter) {
56
- this._testReporterEmitter = new EventEmitter();
57
- this._runtimeEventEmitter = runtimeEventEmitter;
58
- this._testCases = [];
59
- this._runningTestCase = null;
60
- // Measuring the execution time
61
- this._timeStartTestSuite = null;
62
- this._timeEndTestSuite = null;
63
- this.subscribeRuntimeEvents();
64
- }
65
-
66
- get emitter() {
67
- return this._testReporterEmitter;
68
- }
69
-
70
- subscribeRuntimeEvents() {
71
- this._runtimeEventEmitter.on('runtime-event', async (data) => {
72
- //console.log('TestReporter has received a runtime-event', data);
73
- let p = data.payload;
74
-
75
- switch (data.id) {
76
- case runtimeEvents.TEST_TESTSUITE_START:
77
- this._timeStartTestSuite = performance.now();
78
- break;
79
- case runtimeEvents.TEST_TESTSUITE_END:
80
- this._timeEndTestSuite = performance.now();
81
- this.printSummary();
82
- break;
83
-
84
- case runtimeEvents.TEST_TESTCASE_START:
85
- let tcr = p.testCaseResults;
86
- let testCase = new TestCase(
87
- tcr.testCaseID,
88
- tcr.testCaseDescription,
89
- tcr.target
90
- );
91
- this.addTestCase(testCase);
92
- // this.printTestCaseHeader();
93
- break;
94
- case runtimeEvents.TEST_TESTCASE_END:
95
- this.printTestCaseResult(p.testCaseResults);
96
- let tc = this.findTestCase(p.testCaseResults.testCaseID);
97
- if (tc){
98
- tc.attachAssertions(p.testCaseResults.assertionResults);
99
- }
100
-
101
- remainingTestCases = remainingTestCases - 1;
102
- if (remainingTestCases === 0) {
103
- // Inform the TestController to stop the command
104
- this._testReporterEmitter.emit(internalEvents.TEST_RUNNER_STOP);
105
- }
106
- break;
107
- case runtimeEvents.TEST_TESTCASE_END_WITH_ERROR:
108
- this.printTestCaseWithError(p.testCaseResults, p.error);
109
- remainingTestCases = remainingTestCases - 1;
110
- if (remainingTestCases === 0) {
111
- // Inform the TestController to stop the command
112
- this._testReporterEmitter.emit(internalEvents.TEST_RUNNER_STOP);
113
- }
114
- break;
115
- default:
116
- // do not do anything
117
- }
118
-
119
- // For future ideas of how to implement debugger on terminal
120
- // if (data.id === 'node-debug') {
121
- // console.log(JSON.stringify(data.payload, null, 2));
122
- // }
123
- });
124
- }
125
-
126
- addTestCase(testCase) {
127
- this._runningTestCase = testCase;
128
- this._testCases.push(testCase);
129
- }
130
-
131
-
132
- findTestCase(testCaseId){
133
- let tcfound = this._testCases.filter(tc => tc._testCaseId === testCaseId);
134
- if (tcfound.length === 0) {
135
- return undefined;
136
- } else {
137
- return tcfound[0];
138
- }
139
-
140
- }
141
-
142
- printTestCaseHeader(description, target) {
143
- let prettyName = `${description}`; // mvp: only full flow being targeted > ${target}
144
- const sep = '=';
145
- let underline = sep.repeat(prettyName.length);
146
- let headerLine = `- ${prettyName}\n ${underline}`;
147
- log(chalk.cyan(headerLine));
148
- log(` Results:`);
149
- }
150
-
151
- printTestAssertion(ar, index){
152
- // console.log('Assertion:', ar)
153
- let { description, selector, property, comparison, valueExpected, diffReported } = ar;
154
- let status = diffReported? STATUS_FAILED: STATUS_PASSED;
155
- let icon;
156
- if (status === STATUS_FAILED) {
157
- icon = chalk.red('\u2716'); // cross mark
158
- } else {
159
- icon = chalk.green(`\u2713`); // tick
160
- }
161
- // Description
162
- let descriptionName;
163
- if (description && description.length > 0) {
164
- descriptionName = description;
165
- } else {
166
- descriptionName = `${selector} - ${property} - ${comparison} - ${valueExpected}`;
167
- }
168
- let prettyName = ` ${index}. ${icon} ${descriptionName}`;
169
- if (diffReported) {
170
- prettyName = `${prettyName}
171
- Diff report:\n${chalk.red(JSON.stringify(diffReported, null, 2))}`;
172
- }
173
- log (prettyName);
174
- }
175
-
176
- printTestAssertionResult(assertionResults) {
177
- // Print Assertions
178
- if (assertionResults.length === 0){
179
- log(chalk.dim(` (No assertions found)`));
180
- } else {
181
- assertionResults.map( (ar, index) => {
182
- this.printTestAssertion(ar, index);
183
- });
184
- }
185
- }
186
-
187
- printTestCaseStatus(testCaseResult){
188
- // See if any assertion has failed
189
- let failedAssertions = testCaseResult.assertionResults.filter(ar => ar.status === STATUS_FAILED);
190
- let failedTestCase = failedAssertions.length >= 1? true: false;
191
- // Print it nicely
192
- let coloredStatus;
193
- if (failedTestCase) {
194
- coloredStatus = chalk.bgRed.white(` Failed `);
195
- } else {
196
- coloredStatus = chalk.bgGreen.white(` Passed `);
197
- }
198
- log(` Status: ${coloredStatus}\n`);
199
- }
200
-
201
- printTestCaseWithError(testCaseResult, error){
202
- let {
203
- testCaseDescription,
204
- target
205
- } = testCaseResult;
206
-
207
- // Print header
208
- this.printTestCaseHeader(testCaseDescription, target);
209
- log(` ERROR: ${error}`);
210
- log(` Status: ${chalk.bgRed.white(` Failed `)}\n`);
211
- }
212
-
213
- printTestCaseResult(testCaseResult) {
214
- let {
215
- testCaseID,
216
- testCaseDescription,
217
- target,
218
- assertionResults } = testCaseResult;
219
-
220
- // Print header
221
- this.printTestCaseHeader(testCaseDescription, target);
222
-
223
- // Print assertions
224
- this.printTestAssertionResult(assertionResults || []);
225
-
226
- // Print status
227
- this.printTestCaseStatus(testCaseResult);
228
- }
229
-
230
- printSummary() {
231
- log(`TestCases - Completed
232
-
233
- Final Execution Statistics
234
- -------------------------------
235
- Execution Time: ${this.getExecutionTime()} ms
236
- Total Test Cases: ${this.getTestCases().length}
237
- Failed: ${this.getFailedTestCases().length}
238
- Passed: ${this.getPassedTestCases().length}
239
- -------------------------------
240
- `);
241
- }
242
-
243
- getTestCases() {
244
- return this._testCases;
245
- }
246
-
247
- getFailedTestCases() {
248
- let failedTestCases = this.getTestCases().filter(
249
- (tc) => tc._status === STATUS_FAILED
250
- );
251
- return failedTestCases || [];
252
- }
253
-
254
- getPassedTestCases() {
255
- let passedTestCases = this.getTestCases().filter(
256
- (tc) => tc._status === STATUS_PASSED
257
- );
258
- return passedTestCases || [];
259
- }
260
- getExecutionTime() {
261
- if (this._timeStartTestSuite && this._timeEndTestSuite) {
262
- return this.toFixed(this._timeEndTestSuite - this._timeStartTestSuite, 2);
263
- } else {
264
- return 0;
265
- }
266
- }
267
-
268
- /**
269
- *
270
- * @param {*} num - number to get truncated its decimal digits
271
- * @param {*} fixed - number of digits to be truncated
272
- */
273
- toFixed(num, fixed) {
274
- fixed = fixed || 0;
275
- fixed = Math.pow(10, fixed);
276
- return Math.floor(num * fixed) / fixed;
277
- }
278
- }
279
-
280
- class TestSuiteController {
281
- constructor(appServer) {
282
- this._appServer = appServer;
283
- this._testReporter = new TestReporter(this._appServer.events);
284
- }
285
-
286
- async waitForResults() {
287
- log(`TestCases - Executing\n`);
288
- try {
289
- const testReporterEmitter = this._testReporter.emitter;
290
- return new Promise((resolve, reject) => {
291
- testReporterEmitter.on(internalEvents.TEST_RUNNER_STOP, () => {
292
- resolve();
293
- });
294
- });
295
- } catch (err) {
296
- log(
297
- error(
298
- `Unexpected error occurred while starting server due to <${err.message}>`
299
- )
300
- );
301
- process.exit(1);
302
- }
303
- }
304
-
305
- findTestCasesFromFlow(flowFilePath) {
306
- const flowFileData = fs.readFileSync(flowFilePath, 'utf-8');
307
- const flowFileJson = JSON.parse(flowFileData);
308
- return flowFileJson.filter((node) => node.type === 'TestCase' || node.type === 'HTTPTestCase');
309
- }
310
-
311
- /**
312
- *
313
- * @param {*} testcasesSelected - array of {id: nodeId, name: nodeName}
314
- * @returns
315
- */
316
- async runTestSuite(testcasesSelected) {
317
- // === Starting the testSuite ===
318
- this._appServer.events.emit('runtime-event', {
319
- id: runtimeEvents.TEST_TESTSUITE_START,
320
- payload: {},
321
- });
322
-
323
- // === Iterate over all the testCases ===
324
- await this.runTestCases(testcasesSelected);
325
- await this.waitForResults();
326
- const errorsNum = this._testReporter.getFailedTestCases().length;
327
-
328
- // === End the testSuite
329
- this._appServer.events.emit('runtime-event', {
330
- id: runtimeEvents.TEST_TESTSUITE_END,
331
- payload: {},
332
- });
333
-
334
- return errorsNum;
335
- }
336
-
337
- async runTestCases(testCases) {
338
- remainingTestCases = testCases.length;
339
- const port = this._appServer._server.address().port;
340
-
341
- testCases.map(async(testCase) => {
342
- try{
343
- await got({
344
- url: `http://127.0.0.1:${port}`,
345
- method: 'POST',
346
- headers: { 'x-kumologica-testcasenode': `${testCase.id}` },
347
- });
348
- } catch (err) {
349
- log(`Error found while running TestCase Id=${testCase.id} due to... ${err}`);
350
- process.exit(1);
351
- }
352
-
353
- })
354
- }
355
-
356
- _debugResponse(resp) {
357
- log(JSON.stringify(resp));
358
- }
359
- }
360
-
361
- module.exports = {
362
- TestSuiteController,
363
- };
@@ -1,171 +0,0 @@
1
- const expect = require('chai').expect;
2
- const { TestSuiteController } = require('./TestSuiteController');
3
- const { resolve } = require('path');
4
- const { AppServer } = require('@kumologica/runtime');
5
-
6
- function emulateRuntimeEvents(events) {
7
- // Start testSuite
8
- events.emit('runtime-event', {
9
- id: 'test:testsuite-start',
10
- payload: {}
11
- });
12
- // Start testcase
13
- events.emit('runtime-event', {
14
- id: 'test:testcase-start',
15
- payload: {
16
- testCaseId: 'case1',
17
- testCaseDescription: 'Ensure status code is ok',
18
- target: 'flow:*'
19
- }
20
- });
21
-
22
- // Emit passed assertion
23
- events.emit('runtime-event', {
24
- id: 'test:assertion-report',
25
- payload: {
26
- description: 'HTTP Response is 200',
27
- selector: 'StatusCode',
28
- property: '',
29
- comparison: 'equalsTo',
30
- valueExpected: 200
31
- }
32
- });
33
-
34
- // Emit passed assertion
35
- events.emit('runtime-event', {
36
- id: 'test:assertion-report',
37
- payload: {
38
- description: 'At least one account returned',
39
- selector: 'JsonBody',
40
- property: '$.[*]',
41
- comparison: 'greaterOrEqualsTo',
42
- valueExpected: 1
43
- }
44
- });
45
-
46
- // Emit passed assertion
47
- events.emit('runtime-event', {
48
- id: 'test:assertion-report',
49
- payload: {
50
- description: 'Meet response SLA ',
51
- selector: 'responseTime',
52
- property: '',
53
- comparison: 'lessOrEqualsTo',
54
- valueExpected: 2000
55
- }
56
- });
57
-
58
- // Finish testCase
59
-
60
- events.emit('runtime-event', {
61
- id: 'test:testcase-end',
62
- payload: {
63
- testCaseId: 'case1'
64
- }
65
- });
66
-
67
- // Start testcase
68
- events.emit('runtime-event', {
69
- id: 'test:testcase-start',
70
- payload: {
71
- testCaseId: 'case2',
72
- testCaseDescription: 'Handle business exceptions',
73
- target: 'flow:*'
74
- }
75
- });
76
-
77
- // Emit passed assertion
78
- events.emit('runtime-event', {
79
- id: 'test:assertion-report',
80
- payload: {
81
- description: 'HTTP Response is 500',
82
- selector: 'StatusCode',
83
- property: '',
84
- comparison: 'equalsTo',
85
- valueExpected: 500
86
- }
87
- });
88
-
89
- // Emit passed assertion
90
- events.emit('runtime-event', {
91
- id: 'test:assertion-report',
92
- payload: {
93
- description: 'body is empty',
94
- selector: 'JsonBody',
95
- property: '',
96
- comparison: 'isEmpty()',
97
- valueExpected: 1
98
- }
99
- });
100
-
101
- // Emit passed assertion
102
- events.emit('runtime-event', {
103
- id: 'test:assertion-report',
104
- payload: {
105
- description: 'Doesnt meet response SLA ',
106
- selector: 'responseTime',
107
- property: '',
108
- comparison: 'greaterOrEqualsTo',
109
- valueExpected: 2000,
110
- diffReported: {
111
- expected: 'Response time > 2000 ms',
112
- actual: 'Response time equals to 500 ms'
113
- }
114
- }
115
- });
116
-
117
- // Emit passed assertion
118
- events.emit('runtime-event', {
119
- id: 'test:assertion-report',
120
- payload: {
121
- description: 'Response header is type JSON',
122
- selector: 'headers',
123
- property: 'content/type',
124
- comparison: 'equalsTo',
125
- valueExpected: 'json'
126
- }
127
- });
128
-
129
- // Finish testCase
130
-
131
- events.emit('runtime-event', {
132
- id: 'test:testcase-end',
133
- payload: {
134
- testCaseId: 'case1'
135
- }
136
- });
137
-
138
- // Finish testSuite
139
- events.emit('runtime-event', {
140
- id: 'test:testsuite-end',
141
- payload: {}
142
- });
143
- }
144
-
145
- it('Simulate happy path runtime events', async () => {
146
- expect('hola').to.equal('hola');
147
- //console.log(resolve('lib/cmds/test/fixtures/example3-flow.json'));
148
- let appServer = new AppServer(
149
- resolve('lib/cmds/test/fixtures/example3-flow.json'),
150
- resolve('lib/cmds/test/fixtures/example3-flow.json'),
151
- 1990,
152
- AppServer.mode.HEADLESS_KUMOLOGICA,
153
- AppServer.logLevel.ERROR,
154
- undefined
155
- );
156
- try {
157
- await appServer.start();
158
- let testSuiteController = new TestSuiteController(appServer);
159
- let promiseFinished = testSuiteController.waitForResults();
160
- emulateRuntimeEvents(appServer.events);
161
- await promiseFinished;
162
-
163
- await appServer.stop();
164
- process.exit();
165
- } catch (err) {
166
- console.log(
167
- `Unexpected error occurred while starting server due to <${err.message}>`
168
- );
169
- console.log(err);
170
- }
171
- });
@@ -1,14 +0,0 @@
1
- const chalk = require('chalk');
2
-
3
- function error(message) {
4
- return chalk.red(message);
5
- }
6
-
7
- function bold(message) {
8
- return chalk.bold(message);
9
- }
10
-
11
- module.exports = {
12
- error,
13
- bold
14
- };
@@ -1,17 +0,0 @@
1
- const updateNotifier = require('update-notifier');
2
- const chalk = require('chalk');
3
- const pkg = require('./pkg');
4
-
5
- module.exports = () => {
6
- const { update } = updateNotifier({ pkg });
7
-
8
- if (!update) {
9
- return;
10
- }
11
-
12
- console.log(
13
- `${chalk.white.bold.bgRed(
14
- 'UPDATE AVAILABLE'
15
- )} The latest version of Kumologica CLI is ${chalk.bold(update.latest)}`
16
- );
17
- };
@@ -1,13 +0,0 @@
1
- /* eslint-disable import/no-unresolved */
2
-
3
- const path = require('path');
4
- const pkg = require('../../../package.json');
5
-
6
- try {
7
- const distDir = path.dirname(process.execPath);
8
- pkg._npmPkg = require(path.join(distDir, '../../package.json'));
9
- } catch (err) {
10
- pkg._npmPkg = null;
11
- }
12
-
13
- module.exports = pkg;