@finos/legend-application-studio 27.1.0 → 27.1.1

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 (93) hide show
  1. package/lib/__lib__/LegendStudioEvent.d.ts +1 -0
  2. package/lib/__lib__/LegendStudioEvent.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioEvent.js +1 -0
  4. package/lib/__lib__/LegendStudioEvent.js.map +1 -1
  5. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts.map +1 -1
  6. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js +5 -4
  7. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js.map +1 -1
  8. package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.d.ts.map +1 -1
  9. package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.js +62 -12
  10. package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.js.map +1 -1
  11. package/lib/components/editor/editor-group/mapping-editor/MappingTestableEditor.d.ts +1 -1
  12. package/lib/components/editor/editor-group/mapping-editor/MappingTestableEditor.d.ts.map +1 -1
  13. package/lib/components/editor/editor-group/mapping-editor/MappingTestableEditor.js +101 -137
  14. package/lib/components/editor/editor-group/mapping-editor/MappingTestableEditor.js.map +1 -1
  15. package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts +11 -0
  16. package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts.map +1 -1
  17. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js +27 -2
  18. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js.map +1 -1
  19. package/lib/index.css +2 -2
  20. package/lib/index.css.map +1 -1
  21. package/lib/package.json +1 -1
  22. package/lib/stores/editor/NewElementState.d.ts.map +1 -1
  23. package/lib/stores/editor/NewElementState.js.map +1 -1
  24. package/lib/stores/editor/editor-state/element-editor-state/data/DataEditorState.d.ts +2 -2
  25. package/lib/stores/editor/editor-state/element-editor-state/data/DataEditorState.d.ts.map +1 -1
  26. package/lib/stores/editor/editor-state/element-editor-state/data/DataEditorState.js +2 -2
  27. package/lib/stores/editor/editor-state/element-editor-state/data/DataEditorState.js.map +1 -1
  28. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts +14 -19
  29. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts.map +1 -1
  30. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js +30 -65
  31. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js.map +1 -1
  32. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts +56 -78
  33. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts.map +1 -1
  34. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js +285 -384
  35. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js.map +1 -1
  36. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.d.ts +23 -0
  37. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.d.ts.map +1 -0
  38. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.js +129 -0
  39. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.js.map +1 -0
  40. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.d.ts.map +1 -1
  41. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js +2 -2
  42. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js.map +1 -1
  43. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts +1 -0
  44. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts.map +1 -1
  45. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js +12 -2
  46. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js.map +1 -1
  47. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.d.ts.map +1 -1
  48. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.js +15 -8
  49. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.js.map +1 -1
  50. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.d.ts +7 -4
  51. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.d.ts.map +1 -1
  52. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js +53 -10
  53. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js.map +1 -1
  54. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.d.ts +2 -1
  55. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.d.ts.map +1 -1
  56. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.js +20 -16
  57. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.js.map +1 -1
  58. package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.d.ts +1 -1
  59. package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.d.ts.map +1 -1
  60. package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.js +3 -0
  61. package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.js.map +1 -1
  62. package/lib/stores/editor/utils/MockDataUtils.d.ts.map +1 -1
  63. package/lib/stores/editor/utils/MockDataUtils.js +3 -0
  64. package/lib/stores/editor/utils/MockDataUtils.js.map +1 -1
  65. package/lib/stores/editor/utils/TestableUtils.d.ts +11 -1
  66. package/lib/stores/editor/utils/TestableUtils.d.ts.map +1 -1
  67. package/lib/stores/editor/utils/TestableUtils.js +50 -1
  68. package/lib/stores/editor/utils/TestableUtils.js.map +1 -1
  69. package/lib/stores/graph-modifier/DSL_Mapping_GraphModifierHelper.d.ts +5 -4
  70. package/lib/stores/graph-modifier/DSL_Mapping_GraphModifierHelper.d.ts.map +1 -1
  71. package/lib/stores/graph-modifier/DSL_Mapping_GraphModifierHelper.js +4 -1
  72. package/lib/stores/graph-modifier/DSL_Mapping_GraphModifierHelper.js.map +1 -1
  73. package/package.json +6 -6
  74. package/src/__lib__/LegendStudioEvent.ts +1 -1
  75. package/src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx +34 -37
  76. package/src/components/editor/editor-group/data-editor/RelationalCSVDataEditor.tsx +134 -31
  77. package/src/components/editor/editor-group/mapping-editor/MappingTestableEditor.tsx +296 -414
  78. package/src/components/editor/editor-group/testable/TestableSharedComponents.tsx +88 -3
  79. package/src/stores/editor/NewElementState.ts +0 -1
  80. package/src/stores/editor/editor-state/element-editor-state/data/DataEditorState.ts +7 -1
  81. package/src/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.ts +48 -77
  82. package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.ts +407 -617
  83. package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.ts +243 -0
  84. package/src/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.ts +6 -2
  85. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.ts +18 -1
  86. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.ts +20 -12
  87. package/src/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.ts +76 -18
  88. package/src/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.ts +29 -24
  89. package/src/stores/editor/sidebar-state/testable/GlobalTestRunnerState.ts +4 -1
  90. package/src/stores/editor/utils/MockDataUtils.ts +2 -0
  91. package/src/stores/editor/utils/TestableUtils.ts +73 -0
  92. package/src/stores/graph-modifier/DSL_Mapping_GraphModifierHelper.ts +15 -12
  93. package/tsconfig.json +1 -0
@@ -16,88 +16,53 @@
16
16
 
17
17
  import {
18
18
  type Mapping,
19
- type MappingTestSuite,
19
+ MappingTestSuite,
20
20
  type Class,
21
21
  type MappingModelCoverageAnalysisResult,
22
- type GraphManagerState,
23
22
  type RawLambda,
24
- type MappingTest,
25
- type SetImplementation,
26
- type TestAssertion,
23
+ MappingTest,
27
24
  type AtomicTest,
28
25
  type EmbeddedData,
29
26
  type Store,
30
27
  type DataElement,
28
+ type TestResult,
31
29
  LAMBDA_PIPE,
32
30
  buildSourceInformationSourceId,
33
31
  isStubbed_RawLambda,
34
32
  GRAPH_MANAGER_EVENT,
35
- MappingDataTestSuite,
36
- MappingQueryTestSuite,
37
- RootGraphFetchTree,
38
33
  PackageableElementExplicitReference,
39
- EntityMappedProperty,
40
- PropertyGraphFetchTree,
41
- PropertyExplicitReference,
42
- LambdaFunction,
43
- FunctionType,
44
- Multiplicity,
45
- CORE_PURE_PATH,
46
- buildRawLambdaFromLambdaFunction,
47
- MappingDataTest,
48
- MappingQueryTest,
49
- PureInstanceSetImplementation,
50
34
  StoreTestData,
51
- ModelStore,
52
35
  getRootSetImplementation,
53
- stub_RawLambda,
54
36
  DataElementReference,
55
37
  RelationalCSVData,
56
- getAllClassProperties,
57
- getAllClassDerivedProperties,
58
- RelationalInstanceSetImplementation,
59
- EmbeddedRelationalInstanceSetImplementation,
60
- TableAlias,
61
- Table,
62
- RelationalCSVDataTable,
63
- ModelStoreData,
64
- ModelEmbeddedData,
65
- getMappingCompatibleClasses,
38
+ RunTestsTestableInput,
39
+ UniqueTestId,
66
40
  } from '@finos/legend-graph';
