@finos/legend-application-studio 28.13.3 → 28.13.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.
Files changed (33) hide show
  1. package/lib/components/editor/ActivityBar.js +1 -1
  2. package/lib/components/editor/ActivityBar.js.map +1 -1
  3. package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.js +15 -15
  4. package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.js.map +1 -1
  5. package/lib/components/editor/editor-group/function-activator/FunctionEditor.d.ts.map +1 -1
  6. package/lib/components/editor/editor-group/function-activator/FunctionEditor.js +10 -10
  7. package/lib/components/editor/editor-group/function-activator/FunctionEditor.js.map +1 -1
  8. package/lib/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.js +1 -1
  9. package/lib/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.js.map +1 -1
  10. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.d.ts.map +1 -1
  11. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js +52 -16
  12. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js.map +1 -1
  13. package/lib/index.css +1 -1
  14. package/lib/package.json +1 -1
  15. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts +8 -2
  16. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts.map +1 -1
  17. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js +140 -4
  18. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
  19. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts.map +1 -1
  20. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js.map +1 -1
  21. package/lib/stores/graph-modifier/DomainGraphModifierHelper.d.ts +1 -0
  22. package/lib/stores/graph-modifier/DomainGraphModifierHelper.d.ts.map +1 -1
  23. package/lib/stores/graph-modifier/DomainGraphModifierHelper.js +4 -1
  24. package/lib/stores/graph-modifier/DomainGraphModifierHelper.js.map +1 -1
  25. package/package.json +6 -6
  26. package/src/components/editor/ActivityBar.tsx +1 -1
  27. package/src/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.tsx +36 -36
  28. package/src/components/editor/editor-group/function-activator/FunctionEditor.tsx +86 -78
  29. package/src/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.tsx +1 -1
  30. package/src/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.tsx +156 -25
  31. package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +237 -5
  32. package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.ts +0 -1
  33. package/src/stores/graph-modifier/DomainGraphModifierHelper.ts +11 -0
@@ -22,17 +22,37 @@ import {
22
22
  isNonNullable,
23
23
  uuid,
24
24
  type GeneratorFn,
25
+ LogEvent,
26
+ guaranteeNonNullable,
27
+ addUniqueEntry,
28
+ uniq,
29
+ assertTrue,
30
+ guaranteeType,
25
31
  } from '@finos/legend-shared';
26
32
  import {
27
- FunctionTest,
28
33
  type ConcreteFunctionDefinition,
29
34
  type EmbeddedData,
30
- type FunctionStoreTestData,
31
- type FunctionTestSuite,
32
35
  type TestResult,
33
36
  type AtomicTest,
37
+ type EngineRuntime,
38
+ type ObserverContext,
39
+ type ValueSpecification,
40
+ FunctionTest,
34
41
  UniqueTestId,
42
+ FunctionStoreTestData,
43
+ FunctionTestSuite,
35
44
  RunTestsTestableInput,
45
+ RawLambda,
46
+ PackageableRuntime,
47
+ SimpleFunctionExpression,
48
+ LambdaFunctionInstanceValue,
49
+ SUPPORTED_FUNCTIONS,
50
+ matchFunctionName,
51
+ InstanceValue,
52
+ PackageableElementReference,
53
+ Database,
54
+ RelationalCSVData,
55
+ PackageableElementExplicitReference,
36
56
  } from '@finos/legend-graph';
