@finos/legend-application-studio 28.21.17 → 28.21.19
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/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js +5 -3
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js.map +1 -1
- package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js +1 -19
- package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js.map +1 -1
- package/lib/components/editor/editor-group/uml-editor/StereotypeSelector.d.ts.map +1 -1
- package/lib/components/editor/editor-group/uml-editor/StereotypeSelector.js +7 -2
- package/lib/components/editor/editor-group/uml-editor/StereotypeSelector.js.map +1 -1
- package/lib/components/editor/editor-group/uml-editor/TaggedValueEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/uml-editor/TaggedValueEditor.js +9 -4
- package/lib/components/editor/editor-group/uml-editor/TaggedValueEditor.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts +2 -4
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js +98 -64
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
- package/package.json +14 -14
- package/src/components/editor/editor-group/data-editor/RelationElementsDataEditor.tsx +5 -3
- package/src/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.tsx +3 -32
- package/src/components/editor/editor-group/uml-editor/StereotypeSelector.tsx +9 -3
- package/src/components/editor/editor-group/uml-editor/TaggedValueEditor.tsx +11 -5
- package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +145 -85
|
@@ -14,7 +14,14 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
action,
|
|
19
|
+
flow,
|
|
20
|
+
flowResult,
|
|
21
|
+
makeObservable,
|
|
22
|
+
observable,
|
|
23
|
+
runInAction,
|
|
24
|
+
} from 'mobx';
|
|
18
25
|
import type { EditorStore } from '../../../../EditorStore.js';
|
|
19
26
|
import type { FunctionEditorState } from '../../FunctionEditorState.js';
|
|
20
27
|
import {
|
|
@@ -43,6 +50,8 @@ import {
|
|
|
43
50
|
type ValueSpecification,
|
|
44
51
|
type TestAssertion,
|
|
45
52
|
type AccessorOwner,
|
|
53
|
+
type AbstractPureGraphManager,
|
|
54
|
+
type PackageableElement,
|
|
46
55
|
FunctionParameterValue,
|
|
47
56
|
VariableExpression,
|
|
48
57
|
FunctionTest,
|
|
@@ -57,8 +66,11 @@ import {
|
|
|
57
66
|
InstanceValue,
|
|
58
67
|
PackageableElementReference,
|
|
59
68
|
Database,
|
|
69
|
+
DataProduct,
|
|
70
|
+
IngestDefinition,
|
|
60
71
|
PackageableElementExplicitReference,
|
|
61
72
|
observe_ValueSpecification,
|
|
73
|
+
observe_RelationElementsData,
|
|
62
74
|
buildLambdaVariableExpressions,
|
|
63
75
|
EqualTo,
|
|
64
76
|
EqualToRelation,
|
|
@@ -72,7 +84,7 @@ import {
|
|
|
72
84
|
type Accessor,
|
|
73
85
|
DataProductAccessor,
|
|
74
86
|
IngestionAccessor,
|
|
75
|
-
|
|
87
|
+
getAccessorItemLabelForElement,
|
|
76
88
|
V1_buildRelationElementsDataFromAccessors,
|
|
77
89
|
} from '@finos/legend-graph';
|
|
78
90
|
import {
|
|
@@ -191,6 +203,28 @@ const resolveRuntimesFromQuery = (
|
|
|
191
203
|
}
|
|
192
204
|
};
|
|
193
205
|
|
|
206
|
+
interface ElementDataItem {
|
|
207
|
+
id: string;
|
|
208
|
+
label: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const getElementDataItems = (
|
|
212
|
+
element: PackageableElement,
|
|
213
|
+
graphManager: AbstractPureGraphManager,
|
|
214
|
+
): ElementDataItem[] => {
|
|
215
|
+
if (element instanceof DataProduct) {
|
|
216
|
+
return element.accessPointGroups
|
|
217
|
+
.flatMap((g) => g.accessPoints)
|
|
218
|
+
.map((ap) => ({ id: ap.id, label: ap.id }));
|
|
219
|
+
}
|
|
220
|
+
if (element instanceof IngestDefinition) {
|
|
221
|
+
return graphManager
|
|
222
|
+
.getIngestDefinitionDatasetNames(element)
|
|
223
|
+
.map((name) => ({ id: name, label: name }));
|
|
224
|
+
}
|
|
225
|
+
return [];
|
|
226
|
+
};
|
|
227
|
+
|
|
194
228
|
export class FunctionStoreTestDataState {
|
|
195
229
|
readonly editorStore: EditorStore;
|
|
196
230
|
readonly testDataState: FunctionTestDataState;
|
|
@@ -239,51 +273,69 @@ export class FunctionStoreTestDataState {
|
|
|
239
273
|
embeddedDataState: RelationElementsDataState,
|
|
240
274
|
): Promise<void> {
|
|
241
275
|
const parentElement = this.storeTestData.element.value;
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
);
|
|
248
|
-
if (!parentAccessors.length) {
|
|
276
|
+
const graphManager = this.editorStore.graphManagerState.graphManager;
|
|
277
|
+
const graph = this.editorStore.graphManagerState.graph;
|
|
278
|
+
|
|
279
|
+
// For Database parents, fall back to the schema+table form
|
|
280
|
+
if (parentElement instanceof Database) {
|
|
249
281
|
embeddedDataState.setAccessorOptions(undefined, undefined);
|
|
250
282
|
return;
|
|
251
283
|
}
|
|
252
|
-
|
|
253
|
-
|
|
284
|
+
|
|
285
|
+
const items = getElementDataItems(parentElement, graphManager);
|
|
286
|
+
if (items.length === 0) {
|
|
254
287
|
embeddedDataState.setAccessorOptions(undefined, undefined);
|
|
255
288
|
return;
|
|
256
289
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
290
|
+
const typeLabel = getAccessorItemLabelForElement(
|
|
291
|
+
parentElement as AccessorOwner,
|
|
292
|
+
);
|
|
293
|
+
const options = await Promise.all(
|
|
294
|
+
items.map(async (item) => {
|
|
295
|
+
let columns: string[] = [];
|
|
296
|
+
try {
|
|
297
|
+
if (parentElement instanceof IngestDefinition) {
|
|
298
|
+
const accessor =
|
|
299
|
+
await graphManager.createAccessorFromPackageableElement(
|
|
300
|
+
parentElement,
|
|
301
|
+
graph,
|
|
302
|
+
{ schemaName: undefined, tableName: item.id },
|
|
303
|
+
);
|
|
304
|
+
if (accessor) {
|
|
305
|
+
columns = accessor.relationType.columns.map((c) => c.name);
|
|
306
|
+
}
|
|
307
|
+
} else if (parentElement instanceof DataProduct) {
|
|
308
|
+
const accessor = await graphManager.buildDataProductAccessor(
|
|
309
|
+
parentElement,
|
|
310
|
+
graph,
|
|
311
|
+
{ tableName: item.id },
|
|
312
|
+
);
|
|
313
|
+
if (accessor) {
|
|
314
|
+
columns = accessor.relationType.columns.map((c) => c.name);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
} catch {}
|
|
318
|
+
return { label: item.label, value: item.id, columns };
|
|
319
|
+
}),
|
|
320
|
+
);
|
|
321
|
+
runInAction(() => {
|
|
322
|
+
embeddedDataState.setAccessorOptions(options, typeLabel);
|
|
323
|
+
const columnsByItem = new Map(
|
|
324
|
+
options
|
|
325
|
+
.filter((o) => o.columns.length > 0)
|
|
326
|
+
.map((o) => [o.value, o.columns]),
|
|
327
|
+
);
|
|
274
328
|
for (const relState of embeddedDataState.relationElementStates) {
|
|
275
329
|
const rel = relState.relationElement;
|
|
276
330
|
if (rel.columns.length === 0) {
|
|
277
331
|
const key = rel.paths[rel.paths.length - 1];
|
|
278
|
-
const cols = key ?
|
|
332
|
+
const cols = key ? columnsByItem.get(key) : undefined;
|
|
279
333
|
if (cols) {
|
|
280
334
|
rel.columns = cols;
|
|
281
335
|
}
|
|
282
336
|
}
|
|
283
337
|
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
embeddedDataState.setAccessorOptions(options, typeLabel);
|
|
338
|
+
});
|
|
287
339
|
}
|
|
288
340
|
|
|
289
341
|
setDataElementModal(val: boolean): void {
|
|
@@ -655,34 +707,38 @@ class FunctionTestDataState {
|
|
|
655
707
|
return (this.dataHolder.testData ?? []).map((td) => td.element.value.path);
|
|
656
708
|
}
|
|
657
709
|
|
|
658
|
-
get availableElementsToAdd():
|
|
659
|
-
const
|
|
660
|
-
this.functionTestableState.resolvedIngestOrDataProductAccessors;
|
|
710
|
+
get availableElementsToAdd(): PackageableElement[] {
|
|
711
|
+
const graph = this.editorStore.graphManagerState.graph;
|
|
661
712
|
const existingPaths = new Set(this.existingElementPaths);
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
}
|
|
669
|
-
return Array.from(parentPaths).map((path) => ({ path }));
|
|
713
|
+
const candidates: PackageableElement[] = [
|
|
714
|
+
...graph.ingests,
|
|
715
|
+
...graph.dataProducts,
|
|
716
|
+
...graph.databases,
|
|
717
|
+
];
|
|
718
|
+
return candidates.filter((e) => !existingPaths.has(e.path));
|
|
670
719
|
}
|
|
671
720
|
|
|
672
721
|
addDataElement(elementPath: string): void {
|
|
673
|
-
const
|
|
674
|
-
this.
|
|
675
|
-
|
|
676
|
-
if (!group.length) {
|
|
722
|
+
const element =
|
|
723
|
+
this.editorStore.graphManagerState.graph.getNullableElement(elementPath);
|
|
724
|
+
if (!element) {
|
|
677
725
|
return;
|
|
678
726
|
}
|
|
679
|
-
const element =
|
|
680
|
-
this.editorStore.graphManagerState.graph.getElement(elementPath);
|
|
681
727
|
const data = new FunctionTestData();
|
|
682
728
|
data.element = PackageableElementExplicitReference.create(
|
|
683
729
|
element as AccessorOwner,
|
|
684
730
|
);
|
|
685
|
-
|
|
731
|
+
const matchingAccessors = this.functionTestableState.cachedAccessors.filter(
|
|
732
|
+
(a) => a.accessorOwner === elementPath,
|
|
733
|
+
);
|
|
734
|
+
if (matchingAccessors.length) {
|
|
735
|
+
data.data = V1_buildRelationElementsDataFromAccessors(matchingAccessors);
|
|
736
|
+
} else {
|
|
737
|
+
const relData = new RelationElementsData();
|
|
738
|
+
relData.relationElements = [];
|
|
739
|
+
data.data = relData;
|
|
740
|
+
}
|
|
741
|
+
observe_RelationElementsData(data.data as RelationElementsData);
|
|
686
742
|
if (!this.dataHolder.testData) {
|
|
687
743
|
this.dataHolder.testData = [];
|
|
688
744
|
}
|
|
@@ -966,36 +1022,9 @@ export class FunctionTestableState extends TestablePackageableElementEditorState
|
|
|
966
1022
|
|
|
967
1023
|
const ingestOrDataProductAccessors =
|
|
968
1024
|
this.resolvedIngestOrDataProductAccessors;
|
|
969
|
-
const databaseAccessors = this.cachedAccessors.filter(
|
|
970
|
-
(a) => a instanceof RelationalStoreAccessor,
|
|
971
|
-
);
|
|
972
1025
|
|
|
973
1026
|
try {
|
|
974
|
-
if (ingestOrDataProductAccessors.length) {
|
|
975
|
-
// Group by parent element path and create test data per parent
|
|
976
|
-
const parentElementMap = new Map<string, Accessor[]>();
|
|
977
|
-
for (const accessor of ingestOrDataProductAccessors) {
|
|
978
|
-
const key = accessor.accessorOwner;
|
|
979
|
-
if (key) {
|
|
980
|
-
const group = parentElementMap.get(key) ?? [];
|
|
981
|
-
group.push(accessor);
|
|
982
|
-
parentElementMap.set(key, group);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
functionSuite.testData = Array.from(parentElementMap.entries()).map(
|
|
986
|
-
([parentPath, group]) => {
|
|
987
|
-
const data = new FunctionTestData();
|
|
988
|
-
const element =
|
|
989
|
-
this.editorStore.graphManagerState.graph.getElement(parentPath);
|
|
990
|
-
data.element = PackageableElementExplicitReference.create(
|
|
991
|
-
element as AccessorOwner,
|
|
992
|
-
);
|
|
993
|
-
data.data = V1_buildRelationElementsDataFromAccessors(group);
|
|
994
|
-
return data;
|
|
995
|
-
},
|
|
996
|
-
);
|
|
997
|
-
} else {
|
|
998
|
-
// No ingest/data product accessors found — try runtime-based approach
|
|
1027
|
+
if (!ingestOrDataProductAccessors.length) {
|
|
999
1028
|
const engineRuntimes = this.associatedRuntimes;
|
|
1000
1029
|
if (engineRuntimes?.length) {
|
|
1001
1030
|
assertTrue(
|
|
@@ -1047,10 +1076,44 @@ export class FunctionTestableState extends TestablePackageableElementEditorState
|
|
|
1047
1076
|
type.path === CORE_PURE_PATH.RELATION ||
|
|
1048
1077
|
type.path === CORE_PURE_PATH.TABULAR_DATASET
|
|
1049
1078
|
) {
|
|
1050
|
-
this.editorStore.applicationStore.notificationService.
|
|
1051
|
-
`
|
|
1079
|
+
this.editorStore.applicationStore.notificationService.notifyWarning(
|
|
1080
|
+
`No runtime or accessors found, or they could not be resolved. For Relational (non-Lakehouse) function testing, please ensure that your query is bound to a runtime`,
|
|
1081
|
+
);
|
|
1082
|
+
// continue: still allow the user to create the suite/test and
|
|
1083
|
+
// add test data manually
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
if (this.cachedAccessors.length) {
|
|
1089
|
+
const accessorsByOwner = new Map<string, Accessor[]>();
|
|
1090
|
+
for (const accessor of this.cachedAccessors) {
|
|
1091
|
+
const key = accessor.accessorOwner;
|
|
1092
|
+
if (key) {
|
|
1093
|
+
const group = accessorsByOwner.get(key) ?? [];
|
|
1094
|
+
group.push(accessor);
|
|
1095
|
+
accessorsByOwner.set(key, group);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
if (!functionSuite.testData) {
|
|
1099
|
+
functionSuite.testData = [];
|
|
1100
|
+
}
|
|
1101
|
+
for (const [parentPath, group] of accessorsByOwner.entries()) {
|
|
1102
|
+
const builtData = V1_buildRelationElementsDataFromAccessors(group);
|
|
1103
|
+
const existing = functionSuite.testData.find(
|
|
1104
|
+
(td) => td.element.value.path === parentPath,
|
|
1105
|
+
);
|
|
1106
|
+
if (existing) {
|
|
1107
|
+
existing.data = builtData;
|
|
1108
|
+
} else {
|
|
1109
|
+
const element =
|
|
1110
|
+
this.editorStore.graphManagerState.graph.getElement(parentPath);
|
|
1111
|
+
const data = new FunctionTestData();
|
|
1112
|
+
data.element = PackageableElementExplicitReference.create(
|
|
1113
|
+
element as AccessorOwner,
|
|
1052
1114
|
);
|
|
1053
|
-
|
|
1115
|
+
data.data = builtData;
|
|
1116
|
+
functionSuite.testData.push(data);
|
|
1054
1117
|
}
|
|
1055
1118
|
}
|
|
1056
1119
|
}
|
|
@@ -1062,10 +1125,7 @@ export class FunctionTestableState extends TestablePackageableElementEditorState
|
|
|
1062
1125
|
return;
|
|
1063
1126
|
}
|
|
1064
1127
|
|
|
1065
|
-
const hasTestData =
|
|
1066
|
-
this.containsRuntime ||
|
|
1067
|
-
ingestOrDataProductAccessors.length > 0 ||
|
|
1068
|
-
databaseAccessors.length > 0;
|
|
1128
|
+
const hasTestData = this.containsRuntime || this.cachedAccessors.length > 0;
|
|
1069
1129
|
yield createFunctionTest(
|
|
1070
1130
|
testName,
|
|
1071
1131
|
this.editorStore.changeDetectionState.observerContext,
|