67
41
  import { action, flow, flowResult, makeObservable, observable } from 'mobx';
68
42
  import {
69
43
  ActionState,
70
44
  assertErrorThrown,
71
- guaranteeNonNullable,
72
45
  type GeneratorFn,
73
- assertTrue,
74
46
  isNonNullable,
75
47
  UnsupportedOperationError,
76
48
  LogEvent,
77
49
  uuid,
78
50
  filterByType,
79
51
  } from '@finos/legend-shared';
80
- import {
81
- LambdaEditorState,
82
- buildGetAllFunction,
83
- buildSerialzieFunctionWithGraphFetch,
84
- } from '@finos/legend-query-builder';
85
- import {
86
- type MappingEditorState,
87
- getMappingElementSource,
88
- } from '../MappingEditorState.js';
52
+ import { LambdaEditorState } from '@finos/legend-query-builder';
53
+ import { type MappingEditorState } from '../MappingEditorState.js';
89
54
  import {
90
55
  mappingTestable_addStoreTestData,
91
56
  mappingTestable_deleteStoreTestData,
57
+ mappingTestable_setEmbeddedData,
92
58
  mappingTestable_setQuery,
93
59
  mapping_addTestSuite,
94
60
  mapping_deleteTestSuite,
95
61
  } from '../../../../../graph-modifier/DSL_Mapping_GraphModifierHelper.js';
96
62
  import {
97
- DEFAULT_TEST_ASSERTION_ID,
63
+ EmbeddedDataCreatorFromEmbeddedData,
98
64
  createBareExternalFormat,
99
- createDefaultEqualToJSONTestAssertion,
100
- createEmbeddedDataFromClass,
65
+ isTestPassing,
101
66
  } from '../../../../utils/TestableUtils.js';