37
57
  import {
38
58
  TestablePackageableElementEditorState,
@@ -43,8 +63,95 @@ import { EmbeddedDataEditorState } from '../../data/DataEditorState.js';
43
63
  import {
44
64
  functionTestable_deleteDataStore,
45
65
  functionTestable_setEmbeddedData,
66
+ function_addTestSuite,
46
67
  } from '../../../../../graph-modifier/DomainGraphModifierHelper.js';
47
- import { isTestPassing } from '../../../../utils/TestableUtils.js';
68
+ import {
69
+ DEFAULT_TEST_ASSERTION_ID,
70
+ createDefaultEqualToJSONTestAssertion,
71
+ isTestPassing,
72
+ } from '../../../../utils/TestableUtils.js';
73
+ import { LEGEND_STUDIO_APP_EVENT } from '../../../../../../__lib__/LegendStudioEvent.js';
74
+ import { testSuite_addTest } from '../../../../../graph-modifier/Testable_GraphModifierHelper.js';
75
+
76
+ const addToFunctionMap = (
77
+ val: SimpleFunctionExpression,
78
+ functions: Map<string, SimpleFunctionExpression[]>,
79
+ ): boolean => {
80
+ const values = functions.get(val.functionName) ?? [];
81
+ if (values.includes(val)) {
82
+ return false;
83
+ }
84
+ addUniqueEntry(values, val);
85
+ functions.set(val.functionName, values);
86
+ return true;
87
+ };
88
+
89
+ const collectSimpleFunctionExpressions = (
90
+ val: ValueSpecification,
91
+ functions: Map<string, SimpleFunctionExpression[]>,
92
+ ): void => {
93
+ if (val instanceof SimpleFunctionExpression) {
94
+ const continueProcessing = addToFunctionMap(val, functions);
95
+ if (continueProcessing) {
96
+ val.parametersValues.forEach((v) =>
97
+ collectSimpleFunctionExpressions(v, functions),
98
+ );
99
+ }
100
+ }
101
+ };
102
+
103
+ const resolveRuntimesFromQuery = (
104
+ func: ConcreteFunctionDefinition,
105
+ editorStore: EditorStore,
106
+ ): EngineRuntime[] | undefined => {
107
+ try {
108
+ const body = func.expressionSequence;
109
+ const rawLambda = new RawLambda([], body);
110
+ const functions = new Map<string, SimpleFunctionExpression[]>();
111
+ const valueSpec =
112
+ editorStore.graphManagerState.graphManager.buildValueSpecification(
113
+ editorStore.graphManagerState.graphManager.serializeRawValueSpecification(
114
+ rawLambda,
115
+ ),
116
+ editorStore.graphManagerState.graph,
117
+ );
118
+ if (valueSpec instanceof LambdaFunctionInstanceValue) {
119
+ const vals = guaranteeNonNullable(
120
+ valueSpec.values[0],
121
+ 'function expected to be of type lambda',
122
+ ).expressionSequence;
123
+ vals.forEach((v) => collectSimpleFunctionExpressions(v, functions));
124
+ const fromFunctions = Array.from(functions.keys())
125
+ .filter((v) => matchFunctionName(v, SUPPORTED_FUNCTIONS.FROM))
126
+ .map((e) => functions.get(e))
127
+ .flat()
128
+ .filter(isNonNullable);
129
+ const runtimeInstance: PackageableRuntime[] = [];
130
+ fromFunctions.forEach((v) => {
131
+ v.parametersValues.forEach((p) => {
132
+ if (p instanceof InstanceValue) {
133
+ p.values.forEach((pIn) => {
134
+ if (pIn instanceof PackageableElementReference) {
135
+ if (pIn.value instanceof PackageableRuntime) {
136
+ runtimeInstance.push(pIn.value);
137
+ }
138
+ }
139
+ });
140
+ }
141
+ });
142
+ });
143
+ return uniq(runtimeInstance.map((e) => e.runtimeValue).flat());
144
+ }
145
+ return [];
146
+ } catch (error) {
147
+ assertErrorThrown(error);
148
+ editorStore.applicationStore.logService.error(
149
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SERVICE_TEST_SETUP_FAILURE),
150
+ error,
151
+ );
152
+ return undefined;
153
+ }
154
+ };
48
155
 
49
156
  export class FunctionStoreTestDataState {
50
157
  readonly editorStore: EditorStore;
@@ -186,6 +293,25 @@ class FunctionTestDataState {
186
293
  }
187
294
  }
188
295
 