102
67
  import {
103
68
  TESTABLE_TEST_TAB,
@@ -112,226 +77,71 @@ import {
112
77
  } from '../../../../../graph-modifier/Testable_GraphModifierHelper.js';
113
78
  import { EmbeddedDataType } from '../../../ExternalFormatState.js';
114
79
  import type { EditorStore } from '../../../../EditorStore.js';
115
- import { createMockDataForTable } from '../../../../utils/MockDataUtils.js';
116
-
117
- export enum MAPPING_TEST_SUITE_TYPE {
118
- DATA = 'DATA',
119
- QUERY = 'QUERY',
120
- }
121
-
122
- const createGraphFetchLambda = (
123
- mainClass: Class,
124
- graphManagerState: GraphManagerState,
125
- root: RootGraphFetchTree,
126
- ): RawLambda => {
127
- const lambdaFunction = new LambdaFunction(
128
- new FunctionType(
129
- PackageableElementExplicitReference.create(
130
- graphManagerState.graph.getType(CORE_PURE_PATH.ANY),
131
- ),
132
- Multiplicity.ONE,
133
- ),
134
- );
135
- const getAllFunction = buildGetAllFunction(mainClass, Multiplicity.ONE);
136
- const serialize = buildSerialzieFunctionWithGraphFetch(
137
- root,
138
- false,
139
- getAllFunction,
140
- undefined,
141
- );
142
- lambdaFunction.expressionSequence = [serialize];
143
- return buildRawLambdaFromLambdaFunction(lambdaFunction, graphManagerState);
144
- };
145
-
146
- const createBareModelStoreData = (
147
- _class: Class,
148
- editorStore: EditorStore,
149
- ): StoreTestData => {
150
- const embeddedData = createEmbeddedDataFromClass(_class, editorStore);
151
- const testData = new StoreTestData();
152
- const modelStoreData = new ModelStoreData();
153
- const modelData = new ModelEmbeddedData();
154
- modelData.data = embeddedData;
155
- modelData.model = PackageableElementExplicitReference.create(_class);
156
- modelStoreData.modelData = [modelData];
157
- testData.data = modelStoreData;
158
- testData.store = PackageableElementExplicitReference.create(
159
- ModelStore.INSTANCE,
160
- );
161
- return testData;
162
- };
163
-
164
- const createBareMappingDataTest = (
165
- id: string,
166
- storeTestData: StoreTestData | undefined,
167
- suite?: MappingTestSuite | undefined,
168
- ): MappingDataTest => {
169
- const dataTest = new MappingDataTest();
170
- dataTest.id = id;
171
- dataTest.storeTestData = storeTestData ? [storeTestData] : [];
172
- dataTest.assertions = [
173
- createDefaultEqualToJSONTestAssertion(DEFAULT_TEST_ASSERTION_ID),
174
- ];
175
- if (suite) {
176
- dataTest.__parent = suite;
177
- suite.tests.push(dataTest);
178
- }
179
- return dataTest;
180
- };
181
-
182
- const createBareMappingQueryTest = (
183
- id: string,
184
- query: RawLambda,
185
- suite?: MappingTestSuite | undefined,
186
- ): MappingQueryTest => {
187
- const dataTest = new MappingQueryTest();
188
- dataTest.id = id;
189
- dataTest.func = query;
190
- dataTest.assertions = [
191
- createDefaultEqualToJSONTestAssertion(DEFAULT_TEST_ASSERTION_ID),
192
- ];
193
- if (suite) {
194
- dataTest.__parent = suite;
195
- suite.tests.push(dataTest);
196
- }
197
- return dataTest;
198
- };
199
-
200
- export class MappingTestableQueryState extends LambdaEditorState {
201
- editorStore: EditorStore;
202
- parent: MappingQueryTestSuite | MappingQueryTest;
203
- isInitializingLambda = false;
204
- query: RawLambda;
205
-
206
- constructor(
207
- editorStore: EditorStore,
208
- parent: MappingQueryTestSuite | MappingQueryTest,
209
- query: RawLambda,
210
- ) {
211
- super('', LAMBDA_PIPE);
212
-
213
- makeObservable(this, {
214
- query: observable,
215
- isInitializingLambda: observable,
216
- setIsInitializingLambda: action,
217
- updateLamba: flow,
218
- });
219
-
220
- this.parent = parent;
221
- this.editorStore = editorStore;
222
- this.query = query;
223
- }
224
-
225
- get lambdaId(): string {
226
- return buildSourceInformationSourceId([this.uuid]);
227
- }
228
-
229
- setIsInitializingLambda(val: boolean): void {
230
- this.isInitializingLambda = val;
231
- }
232
-
233
- *updateLamba(val: RawLambda): GeneratorFn<void> {
234
- this.query = val;
235
- mappingTestable_setQuery(this.parent, val);
236
- yield flowResult(this.convertLambdaObjectToGrammarString(true));
237
- }
238
-
239
- *convertLambdaObjectToGrammarString(pretty?: boolean): GeneratorFn<void> {
240
- if (!isStubbed_RawLambda(this.query)) {
241
- try {
242
- const lambdas = new Map<string, RawLambda>();
243
- lambdas.set(this.lambdaId, this.query);
244
- const isolatedLambdas =
245
- (yield this.editorStore.graphManagerState.graphManager.lambdasToPureCode(
246
- lambdas,
247
- pretty,
248
- )) as Map<string, string>;
249
- const grammarText = isolatedLambdas.get(this.lambdaId);
250
- this.setLambdaString(
251
- grammarText !== undefined
252
- ? this.extractLambdaString(grammarText)
253
- : '',
254
- );
255
- this.clearErrors();
256
- } catch (error) {
257
- assertErrorThrown(error);
258
- this.editorStore.applicationStore.logService.error(
259
- LogEvent.create(GRAPH_MANAGER_EVENT.PARSING_FAILURE),
260
- error,
261
- );
262
- }
263
- } else {
264
- this.clearErrors();
265
- this.setLambdaString('');
266
- }
267
- }
268
-
269
- // NOTE: since we don't allow edition in text mode, we don't need to implement this
270
- *convertLambdaGrammarStringToObject(): GeneratorFn<void> {
271
- throw new UnsupportedOperationError();
272
- }
273
- }
274
-
275
- export abstract class MappingTestState extends TestableTestEditorState {
276
- readonly mappingTestableState: MappingTestableState;
277
- readonly uuid = uuid();
278
- override test: MappingTest;
279
-
280
- constructor(
281
- editorStore: EditorStore,
282
- mappingTestableState: MappingTestableState,
283
- test: MappingTest,
284
- ) {
285
- super(
286
- mappingTestableState.mapping,
287
- test,
288
- mappingTestableState.mappingEditorState.isReadOnly,
289
- editorStore,
290
- );
291
- this.mappingTestableState = mappingTestableState;
292
- this.test = test;
293
- this.selectedTab = this.defaultTab();
294
- }
295
-
296
- abstract defaultTab(): TESTABLE_TEST_TAB;
297
- }
80
+ import {
81
+ createBareMappingTest,
82
+ createGraphFetchQueryFromMappingAnalysis,
83
+ generateStoreTestDataFromSetImpl,
84
+ } from './MappingTestingHelper.js';
85
+ import { LEGEND_STUDIO_APP_EVENT } from '../../../../../../__lib__/LegendStudioEvent.js';
298
86
 
299
87
  export class StoreTestDataState {
300
88
  readonly editorStore: EditorStore;
301
- readonly testDataState: MappingTestableDataState;
89
+ readonly testDataState: MappingTestDataState;
302
90
  storeTestData: StoreTestData;
303
- generatingTestDataSate = ActionState.create();
304
91
  embeddedEditorState: EmbeddedDataEditorState;
92
+ dataElementModal = false;
305
93
 
306
94
  constructor(
307
95
  editorStore: EditorStore,
308
- testDataState: MappingTestableDataState,
96
+ testDataState: MappingTestDataState,
309
97
  value: StoreTestData,
310
98
  ) {
311
99
  makeObservable(this, {
312
100
  storeTestData: observable,
313
- generatingTestDataSate: observable,
101
+ dataElementModal: observable,
102
+ setDataElementModal: action,
103
+ changeEmbeddedData: action,
314
104
  });
315
105
  this.editorStore = editorStore;
316
106
  this.testDataState = testDataState;
317
107
  this.storeTestData = value;
108
+ this.embeddedEditorState = new EmbeddedDataEditorState(
109
+ this.testDataState.editorStore,
110
+ this.storeTestData.data,
111
+ {
112
+ hideSource: true,
113
+ },
114
+ );
115
+ }
116
+
117
+ setDataElementModal(val: boolean): void {
118
+ this.dataElementModal = val;
119
+ }
120
+
121
+ changeEmbeddedData(val: EmbeddedData): void {
122
+ mappingTestable_setEmbeddedData(
123
+ this.storeTestData,
124
+ val,
125
+ this.editorStore.changeDetectionState.observerContext,
126
+ );
318
127
  this.embeddedEditorState = new EmbeddedDataEditorState(
319
128
  this.testDataState.editorStore,
320
129
  this.storeTestData.data,
321
130
  );
322
131
  }
323
132
  }
324
- export class MappingTestableDataState {
133
+
134
+ export class MappingTestDataState {
325
135
  readonly editorStore: EditorStore;
326
136
  readonly mappingTestableState: MappingTestableState;
327
137
  selectedDataState: StoreTestDataState | undefined;
328
- dataHolder: MappingDataTest | MappingDataTestSuite;
138
+ dataHolder: MappingTest;
329
139
  showNewModal = false;
330
140
 
331
141
  constructor(
332
142
  editorStore: EditorStore,
333
143
  mappingTestableState: MappingTestableState,
334
- holder: MappingDataTest | MappingDataTestSuite,
144
+ holder: MappingTest,
335
145
  ) {
336
146
  makeObservable(this, {
337
147
  selectedDataState: observable,
@@ -397,97 +207,136 @@ export class MappingTestableDataState {
397
207
  }
398
208
  }
399
209
 
400
- export class MappingQueryTestState extends MappingTestState {
401
- override test: MappingQueryTest;
402
- queryState: MappingTestableQueryState;
210
+ export class MappingTestState extends TestableTestEditorState {
211
+ readonly parentState: MappingTestSuiteState;
212
+ readonly mappingTestableState: MappingTestableState;
213
+ readonly uuid = uuid();
214
+ override test: MappingTest;
215
+ dataState: MappingTestDataState;
403
216
 
404
217
  constructor(
405
218
  editorStore: EditorStore,
406
- mappingTestableState: MappingTestableState,
407
- test: MappingQueryTest,
219
+ parentSuiteState: MappingTestSuiteState,
220
+ test: MappingTest,
408
221
  ) {
409
- super(editorStore, mappingTestableState, test);
222
+ super(
223
+ parentSuiteState.mappingTestableState.mapping,
224
+ test,
225
+ parentSuiteState.mappingTestableState.mappingEditorState.isReadOnly,
226
+ editorStore,
227
+ );
410
228
  makeObservable(this, {
411
- defaultTab: observable,
412
229
  selectedAsertionState: observable,
413
230
  selectedTab: observable,
414
231
  assertionToRename: observable,
415
232
  assertionEditorStates: observable,
416
233
  testResultState: observable,
417
234
  runningTestAction: observable,
235
+ dataState: observable,
418
236
  addAssertion: action,
419
237
  setAssertionToRename: action,
420
238
  handleTestResult: action,
421
- buildQueryState: action,
422
239
  setSelectedTab: action,
423
240
  runTest: flow,
424
- test: observable,
425
241
  });
242
+ this.parentState = parentSuiteState;
243
+ this.mappingTestableState = parentSuiteState.mappingTestableState;
426
244
  this.test = test;
427
- this.queryState = this.buildQueryState();
245
+ this.selectedTab = this.defaultTab();
246
+ this.dataState = new MappingTestDataState(
247
+ this.editorStore,
248
+ parentSuiteState.mappingTestableState,
249
+ test,
250
+ );
428
251
  }
429
252
 
430
- override defaultTab(): TESTABLE_TEST_TAB {
253
+ defaultTab(): TESTABLE_TEST_TAB {
431
254
  return TESTABLE_TEST_TAB.SETUP;
432
255
  }
433
-
434
- buildQueryState(): MappingTestableQueryState {
435
- const queryState = new MappingTestableQueryState(
436
- this.editorStore,
437
- this.test,
438
- this.test.func,
439
- );
440
- flowResult(queryState.updateLamba(this.test.func)).catch(
441
- this.editorStore.applicationStore.alertUnhandledError,
442
- );
443
- return queryState;
444
- }
445
256
  }
446
257
 
447
- export class MappingDataTestState extends MappingTestState {
448
- override test: MappingDataTest;
449
- dataState: MappingTestableDataState;
258
+ export class MappingTestSuiteQueryState extends LambdaEditorState {
259
+ editorStore: EditorStore;
260
+ parent: MappingTestSuite;
261
+ isInitializingLambda = false;
262
+ query: RawLambda;
450
263
 
451
264
  constructor(
452
265
  editorStore: EditorStore,
453
- mappingTestableState: MappingTestableState,
454
- test: MappingDataTest,
266
+ parent: MappingTestSuite,
267
+ query: RawLambda,
455
268
  ) {
456
- super(editorStore, mappingTestableState, test);
269
+ super('', LAMBDA_PIPE);
270
+
457
271
  makeObservable(this, {
458
- defaultTab: observable,
459
- selectedAsertionState: observable,
460
- selectedTab: observable,
461
- assertionToRename: observable,
462
- assertionEditorStates: observable,
463
- testResultState: observable,
464
- runningTestAction: observable,
465
- addAssertion: action,
466
- setAssertionToRename: action,
467
- handleTestResult: action,
468
- setSelectedTab: action,
469
- runTest: flow,
470
- test: observable,
272
+ query: observable,
273
+ isInitializingLambda: observable,
274
+ setIsInitializingLambda: action,
275
+ updateLamba: flow,
471
276
  });
472
- this.test = test;
473
- this.dataState = new MappingTestableDataState(
474
- this.editorStore,
475
- mappingTestableState,
476
- test,
477
- );
277
+
278
+ this.parent = parent;
279
+ this.editorStore = editorStore;
280
+ this.query = query;
478
281
  }
479
282
 
480
- override defaultTab(): TESTABLE_TEST_TAB {
481
- return TESTABLE_TEST_TAB.SETUP;
283
+ get lambdaId(): string {
284
+ return buildSourceInformationSourceId([this.uuid]);
285
+ }
286
+
287
+ setIsInitializingLambda(val: boolean): void {
288
+ this.isInitializingLambda = val;
289
+ }
290
+
291
+ *updateLamba(val: RawLambda): GeneratorFn<void> {
292
+ this.query = val;
293
+ mappingTestable_setQuery(this.parent, val);
294
+ yield flowResult(this.convertLambdaObjectToGrammarString(true));
295
+ }
296
+
297
+ *convertLambdaObjectToGrammarString(pretty?: boolean): GeneratorFn<void> {
298
+ if (!isStubbed_RawLambda(this.query)) {
299
+ try {
300
+ const lambdas = new Map<string, RawLambda>();
301
+ lambdas.set(this.lambdaId, this.query);
302
+ const isolatedLambdas =
303
+ (yield this.editorStore.graphManagerState.graphManager.lambdasToPureCode(
304
+ lambdas,
305
+ pretty,
306
+ )) as Map<string, string>;
307
+ const grammarText = isolatedLambdas.get(this.lambdaId);
308
+ this.setLambdaString(
309
+ grammarText !== undefined
310
+ ? this.extractLambdaString(grammarText)
311
+ : '',
312
+ );
313
+ this.clearErrors();
314
+ } catch (error) {
315
+ assertErrorThrown(error);
316
+ this.editorStore.applicationStore.logService.error(
317
+ LogEvent.create(GRAPH_MANAGER_EVENT.PARSING_FAILURE),
318
+ error,
319
+ );
320
+ }
321
+ } else {
322
+ this.clearErrors();
323
+ this.setLambdaString('');
324
+ }
325
+ }
326
+
327
+ // NOTE: since we don't allow edition in text mode, we don't need to implement this
328
+ *convertLambdaGrammarStringToObject(): GeneratorFn<void> {
329
+ throw new UnsupportedOperationError();
482
330
  }
483
331
  }
484
332
 
485
- export abstract class MappingTestSuiteState extends TestableTestSuiteEditorState {
333
+ export class MappingTestSuiteState extends TestableTestSuiteEditorState {
486
334
  readonly mappingTestableState: MappingTestableState;
487
335
  override suite: MappingTestSuite;
488
336
  override testStates: MappingTestState[] = [];
489
337
  override selectTestState: MappingTestState | undefined;
490
338
  showCreateModal = false;
339
+ queryState: MappingTestSuiteQueryState;
491
340
 
492
341
  constructor(
493
342
  editorStore: EditorStore,
@@ -500,10 +349,26 @@ export abstract class MappingTestSuiteState extends TestableTestSuiteEditorState
500
349
  mappingTestableState.mappingEditorState.isReadOnly,
501
350
  editorStore,
502
351
  );
352
+ makeObservable(this, {
353
+ queryState: observable,
354
+ showCreateModal: observable,
355
+ selectTestState: observable,
356
+ runningSuiteState: observable,
357
+ setShowModal: action,
358
+ changeTest: action,
359
+ addNewTest: action,
360
+ deleteTest: action,
361
+ buildQueryState: action,
362
+ buildTestState: action,
363
+ createStoreTestData: action,
364
+ runSuite: flow,
365
+ runFailingTests: flow,
366
+ });
503
367
  this.mappingTestableState = mappingTestableState;
504
368
  this.suite = suite;
505
369
  this.testStates = this.buildTestStates();
506
370
  this.selectTestState = this.testStates[0];
371
+ this.queryState = this.buildQueryState();
507
372
  }
508
373
 
509
374
  buildTestStates(): MappingTestState[] {
@@ -512,12 +377,57 @@ export abstract class MappingTestSuiteState extends TestableTestSuiteEditorState
512
377
  .filter(isNonNullable);
513
378
  }
514
379
 
515
- abstract getDefaultClass(): Class | undefined;
380
+ buildTestState(val: AtomicTest): MappingTestState | undefined {
381
+ if (val instanceof MappingTest) {
382
+ return new MappingTestState(this.editorStore, this, val);
383
+ }
384
+ return undefined;
385
+ }
516
386
 
517
- abstract buildTestState(val: MappingTest): MappingTestState | undefined;
387
+ buildQueryState(): MappingTestSuiteQueryState {
388
+ const queryState = new MappingTestSuiteQueryState(
389
+ this.editorStore,
390
+ this.suite,
391
+ this.suite.func,
392
+ );
393
+ flowResult(queryState.updateLamba(this.suite.func)).catch(
394
+ this.editorStore.applicationStore.alertUnhandledError,
395
+ );
396
+ return queryState;
397
+ }
398
+
399
+ createStoreTestData(
400
+ targetClass: Class | undefined,
401
+ ): StoreTestData | undefined {
402
+ const firstData = this.suite.tests.filter(filterByType(MappingTest))[0]
403
+ ?.storeTestData[0];
404
+ if (firstData) {
405
+ const storeTestData = new StoreTestData();
406
+ storeTestData.store = PackageableElementExplicitReference.create(
407
+ firstData.store.value,
408
+ );
409
+ storeTestData.data = firstData.data.accept_EmbeddedDataVisitor(
410
+ new EmbeddedDataCreatorFromEmbeddedData(),
411
+ );
412
+ return storeTestData;
413
+ } else if (targetClass) {
414
+ const rootSetImpl = getRootSetImplementation(
415
+ this.mappingTestableState.mapping,
416
+ targetClass,
417
+ );
418
+ return rootSetImpl
419
+ ? generateStoreTestDataFromSetImpl(rootSetImpl, this.editorStore)
420
+ : undefined;
421
+ }
422
+ return undefined;
423
+ }
518
424
 
519
425
  addNewTest(id: string, _class: Class | undefined): void {
520
- const test = this.createNewTest(id, _class);
426
+ const test = createBareMappingTest(
427
+ id,
428
+ this.createStoreTestData(_class),
429
+ this.suite,
430
+ );
521
431
  testSuite_addTest(
522
432
  this.suite,
523
433
  test,
@@ -531,8 +441,6 @@ export abstract class MappingTestSuiteState extends TestableTestSuiteEditorState
531
441
  this.selectTestState = testState;
532
442
  }
533
443
 
534
- abstract createNewTest(id: string, _class: Class | undefined): MappingTest;
535
-
536
444
  setShowModal(val: boolean): void {
537
445
  this.showCreateModal = val;
538
446
  }
@@ -558,137 +466,6 @@ export abstract class MappingTestSuiteState extends TestableTestSuiteEditorState
558
466
  }
559
467
  }
560
468
 
561
- export class MappingDataTestSuiteState extends MappingTestSuiteState {
562
- override suite: MappingDataTestSuite;
563
- dataState: MappingTestableDataState;
564
- declare testStates: MappingQueryTestState[];
565
- declare selectTestState: MappingQueryTestState | undefined;
566
-
567
- constructor(
568
- editorStore: EditorStore,
569
- mappingTestableState: MappingTestableState,
570
- suite: MappingDataTestSuite,
571
- ) {
572
- super(editorStore, mappingTestableState, suite);
573
- makeObservable(this, {
574
- testStates: observable,
575
- selectTestState: observable,
576
- showCreateModal: observable,
577
- buildTestStates: action,
578
- changeTest: action,
579
- deleteTest: action,
580
- removeTestState: action,
581
- addNewTest: action,
582
- setShowModal: action,
583
- runFailingTests: flow,
584
- runSuite: flow,
585
- });
586
- this.suite = suite;
587
- this.dataState = new MappingTestableDataState(
588
- this.editorStore,
589
- mappingTestableState,
590
- suite,
591
- );
592
- }
593
- override buildTestState(val: MappingTest): MappingTestState | undefined {
594
- if (val instanceof MappingQueryTest) {
595
- return new MappingQueryTestState(
596
- this.editorStore,
597
- this.mappingTestableState,
598
- val,
599
- );
600
- }
601
- return undefined;
602
- }
603
-
604
- override createNewTest(id: string, _class: Class | undefined): MappingTest {
605
- const query = _class
606
- ? this.mappingTestableState.createSuiteState.createDefaultQuery(_class)
607
- : stub_RawLambda();
608
- return createBareMappingQueryTest(id, query, this.suite);
609
- }
610
-
611
- getDefaultClass(): Class | undefined {
612
- return getMappingCompatibleClasses(
613
- this.dataState.mappingTestableState.mapping,
614
- this.dataState.mappingTestableState.editorStore.graphManagerState
615
- .usableClasses,
616
- )[0];
617
- }
618
- }
619
-
620
- export class MappingQueryTestSuiteState extends MappingTestSuiteState {
621
- override suite: MappingQueryTestSuite;
622
- declare testStates: MappingDataTestState[];
623
- declare selectTestState: MappingDataTestState | undefined;
624
- queryState: MappingTestableQueryState;
625
-
626
- constructor(
627
- editorStore: EditorStore,
628
- mappingTestableState: MappingTestableState,
629
- suite: MappingQueryTestSuite,
630
- ) {
631
- super(editorStore, mappingTestableState, suite);
632
- makeObservable(this, {
633
- queryState: observable,
634
- testStates: observable,
635
- selectTestState: observable,
636
- showCreateModal: observable,
637
- deleteTest: action,
638
- buildTestStates: action,
639
- buildQueryState: action,
640
- addNewTest: action,
641
- changeTest: action,
642
- setShowModal: action,
643
- runFailingTests: flow,
644
- runSuite: flow,
645
- });
646
- this.suite = suite;
647
- this.queryState = this.buildQueryState();
648
- }
649
-
650
- override buildTestState(val: MappingTest): MappingTestState | undefined {
651
- if (val instanceof MappingDataTest) {
652
- return new MappingDataTestState(
653
- this.editorStore,
654
- this.mappingTestableState,
655
- val,
656
- );
657
- }
658
- return undefined;
659
- }
660
-
661
- override createNewTest(id: string, _class: Class | undefined): MappingTest {
662
- const data = _class
663
- ? createBareModelStoreData(_class, this.mappingTestableState.editorStore)
664
- : undefined;
665
- return createBareMappingDataTest(id, data, this.suite);
666
- }
667
-
668
- buildQueryState(): MappingTestableQueryState {
669
- const queryState = new MappingTestableQueryState(
670
- this.editorStore,
671
- this.suite,
672
- this.suite.func,
673
- );
674
- flowResult(queryState.updateLamba(this.suite.func)).catch(
675
- this.editorStore.applicationStore.alertUnhandledError,
676
- );
677
- return queryState;
678
- }
679
-
680
- getDefaultClass(): Class | undefined {
681
- const dataTest = this.suite.tests.filter(filterByType(MappingDataTest))[0];
682
- if (dataTest) {
683
- const storeTestData = dataTest.storeTestData[0]?.data;
684
- if (storeTestData instanceof ModelStoreData) {
685
- return storeTestData.modelData?.[0]?.model.value;
686
- }
687
- }
688
- return undefined;
689
- }
690
- }
691
-
692
469
  export class CreateSuiteState {
693
470
  readonly editorStore: EditorStore;
694
471
  readonly mappingTestableState: MappingTestableState;
@@ -704,26 +481,22 @@ export class CreateSuiteState {
704
481
 
705
482
  makeObservable(this, {
706
483
  showModal: observable,
707
- setShowModal: action,
708
484
  createAndAddTestSuite: flow,
709
485
  isCreatingSuiteState: observable,
710
486
  });
711
487
  }
712
488
 
713
- setShowModal(val: boolean): void {
714
- this.showModal = val;
715
- }
716
-
717
489
  *createAndAddTestSuite(
718
490
  _class: Class,
719
- type: MAPPING_TEST_SUITE_TYPE,
720
- name: string,
491
+ suiteName: string,
721
492
  testName: string,
722
493
  ): GeneratorFn<void> {
723
- // type
724
494
  try {
725
495
  this.isCreatingSuiteState.inProgress();
726
496
  const mappingTestableState = this.mappingTestableState;
497
+ const mappingTestSuite = new MappingTestSuite();
498
+ mappingTestSuite.id = suiteName;
499
+ // mapping anaylsis
727
500
  if (!mappingTestableState.mappingModelCoverageAnalysisResult) {
728
501
  this.isCreatingSuiteState.setMessage(
729
502
  'Analyzing mapping to generate test query...',
@@ -731,60 +504,30 @@ export class CreateSuiteState {
731
504
  yield flowResult(mappingTestableState.analyzeMappingModelCoverage());
732
505
  }
733
506
  this.isCreatingSuiteState.setMessage('Creating test query...');
507
+ // add query
508
+ mappingTestSuite.func = createGraphFetchQueryFromMappingAnalysis(
509
+ _class,
510
+ mappingTestableState.editorStore.graphManagerState,
511
+ mappingTestableState.mappingModelCoverageAnalysisResult,
512
+ );
513
+ // add first test
734
514
  const rootSetImpl = getRootSetImplementation(
735
- this.mappingTestableState.mapping,
515
+ mappingTestableState.mapping,
736
516
  _class,
737
517
  );
738
- const query = this.createDefaultQuery(_class);
739
518
  const storeTestData = rootSetImpl
740
- ? this.attemptToGenerateTestData(rootSetImpl, this.editorStore)
519
+ ? generateStoreTestDataFromSetImpl(rootSetImpl, this.editorStore)
741
520
  : undefined;
742
- let testSuite: MappingTestSuite;
743
- if (type === MAPPING_TEST_SUITE_TYPE.DATA) {
744
- const dataSuite = new MappingDataTestSuite();
745
- dataSuite.storeTestData = storeTestData ? [storeTestData] : [];
746
- const test = createBareMappingQueryTest(testName, query, dataSuite);
747
- test.__parent = dataSuite;
748
- dataSuite.tests = [test];
749
- const _assertion = createDefaultEqualToJSONTestAssertion(
750
- `${testName}_assertion1`,
751
- );
752
- test.assertions = [_assertion];
753
- _assertion.parentTest = test;
754
- testSuite = dataSuite;
755
- } else {
756
- const querySuite = new MappingQueryTestSuite();
757
- querySuite.func = query;
758
- // add test
759
- const _test = createBareMappingDataTest(
760
- testName,
761
- storeTestData,
762
- querySuite,
763
- );
764
- const _assertion = createDefaultEqualToJSONTestAssertion(
765
- `${testName}_assertion1`,
766
- );
767
- _test.assertions = [_assertion];
768
- _assertion.parentTest = _test;
769
- testSuite = querySuite;
770
- }
771
- testSuite.id = name;
521
+
522
+ createBareMappingTest(testName, storeTestData, mappingTestSuite);
523
+ // set test suite
772
524
  mapping_addTestSuite(
773
525
  this.mappingTestableState.mapping,
774
- testSuite,
526
+ mappingTestSuite,
775
527
  this.editorStore.changeDetectionState.observerContext,
776
528
  );
777
- this.mappingTestableState.changeSuite(testSuite);
778
- const selectTestState =
779
- this.mappingTestableState.selectedTestSuite?.selectTestState;
780
- const selectedAsertionState = selectTestState?.selectedAsertionState;
781
- if (selectTestState && selectedAsertionState) {
782
- this.isCreatingSuiteState.setMessage(
783
- 'Attempting to generate expected result...',
784
- );
785
- yield flowResult(selectedAsertionState.generateExpected());
786
- }
787
- this.setShowModal(false);
529
+ this.mappingTestableState.changeSuite(mappingTestSuite);
530
+ this.mappingTestableState.closeCreateModal();
788
531
  } catch (error) {
789
532
  assertErrorThrown(error);
790
533
  this.editorStore.applicationStore.notificationService.notifyError(
@@ -795,128 +538,26 @@ export class CreateSuiteState {
795
538
  this.isCreatingSuiteState.setMessage(undefined);
796
539
  }
797
540
  }
798
-
799
- createDefaultQuery(_class: Class): RawLambda {
800
- try {
801
- const mappingTestableState = this.mappingTestableState;
802
- const anaylsis = guaranteeNonNullable(
803
- mappingTestableState.mappingModelCoverageAnalysisResult,
804
- );
805
- const mappedEntity = guaranteeNonNullable(
806
- anaylsis.mappedEntities.find((e) => e.path === _class.path),
807
- );
808
- const rootTree = new RootGraphFetchTree(
809
- PackageableElementExplicitReference.create(_class),
810
- );
811
- // TODO: allow complex properties
812
- mappedEntity.properties.forEach((e) => {
813
- if (!(e instanceof EntityMappedProperty)) {
814
- const name = e.name;
815
- const property = getAllClassProperties(_class)
816
- .concat(
817
- // we fetch mapped derived properties without parameters
818
- getAllClassDerivedProperties(_class).filter(
819
- (p) => !p.parameters || !(p.parameters as object[]).length,
820
- ),
821
- )
822
- .find((prop) => prop.name === name);
823
- if (property) {
824
- const subTree = new PropertyGraphFetchTree(
825
- PropertyExplicitReference.create(property),
826
- undefined,
827
- );
828
- rootTree.subTrees.push(subTree);
829
- }
830
- }
831
- });
832
- assertTrue(!rootTree.isEmpty);
833
- return createGraphFetchLambda(
834
- _class,
835
- this.editorStore.graphManagerState,
836
- rootTree,
837
- );
838
- } catch (error) {
839
- assertErrorThrown(error);
840
- const lambdaFunction = new LambdaFunction(
841
- new FunctionType(
842
- PackageableElementExplicitReference.create(
843
- this.editorStore.graphManagerState.graph.getType(
844
- CORE_PURE_PATH.ANY,
845
- ),
846
- ),
847
- Multiplicity.ONE,
848
- ),
849
- );
850
- lambdaFunction.expressionSequence = [
851
- buildGetAllFunction(_class, Multiplicity.ONE),
852
- ];
853
- return buildRawLambdaFromLambdaFunction(
854
- lambdaFunction,
855
- this.editorStore.graphManagerState,
856
- );
857
- }
858
- }
859
-
860
- // change to use api call for relational
861
- attemptToGenerateTestData(
862
- setImpl: SetImplementation,
863
- editorStore: EditorStore,
864
- ): StoreTestData | undefined {
865
- if (
866
- setImpl instanceof RelationalInstanceSetImplementation ||
867
- setImpl instanceof EmbeddedRelationalInstanceSetImplementation ||
868
- setImpl instanceof EmbeddedRelationalInstanceSetImplementation
869
- ) {
870
- const _table = getMappingElementSource(
871
- setImpl,
872
- editorStore.pluginManager.getApplicationPlugins(),
873
- );
874
- if (_table instanceof TableAlias) {
875
- const relation = _table.relation.value;
876
- const owner = relation.schema._OWNER;
877
- const val = new RelationalCSVData();
878
- if (relation instanceof Table) {
879
- const mockTable = new RelationalCSVDataTable();
880
- const values = createMockDataForTable(relation);
881
- mockTable.table = relation.name;
882
- mockTable.schema = relation.schema.name;
883
- mockTable.values = values;
884
- val.tables.push(mockTable);
885
- }
886
- const testData = new StoreTestData();
887
- testData.data = val;
888
- testData.store = PackageableElementExplicitReference.create(owner);
889
- return testData;
890
- }
891
- } else if (setImpl instanceof PureInstanceSetImplementation) {
892
- const srcClass = setImpl.srcClass;
893
- if (srcClass) {
894
- return createBareModelStoreData(
895
- srcClass.value,
896
- this.mappingTestableState.editorStore,
897
- );
898
- }
899
- }
900
- return undefined;
901
- }
902
541
  }
903
542
 
904
543
  export class MappingTestableState {
905
544
  readonly editorStore: EditorStore;
906
545
  readonly mappingEditorState: MappingEditorState;
907
- selectedTestSuite: MappingTestSuiteState | undefined;
908
- testableComponentToRename:
909
- | MappingTestSuite
910
- | MappingTest
911
- | TestAssertion
912
- | undefined;
913
- // state
914
- createSuiteState: CreateSuiteState;
915
546
  mappingModelCoverageAnalysisState = ActionState.create();
916
547
  mappingModelCoverageAnalysisResult:
917
548
  | MappingModelCoverageAnalysisResult
918
549
  | undefined;
919
550
 
551
+ testableComponentToRename: MappingTestSuite | MappingTest | undefined;
552
+ createSuiteState: CreateSuiteState | undefined;
553
+
554
+ isRunningTestableSuitesState = ActionState.create();
555
+ isRunningFailingSuitesState = ActionState.create();
556
+
557
+ selectedTestSuite: MappingTestSuiteState | undefined;
558
+ testableResults: TestResult[] | undefined;
559
+ runningSuite: MappingTestSuite | undefined;
560
+
920
561
  constructor(
921
562
  editorStore: EditorStore,
922
563
  mappingEditorState: MappingEditorState,
@@ -927,16 +568,22 @@ export class MappingTestableState {
927
568
  selectedTestSuite: observable,
928
569
  testableComponentToRename: observable,
929
570
  renameTestableComponent: observable,
571
+ testableResults: observable,
572
+ createSuiteState: observable,
930
573
  changeSuite: action,
574
+ closeCreateModal: action,
575
+ openCreateModal: action,
931
576
  init: action,
932
577
  deleteTestSuite: action,
933
578
  analyzeMappingModelCoverage: flow,
934
579
  setRenameComponent: action,
580
+ handleNewResults: action,
581
+ runTestable: flow,
582
+ runSuite: flow,
583
+ runAllFailingSuites: flow,
935
584
  });
936
-
937
585
  this.editorStore = editorStore;
938
586
  this.mappingEditorState = mappingEditorState;
939
- this.createSuiteState = new CreateSuiteState(this.editorStore, this);
940
587
  this.init();
941
588
  }
942
589
 
@@ -944,21 +591,80 @@ export class MappingTestableState {
944
591
  return this.mappingEditorState.mapping;
945
592
  }
946
593
 
947
- renameTestableComponent(val: string | undefined): void {
948
- const _component = this.testableComponentToRename;
949
- if (_component) {
950
- testable_setId(_component, val ?? '');
594
+ get suiteCount(): number {
595
+ return this.mapping.tests.length;
596
+ }
597
+
598
+ get passingSuites(): MappingTestSuite[] {
599
+ const results = this.testableResults;
600
+ if (results?.length) {
601
+ return this.mapping.tests.filter((suite) =>
602
+ results
603
+ .filter((res) => res.parentSuite?.id === suite.id)
604
+ .every((e) => isTestPassing(e)),
605
+ );
606
+ }
607
+ return [];
608
+ }
609
+
610
+ get failingSuites(): MappingTestSuite[] {
611
+ const results = this.testableResults;
612
+ if (results?.length) {
613
+ return this.mapping.tests.filter((suite) =>
614
+ results
615
+ .filter((res) => res.parentSuite?.id === suite.id)
616
+ .some((e) => !isTestPassing(e)),
617
+ );
951
618
  }
619
+ return [];
620
+ }
621
+
622
+ get staticSuites(): MappingTestSuite[] {
623
+ const results = this.testableResults;
624
+ if (results?.length) {
625
+ return this.mapping.tests.filter((suite) =>
626
+ results.every((res) => res.parentSuite?.id !== suite.id),
627
+ );
628
+ }
629
+ return this.mapping.tests;
630
+ }
631
+
632
+ resolveSuiteResults(suite: MappingTestSuite): TestResult[] | undefined {
633
+ return this.testableResults?.filter((t) => t.parentSuite?.id === suite.id);
634
+ }
635
+
636
+ clearTestResultsForSuite(suite: MappingTestSuite): void {
637
+ this.testableResults = this.testableResults?.filter(
638
+ (t) => !(this.resolveSuiteResults(suite) ?? []).includes(t),
639
+ );
640
+ }
641
+
642
+ setTestableResults(val: TestResult[] | undefined): void {
643
+ this.testableResults = val;
952
644
  }
953
645
 
954
646
  init(): void {
955
- // TODO: ? should we add a test suite here by default if certain things
956
647
  const suite = this.mapping.tests[0];
957
648
  this.selectedTestSuite = suite
958
649
  ? this.buildTestSuiteState(suite)
959
650
  : undefined;
960
651
  }
961
652
 
653
+ openCreateModal(): void {
654
+ this.createSuiteState = new CreateSuiteState(this.editorStore, this);
655
+ }
656
+
657
+ closeCreateModal(): void {
658
+ this.createSuiteState = undefined;
659
+ }
660
+
661
+ renameTestableComponent(val: string | undefined): void {
662
+ const _component = this.testableComponentToRename;
663
+ if (_component) {
664
+ testable_setId(_component, val ?? '');
665
+ }
666
+ }
667
+
962
668
  changeSuite(suite: MappingTestSuite): void {
963
669
  if (this.selectedTestSuite?.suite !== suite) {
964
670
  this.selectedTestSuite = this.buildTestSuiteState(suite);
@@ -966,7 +672,7 @@ export class MappingTestableState {
966
672
  }
967
673
 
968
674
  setRenameComponent(
969
- testSuite: MappingTestSuite | AtomicTest | undefined,
675
+ testSuite: MappingTestSuite | MappingTest | undefined,
970
676
  ): void {
971
677
  this.testableComponentToRename = testSuite;
972
678
  }
@@ -978,25 +684,12 @@ export class MappingTestableState {
978
684
  }
979
685
  }
980
686
 
981
- buildTestSuiteStates(): MappingTestSuiteState[] {
982
- return this.mapping.tests
983
- .map((suite) => this.buildTestSuiteState(suite))
984
- .filter(isNonNullable);
985
- }
986
-
987
- buildTestSuiteState(
988
- val: MappingTestSuite,
989
- ): MappingTestSuiteState | undefined {
990
- if (val instanceof MappingQueryTestSuite) {
991
- return new MappingQueryTestSuiteState(this.editorStore, this, val);
992
- } else if (val instanceof MappingDataTestSuite) {
993
- return new MappingDataTestSuiteState(this.editorStore, this, val);
994
- }
995
- return undefined;
687
+ buildTestSuiteState(val: MappingTestSuite): MappingTestSuiteState {
688
+ return new MappingTestSuiteState(this.editorStore, this, val);
996
689
  }
997
690
 
998
- // check to only anaylsis when mapping has changed
999
691
  *analyzeMappingModelCoverage(): GeneratorFn<void> {
692
+ this.mappingModelCoverageAnalysisResult = undefined;
1000
693
  this.mappingModelCoverageAnalysisState.inProgress();
1001
694
  this.mappingModelCoverageAnalysisState.setMessage('Analyzing Mapping...');
1002
695
  try {
@@ -1008,19 +701,116 @@ export class MappingTestableState {
1008
701
  )) as MappingModelCoverageAnalysisResult;
1009
702
  } catch (error) {
1010
703
  assertErrorThrown(error);
1011
- this.editorStore.applicationStore.notificationService.notifyError(
1012
- error.message,
704
+ this.editorStore.applicationStore.logService.error(
705
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.MAPPING_TEST_FAILURE),
706
+ error,
1013
707
  );
1014
708
  } finally {
1015
709
  this.mappingModelCoverageAnalysisState.complete();
1016
710
  }
1017
711
  }
1018
712
 
1019
- runAllSuites(): void {
1020
- // TODO
713
+ *runSuite(suite: MappingTestSuite): GeneratorFn<void> {
714
+ try {
715
+ this.runningSuite = suite;
716
+ this.clearTestResultsForSuite(suite);
717
+ this.selectedTestSuite?.testStates.forEach((t) => t.resetResult());
718
+ this.selectedTestSuite?.testStates.forEach((t) =>
719
+ t.runningTestAction.inProgress(),
720
+ );
721
+ const input = new RunTestsTestableInput(this.mapping);
722
+ suite.tests.forEach((t) =>
723
+ input.unitTestIds.push(new UniqueTestId(suite, t)),
724
+ );
725
+ const testResults =
726
+ (yield this.editorStore.graphManagerState.graphManager.runTests(
727
+ [input],
728
+ this.editorStore.graphManagerState.graph,
729
+ )) as TestResult[];
730
+ this.handleNewResults(testResults);
731
+ } catch (error) {
732
+ assertErrorThrown(error);
733
+ this.editorStore.applicationStore.notificationService.notifyError(error);
734
+ this.isRunningTestableSuitesState.fail();
735
+ } finally {
736
+ this.selectedTestSuite?.testStates.forEach((t) =>
737
+ t.runningTestAction.complete(),
738
+ );
739
+ this.runningSuite = undefined;
740
+ }
741
+ }
742
+
743
+ *runTestable(): GeneratorFn<void> {
744
+ try {
745
+ this.setTestableResults(undefined);
746
+ this.isRunningTestableSuitesState.inProgress();
747
+ this.selectedTestSuite?.testStates.forEach((t) => t.resetResult());
748
+ this.selectedTestSuite?.testStates.forEach((t) =>
749
+ t.runningTestAction.inProgress(),
750
+ );
751
+ const input = new RunTestsTestableInput(this.mapping);
752
+ const testResults =
753
+ (yield this.editorStore.graphManagerState.graphManager.runTests(
754
+ [input],
755
+ this.editorStore.graphManagerState.graph,
756
+ )) as TestResult[];
757
+ this.handleNewResults(testResults);
758
+ this.isRunningTestableSuitesState.complete();
759
+ } catch (error) {
760
+ assertErrorThrown(error);
761
+ this.editorStore.applicationStore.notificationService.notifyError(error);
762
+ this.isRunningTestableSuitesState.fail();
763
+ } finally {
764
+ this.selectedTestSuite?.testStates.forEach((t) =>
765
+ t.runningTestAction.complete(),
766
+ );
767
+ }
768
+ }
769
+
770
+ *runAllFailingSuites(): GeneratorFn<void> {
771
+ try {
772
+ this.isRunningFailingSuitesState.inProgress();
773
+ const input = new RunTestsTestableInput(this.mapping);
774
+ this.failingSuites.forEach((s) => {
775
+ s.tests.forEach((t) => input.unitTestIds.push(new UniqueTestId(s, t)));
776
+ });
777
+ const testResults =
778
+ (yield this.editorStore.graphManagerState.graphManager.runTests(
779
+ [input],
780
+ this.editorStore.graphManagerState.graph,
781
+ )) as TestResult[];
782
+ this.handleNewResults(testResults);
783
+ this.isRunningFailingSuitesState.complete();
784
+ } catch (error) {
785
+ assertErrorThrown(error);
786
+ this.editorStore.applicationStore.notificationService.notifyError(error);
787
+ this.isRunningFailingSuitesState.fail();
788
+ } finally {
789
+ this.selectedTestSuite?.testStates.forEach((t) =>
790
+ t.runningTestAction.complete(),
791
+ );
792
+ }
1021
793
  }
1022
794
 
1023
- runAllFailingSuites(): void {
1024
- // TODO
795
+ handleNewResults(results: TestResult[]): void {
796
+ if (this.testableResults?.length) {
797
+ const newSuitesResults = results
798
+ .map((e) => e.parentSuite?.id)
799
+ .filter(isNonNullable);
800
+ const reducedFilters = this.testableResults.filter(
801
+ (res) => !newSuitesResults.includes(res.parentSuite?.id ?? ''),
802
+ );
803
+ this.setTestableResults([...reducedFilters, ...results]);
804
+ } else {
805
+ this.setTestableResults(results);
806
+ }
807
+ this.testableResults?.forEach((result) => {
808
+ const state = this.selectedTestSuite?.testStates.find(
809
+ (t) =>
810
+ t.test.id === result.atomicTest.id &&
811
+ t.parentState.suite.id === result.parentSuite?.id,
812
+ );
813
+ state?.handleTestResult(result);
814
+ });
1025
815
  }
1026
816
  }