296
+ export const createFunctionTest = (
297
+ id: string,
298
+ observerContext: ObserverContext,
299
+ suite?: FunctionTestSuite | undefined,
300
+ ): FunctionTest => {
301
+ const funcionTest = new FunctionTest();
302
+ funcionTest.id = id;
303
+ funcionTest.assertions = [
304
+ createDefaultEqualToJSONTestAssertion(DEFAULT_TEST_ASSERTION_ID),
305
+ ];
306
+ if (suite) {
307
+ funcionTest.__parent = suite;
308
+ testSuite_addTest(suite, funcionTest, observerContext);
309
+ }
310
+ const assertion = createDefaultEqualToJSONTestAssertion(`expectedAssertion`);
311
+ funcionTest.assertions = [assertion];
312
+ assertion.parentTest = funcionTest;
313
+ return funcionTest;
314
+ };
189
315
  export class FunctionTestSuiteState extends TestableTestSuiteEditorState {
190
316
  readonly functionTestableState: FunctionTestableState;
191
317
  override suite: FunctionTestSuite;
@@ -209,9 +335,13 @@ export class FunctionTestSuiteState extends TestableTestSuiteEditorState {
209
335
  makeObservable(this, {
210
336
  dataState: observable,
211
337
  showCreateModal: observable,
338
+ selectTestState: observable,
339
+ changeTest: observable,
212
340
  buildTestState: action,
213
341
  deleteTest: action,
214
342
  buildTestStates: action,
343
+ setShowModal: action,
344
+ addNewTest: action,
215
345
  });
216
346
  this.functionTestableState = functionTestableState;
217
347
  this.suite = suite;
@@ -224,6 +354,10 @@ export class FunctionTestSuiteState extends TestableTestSuiteEditorState {
224
354
  this.selectTestState = this.testStates[0];
225
355
  }
226
356
 
357
+ setShowModal(val: boolean): void {
358
+ this.showCreateModal = val;
359
+ }
360
+
227
361
  buildTestStates(): FunctionTestState[] {
228
362
  return this.suite.tests
229
363
  .map((t) => this.buildTestState(t))
@@ -236,13 +370,34 @@ export class FunctionTestSuiteState extends TestableTestSuiteEditorState {
236
370
  }
237
371
  return undefined;
238
372
  }
373
+
374
+ addNewTest(id: string): void {
375
+ const test = createFunctionTest(
376
+ id,
377
+ this.editorStore.changeDetectionState.observerContext,
378
+ this.suite,
379
+ );
380
+
381
+ testSuite_addTest(
382
+ this.suite,
383
+ test,
384
+ this.functionTestableState.editorStore.changeDetectionState
385
+ .observerContext,
386
+ );
387
+ const testState = this.buildTestState(test);
388
+ if (testState) {
389
+ this.testStates.push(testState);
390
+ }
391
+ this.selectTestState = testState;
392
+ }
239
393
  }
240
394
 
241
395
  export class FunctionTestableState extends TestablePackageableElementEditorState {
242
396
  readonly functionEditorState: FunctionEditorState;
397
+ declare selectedTestSuite: FunctionTestSuiteState | undefined;
243
398
 
244
399
  runningSuite: FunctionTestSuite | undefined;
245
- declare selectedTestSuite: FunctionTestSuiteState | undefined;
400
+ createSuiteModal = false;
246
401
 
247
402
  constructor(functionEditorState: FunctionEditorState) {
248
403
  super(functionEditorState, functionEditorState.functionElement);
@@ -252,12 +407,15 @@ export class FunctionTestableState extends TestablePackageableElementEditorState
252
407
  selectedTestSuite: observable,
253
408
  testableResults: observable,
254
409
  runningSuite: observable,
410
+ createSuiteModal: observable,
255
411
  init: action,
256
412
  buildTestSuiteState: action,
257
413
  deleteTestSuite: action,
258
414
  changeSuite: action,
259
415
  handleNewResults: action,
260
416
  setRenameComponent: action,
417
+ clearTestResultsForSuite: action,
418
+ setCreateSuite: action,
261
419
  runTestable: flow,
262
420
  runSuite: flow,
263
421
  runAllFailingSuites: flow,
@@ -313,6 +471,80 @@ export class FunctionTestableState extends TestablePackageableElementEditorState
313
471
  }
314
472
  }
315
473
 
474
+ setCreateSuite(val: boolean): void {
475
+ this.createSuiteModal = val;
476
+ }
477
+
478
+ createSuite(suiteName: string, testName: string): void {
479
+ const functionSuite = new FunctionTestSuite();
480
+ functionSuite.id = suiteName;
481
+ const engineRuntimes = resolveRuntimesFromQuery(
482
+ this.function,
483
+ this.editorStore,
484
+ );
485
+ if (engineRuntimes?.length) {
486
+ try {
487
+ assertTrue(
488
+ engineRuntimes.length === 1,
489
+ `Function Test Suite Only supports One Runtime at this time. Found ${engineRuntimes.length}`,
490
+ );
491
+ const engineRuntime = guaranteeNonNullable(engineRuntimes[0]);
492
+ assertTrue(
493
+ !(
494
+ engineRuntime.connectionStores.length &&
495
+ engineRuntime.connections.length
496
+ ),
497
+ `Runtime found has two connection types defined. Please use connection stores only`,
498
+ );
499
+ const stores = [
500
+ ...engineRuntime.connections
501
+ .map((e) =>
502
+ e.storeConnections.map((s) => s.connection.store.value).flat(),
503
+ )
504
+ .flat(),
505
+ ...engineRuntime.connectionStores
506
+ .map((e) => e.storePointers.map((sPt) => sPt.value))
507
+ .flat(),
508
+ ];
509
+ assertTrue(Boolean(stores.length), 'No runtime store found');
510
+ assertTrue(
511
+ stores.length === 1,
512
+ 'Only one store supported in runtime for function tests',
513
+ );
514
+ const store = guaranteeNonNullable(stores[0]);
515
+ guaranteeType(
516
+ store,
517
+ Database,
518
+ 'Only Database stores supported now for function test',
519
+ );
520
+ const relational = new RelationalCSVData();
521
+ const data = new FunctionStoreTestData();
522
+ data.store = PackageableElementExplicitReference.create(store);
523
+ data.data = relational;
524
+ functionSuite.testData = [data];
525
+ } catch (error) {
526
+ assertErrorThrown(error);
527
+ this.editorStore.applicationStore.notificationService.notifyError(
528
+ `Unable to create function test suite: ${error.message}`,
529
+ );
530
+ return;
531
+ }
532
+ }
533
+ createFunctionTest(
534
+ testName,
535
+ this.editorStore.changeDetectionState.observerContext,
536
+ functionSuite,
537
+ );
538
+ // set test suite
539
+ function_addTestSuite(
540
+ this.function,
541
+ functionSuite,
542
+ this.editorStore.changeDetectionState.observerContext,
543
+ );
544
+ this.changeSuite(functionSuite);
545
+ this.setCreateSuite(false);
546
+ }
547
+
316
548
  *runSuite(suite: FunctionTestSuite): GeneratorFn<void> {
317
549
  try {
318
550
  this.runningSuite = suite;
@@ -509,7 +509,6 @@ export class CreateSuiteState {
509
509
  createBareMappingTest(
510
510
  testName,
511
511
  storeTestData,
512
-
513
512
  this.editorStore.changeDetectionState.observerContext,
514
513
  mappingTestSuite,
515
514
  );
@@ -72,6 +72,7 @@ import {
72
72
  isStubbed_PackageableElement,
73
73
  getOtherAssociatedProperty,
74
74
  observe_EmbeddedData,
75
+ observe_FunctionTestSuite,
75
76
  } from '@finos/legend-graph';
76
77
 
77
78
  // --------------------------------------------- Packageable Element -------------------------------------
@@ -404,6 +405,16 @@ export const functionTestable_deleteDataStore = action(
404
405
  },
405
406
  );
406
407
 
408
+ export const function_addTestSuite = action(
409
+ (
410
+ _func: ConcreteFunctionDefinition,
411
+ val: FunctionTestSuite,
412
+ context: ObserverContext,
413
+ ): void => {
414
+ addUniqueEntry(_func.tests, observe_FunctionTestSuite(val, context));
415
+ },
416
+ );
417
+
407
418
  // --------------------------------------------- Enumeration -------------------------------------
408
419
 
409
420
  export const enum_setName = action((val: Enum, value: string): void => {