@finos/legend-application-studio 28.14.1 → 28.14.2
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/function-activator/testable/FunctionTestableEditor.d.ts +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 +93 -14
- package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceRegistrationEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceRegistrationEditor.js +7 -1
- package/lib/components/editor/editor-group/service-editor/ServiceRegistrationEditor.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.d.ts +1 -13
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js +7 -21
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js.map +1 -1
- package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts +12 -1
- package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts.map +1 -1
- package/lib/components/editor/editor-group/testable/TestableSharedComponents.js +13 -3
- package/lib/components/editor/editor-group/testable/TestableSharedComponents.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts +34 -10
- 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 +174 -95
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts +1 -8
- package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js +1 -70
- package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.d.ts +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.js +2 -4
- package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.d.ts +2 -0
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.js +6 -0
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.d.ts +0 -8
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js +3 -73
- package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.d.ts +12 -2
- package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.js +120 -16
- package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.js.map +1 -1
- package/lib/stores/editor/utils/TestableUtils.d.ts +7 -1
- package/lib/stores/editor/utils/TestableUtils.d.ts.map +1 -1
- package/lib/stores/editor/utils/TestableUtils.js +71 -2
- package/lib/stores/editor/utils/TestableUtils.js.map +1 -1
- package/lib/stores/graph-modifier/DomainGraphModifierHelper.d.ts +6 -1
- package/lib/stores/graph-modifier/DomainGraphModifierHelper.d.ts.map +1 -1
- package/lib/stores/graph-modifier/DomainGraphModifierHelper.js +16 -1
- package/lib/stores/graph-modifier/DomainGraphModifierHelper.js.map +1 -1
- package/package.json +4 -4
- package/src/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.tsx +376 -61
- package/src/components/editor/editor-group/service-editor/ServiceRegistrationEditor.tsx +38 -1
- package/src/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.tsx +18 -92
- package/src/components/editor/editor-group/testable/TestableSharedComponents.tsx +74 -1
- package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +280 -131
- package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.ts +2 -94
- package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.ts +5 -5
- package/src/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.ts +7 -0
- package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.ts +1 -143
- package/src/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.ts +159 -19
- package/src/stores/editor/utils/TestableUtils.ts +144 -4
- package/src/stores/graph-modifier/DomainGraphModifierHelper.ts +33 -0
@@ -15,7 +15,6 @@
|
|
15
15
|
*/
|
16
16
|
|
17
17
|
import {
|
18
|
-
type Binding,
|
19
18
|
type ServiceTest,
|
20
19
|
type Service,
|
21
20
|
type ValueSpecification,
|
@@ -24,16 +23,7 @@ import {
|
|
24
23
|
buildLambdaVariableExpressions,
|
25
24
|
VariableExpression,
|
26
25
|
PureMultiExecution,
|
27
|
-
PackageableElementImplicitReference,
|
28
|
-
matchFunctionName,
|
29
|
-
isStubbed_RawLambda,
|
30
|
-
InstanceValue,
|
31
|
-
LambdaFunctionInstanceValue,
|
32
|
-
SimpleFunctionExpression,
|
33
|
-
CollectionInstanceValue,
|
34
26
|
resolveServiceQueryRawLambda,
|
35
|
-
PrimitiveInstanceValue,
|
36
|
-
PrimitiveType,
|
37
27
|
} from '@finos/legend-graph';
|
38
28
|
import { action, flow, makeObservable, observable } from 'mobx';
|
39
29
|
import {
|
@@ -59,15 +49,9 @@ import {
|
|
59
49
|
isNonNullable,
|
60
50
|
returnUndefOnError,
|
61
51
|
uuid,
|
62
|
-
getNullableFirstEntry,
|
63
|
-
LogEvent,
|
64
52
|
} from '@finos/legend-shared';
|
65
53
|
import type { EditorStore } from '../../../../EditorStore.js';
|
66
|
-
import {
|
67
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS,
|
68
|
-
generateVariableExpressionMockValue,
|
69
|
-
} from '@finos/legend-query-builder';
|
70
|
-
import { LEGEND_STUDIO_APP_EVENT } from '../../../../../../__lib__/LegendStudioEvent.js';
|
54
|
+
import { generateVariableExpressionMockValue } from '@finos/legend-query-builder';
|
71
55
|
|
72
56
|
export enum SERIALIZATION_FORMAT {
|
73
57
|
PURE = 'PURE',
|
@@ -199,7 +183,6 @@ export class ServiceTestSetupState {
|
|
199
183
|
addServiceTestAssertKeys: action,
|
200
184
|
syncWithQuery: action,
|
201
185
|
removeParamValueState: action,
|
202
|
-
getContentTypeWithParamFromQuery: action,
|
203
186
|
});
|
204
187
|
|
205
188
|
this.testState = testState;
|
@@ -243,131 +226,6 @@ export class ServiceTestSetupState {
|
|
243
226
|
}));
|
244
227
|
}
|
245
228
|
|
246
|
-
getContentTypeWithParamFromQuery(): {
|
247
|
-
contentType: string;
|
248
|
-
param: string;
|
249
|
-
}[] {
|
250
|
-
const query = resolveServiceQueryRawLambda(this.testState.service);
|
251
|
-
if (query && !isStubbed_RawLambda(query)) {
|
252
|
-
// safely pass unsupported funtions when building ValueSpecification from Rawlambda
|
253
|
-
try {
|
254
|
-
const valueSpec =
|
255
|
-
this.editorStore.graphManagerState.graphManager.buildValueSpecification(
|
256
|
-
this.editorStore.graphManagerState.graphManager.serializeRawValueSpecification(
|
257
|
-
query,
|
258
|
-
),
|
259
|
-
this.editorStore.graphManagerState.graph,
|
260
|
-
);
|
261
|
-
if (valueSpec instanceof LambdaFunctionInstanceValue) {
|
262
|
-
return this.getContentTypeWithParamRecursively(
|
263
|
-
valueSpec.values[0]?.expressionSequence.find(
|
264
|
-
(exp) =>
|
265
|
-
exp instanceof SimpleFunctionExpression &&
|
266
|
-
(matchFunctionName(
|
267
|
-
exp.functionName,
|
268
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS.SERIALIZE,
|
269
|
-
) ||
|
270
|
-
matchFunctionName(
|
271
|
-
exp.functionName,
|
272
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS.EXTERNALIZE,
|
273
|
-
)),
|
274
|
-
),
|
275
|
-
);
|
276
|
-
}
|
277
|
-
} catch (error) {
|
278
|
-
this.editorStore.applicationStore.logService.error(
|
279
|
-
LogEvent.create(LEGEND_STUDIO_APP_EVENT.SERVICE_TEST_SETUP_FAILURE),
|
280
|
-
error,
|
281
|
-
);
|
282
|
-
}
|
283
|
-
}
|
284
|
-
return [];
|
285
|
-
}
|
286
|
-
|
287
|
-
getContentTypeWithParamRecursively(
|
288
|
-
expression: ValueSpecification | undefined,
|
289
|
-
): {
|
290
|
-
contentType: string;
|
291
|
-
param: string;
|
292
|
-
}[] {
|
293
|
-
let currentExpression = expression;
|
294
|
-
const res: {
|
295
|
-
contentType: string;
|
296
|
-
param: string;
|
297
|
-
}[] = [];
|
298
|
-
// use if statement to safely scan service query without breaking the app
|
299
|
-
while (currentExpression instanceof SimpleFunctionExpression) {
|
300
|
-
if (
|
301
|
-
matchFunctionName(
|
302
|
-
currentExpression.functionName,
|
303
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS.INTERNALIZE,
|
304
|
-
) ||
|
305
|
-
matchFunctionName(
|
306
|
-
currentExpression.functionName,
|
307
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS.GET_RUNTIME_WITH_MODEL_QUERY_CONNECTION,
|
308
|
-
)
|
309
|
-
) {
|
310
|
-
if (currentExpression.parametersValues[1] instanceof InstanceValue) {
|
311
|
-
if (
|
312
|
-
currentExpression.parametersValues[1].values[0] instanceof
|
313
|
-
PackageableElementImplicitReference &&
|
314
|
-
currentExpression.parametersValues[2] instanceof VariableExpression
|
315
|
-
) {
|
316
|
-
res.push({
|
317
|
-
contentType: (
|
318
|
-
currentExpression.parametersValues[1].values[0].value as Binding
|
319
|
-
).contentType,
|
320
|
-
param: currentExpression.parametersValues[2].name,
|
321
|
-
});
|
322
|
-
} else if (
|
323
|
-
matchFunctionName(
|
324
|
-
currentExpression.functionName,
|
325
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS.GET_RUNTIME_WITH_MODEL_QUERY_CONNECTION,
|
326
|
-
) &&
|
327
|
-
currentExpression.parametersValues[1] instanceof
|
328
|
-
PrimitiveInstanceValue &&
|
329
|
-
currentExpression.parametersValues[1].genericType.value.rawType ===
|
330
|
-
PrimitiveType.STRING &&
|
331
|
-
currentExpression.parametersValues[2] instanceof VariableExpression
|
332
|
-
) {
|
333
|
-
res.push({
|
334
|
-
contentType: currentExpression.parametersValues[1]
|
335
|
-
.values[0] as string,
|
336
|
-
param: currentExpression.parametersValues[2].name,
|
337
|
-
});
|
338
|
-
}
|
339
|
-
}
|
340
|
-
currentExpression = currentExpression.parametersValues[1];
|
341
|
-
} else if (
|
342
|
-
matchFunctionName(
|
343
|
-
currentExpression.functionName,
|
344
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS.FROM,
|
345
|
-
)
|
346
|
-
) {
|
347
|
-
currentExpression = currentExpression.parametersValues[2];
|
348
|
-
} else if (
|
349
|
-
matchFunctionName(
|
350
|
-
currentExpression.functionName,
|
351
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS.MERGERUNTIMES,
|
352
|
-
)
|
353
|
-
) {
|
354
|
-
const collection = currentExpression.parametersValues[0];
|
355
|
-
if (collection instanceof CollectionInstanceValue) {
|
356
|
-
collection.values
|
357
|
-
.map((v) => this.getContentTypeWithParamRecursively(v))
|
358
|
-
.flat()
|
359
|
-
.map((p) => res.push(p));
|
360
|
-
}
|
361
|
-
currentExpression = collection;
|
362
|
-
} else {
|
363
|
-
currentExpression = getNullableFirstEntry(
|
364
|
-
currentExpression.parametersValues,
|
365
|
-
);
|
366
|
-
}
|
367
|
-
}
|
368
|
-
return res;
|
369
|
-
}
|
370
|
-
|
371
229
|
addServiceTestAssertKeys(val: string[]): void {
|
372
230
|
service_addAssertKeyForTest(this.testState.test, val);
|
373
231
|
}
|
@@ -36,6 +36,7 @@ import {
|
|
36
36
|
addUniqueEntry,
|
37
37
|
deleteEntry,
|
38
38
|
isNonNullable,
|
39
|
+
filterByType,
|
39
40
|
} from '@finos/legend-shared';
|
40
41
|
import { action, flowResult, makeObservable, observable } from 'mobx';
|
41
42
|
import type { EditorStore } from '../../../EditorStore.js';
|
@@ -45,7 +46,10 @@ import {
|
|
45
46
|
testable_deleteTest,
|
46
47
|
testable_setId,
|
47
48
|
} from '../../../../graph-modifier/Testable_GraphModifierHelper.js';
|
48
|
-
import {
|
49
|
+
import {
|
50
|
+
createEmptyEqualToJsonAssertion,
|
51
|
+
isTestPassing,
|
52
|
+
} from '../../../utils/TestableUtils.js';
|
49
53
|
import { TESTABLE_RESULT } from '../../../sidebar-state/testable/GlobalTestRunnerState.js';
|
50
54
|
import {
|
51
55
|
TestAssertionEditorState,
|
@@ -144,22 +148,6 @@ export abstract class TestableTestEditorState {
|
|
144
148
|
}
|
145
149
|
}
|
146
150
|
|
147
|
-
*runTest(): GeneratorFn<void> {
|
148
|
-
try {
|
149
|
-
this.resetResult();
|
150
|
-
this.runningTestAction.inProgress();
|
151
|
-
const result = (yield flowResult(this.fetchTestResult())) as TestResult;
|
152
|
-
this.handleTestResult(result);
|
153
|
-
this.runningTestAction.complete();
|
154
|
-
} catch (error) {
|
155
|
-
assertErrorThrown(error);
|
156
|
-
this.editorStore.applicationStore.notificationService.notifyError(
|
157
|
-
`Error running test: ${error.message}`,
|
158
|
-
);
|
159
|
-
this.runningTestAction.fail();
|
160
|
-
}
|
161
|
-
}
|
162
|
-
|
163
151
|
// Fetches test results. Caller of test should catch the error
|
164
152
|
async fetchTestResult(): Promise<TestResult> {
|
165
153
|
const input = new RunTestsTestableInput(this.testable);
|
@@ -195,6 +183,18 @@ export abstract class TestableTestEditorState {
|
|
195
183
|
});
|
196
184
|
}
|
197
185
|
|
186
|
+
correspondsToTestResult(val: TestResult): boolean {
|
187
|
+
const atomicTest = this.test;
|
188
|
+
if (atomicTest.id === val.atomicTest.id) {
|
189
|
+
const parent = atomicTest.__parent;
|
190
|
+
if (parent instanceof TestSuite) {
|
191
|
+
return parent.id === val.parentSuite?.id;
|
192
|
+
}
|
193
|
+
return val.parentSuite === undefined && val.testable === this.testable;
|
194
|
+
}
|
195
|
+
return false;
|
196
|
+
}
|
197
|
+
|
198
198
|
get assertionCount(): number {
|
199
199
|
return this.assertionEditorStates.length;
|
200
200
|
}
|
@@ -224,6 +224,21 @@ export abstract class TestableTestEditorState {
|
|
224
224
|
(state) => state.assertionResultState.result !== TESTABLE_RESULT.PASSED,
|
225
225
|
).length;
|
226
226
|
}
|
227
|
+
*runTest(): GeneratorFn<void> {
|
228
|
+
try {
|
229
|
+
this.resetResult();
|
230
|
+
this.runningTestAction.inProgress();
|
231
|
+
const result = (yield flowResult(this.fetchTestResult())) as TestResult;
|
232
|
+
this.handleTestResult(result);
|
233
|
+
this.runningTestAction.complete();
|
234
|
+
} catch (error) {
|
235
|
+
assertErrorThrown(error);
|
236
|
+
this.editorStore.applicationStore.notificationService.notifyError(
|
237
|
+
`Error running test: ${error.message}`,
|
238
|
+
);
|
239
|
+
this.runningTestAction.fail();
|
240
|
+
}
|
241
|
+
}
|
227
242
|
}
|
228
243
|
|
229
244
|
export abstract class TestableTestSuiteEditorState {
|
@@ -339,6 +354,7 @@ export abstract class TestablePackageableElementEditorState {
|
|
339
354
|
readonly testable: Testable;
|
340
355
|
testableResults: TestResult[] | undefined;
|
341
356
|
selectedTestSuite: TestableTestSuiteEditorState | undefined;
|
357
|
+
runningSuite: TestSuite | undefined;
|
342
358
|
|
343
359
|
testableComponentToRename: Test | undefined;
|
344
360
|
|
@@ -353,12 +369,58 @@ export abstract class TestablePackageableElementEditorState {
|
|
353
369
|
|
354
370
|
abstract init(): void;
|
355
371
|
|
356
|
-
abstract handleNewResults(results: TestResult[]): void;
|
357
|
-
|
358
372
|
get suiteCount(): number {
|
359
373
|
return this.testable.tests.length;
|
360
374
|
}
|
361
375
|
|
376
|
+
get suites(): TestSuite[] {
|
377
|
+
return this.testable.tests.filter(filterByType(TestSuite));
|
378
|
+
}
|
379
|
+
|
380
|
+
get passingSuites(): TestSuite[] {
|
381
|
+
const results = this.testableResults;
|
382
|
+
if (results?.length) {
|
383
|
+
return this.suites.filter((suite) =>
|
384
|
+
results
|
385
|
+
.filter((res) => res.parentSuite?.id === suite.id)
|
386
|
+
.every((e) => isTestPassing(e)),
|
387
|
+
);
|
388
|
+
}
|
389
|
+
return [];
|
390
|
+
}
|
391
|
+
|
392
|
+
get failingSuites(): TestSuite[] {
|
393
|
+
const results = this.testableResults;
|
394
|
+
if (results?.length) {
|
395
|
+
return this.suites.filter((suite) =>
|
396
|
+
results
|
397
|
+
.filter((res) => res.parentSuite?.id === suite.id)
|
398
|
+
.some((e) => !isTestPassing(e)),
|
399
|
+
);
|
400
|
+
}
|
401
|
+
return [];
|
402
|
+
}
|
403
|
+
|
404
|
+
resolveSuiteResults(suite: TestSuite): TestResult[] | undefined {
|
405
|
+
return this.testableResults?.filter((t) => t.parentSuite?.id === suite.id);
|
406
|
+
}
|
407
|
+
|
408
|
+
clearTestResultsForSuite(suite: TestSuite): void {
|
409
|
+
this.testableResults = this.testableResults?.filter(
|
410
|
+
(t) => !(this.resolveSuiteResults(suite) ?? []).includes(t),
|
411
|
+
);
|
412
|
+
}
|
413
|
+
|
414
|
+
get staticSuites(): TestSuite[] {
|
415
|
+
const results = this.testableResults;
|
416
|
+
if (results?.length) {
|
417
|
+
return this.suites.filter((suite) =>
|
418
|
+
results.every((res) => res.parentSuite?.id !== suite.id),
|
419
|
+
);
|
420
|
+
}
|
421
|
+
return this.suites;
|
422
|
+
}
|
423
|
+
|
362
424
|
setTestableResults(val: TestResult[] | undefined): void {
|
363
425
|
this.testableResults = val;
|
364
426
|
}
|
@@ -377,9 +439,36 @@ export abstract class TestablePackageableElementEditorState {
|
|
377
439
|
deleteTestSuite(testSuite: TestSuite): void {
|
378
440
|
testable_deleteTest(this.testable, testSuite);
|
379
441
|
if (this.selectedTestSuite?.suite === testSuite) {
|
442
|
+
this.selectedTestSuite = undefined;
|
380
443
|
this.init();
|
381
444
|
}
|
382
445
|
}
|
446
|
+
|
447
|
+
*runAllFailingSuites(): GeneratorFn<void> {
|
448
|
+
try {
|
449
|
+
this.isRunningFailingSuitesState.inProgress();
|
450
|
+
const input = new RunTestsTestableInput(this.testable);
|
451
|
+
this.failingSuites.forEach((s) => {
|
452
|
+
s.tests.forEach((t) => input.unitTestIds.push(new UniqueTestId(s, t)));
|
453
|
+
});
|
454
|
+
const testResults =
|
455
|
+
(yield this.editorStore.graphManagerState.graphManager.runTests(
|
456
|
+
[input],
|
457
|
+
this.editorStore.graphManagerState.graph,
|
458
|
+
)) as TestResult[];
|
459
|
+
this.handleNewResults(testResults);
|
460
|
+
this.isRunningFailingSuitesState.complete();
|
461
|
+
} catch (error) {
|
462
|
+
assertErrorThrown(error);
|
463
|
+
this.editorStore.applicationStore.notificationService.notifyError(error);
|
464
|
+
this.isRunningFailingSuitesState.fail();
|
465
|
+
} finally {
|
466
|
+
this.selectedTestSuite?.testStates.forEach((t) =>
|
467
|
+
t.runningTestAction.complete(),
|
468
|
+
);
|
469
|
+
}
|
470
|
+
}
|
471
|
+
|
383
472
|
*runTestable(): GeneratorFn<void> {
|
384
473
|
try {
|
385
474
|
this.setTestableResults(undefined);
|
@@ -406,4 +495,55 @@ export abstract class TestablePackageableElementEditorState {
|
|
406
495
|
);
|
407
496
|
}
|
408
497
|
}
|
498
|
+
|
499
|
+
*runSuite(suite: TestSuite): GeneratorFn<void> {
|
500
|
+
try {
|
501
|
+
this.runningSuite = suite;
|
502
|
+
this.clearTestResultsForSuite(suite);
|
503
|
+
this.selectedTestSuite?.testStates.forEach((t) => t.resetResult());
|
504
|
+
this.selectedTestSuite?.testStates.forEach((t) =>
|
505
|
+
t.runningTestAction.inProgress(),
|
506
|
+
);
|
507
|
+
const input = new RunTestsTestableInput(this.testable);
|
508
|
+
suite.tests.forEach((t) =>
|
509
|
+
input.unitTestIds.push(new UniqueTestId(suite, t)),
|
510
|
+
);
|
511
|
+
const testResults =
|
512
|
+
(yield this.editorStore.graphManagerState.graphManager.runTests(
|
513
|
+
[input],
|
514
|
+
this.editorStore.graphManagerState.graph,
|
515
|
+
)) as TestResult[];
|
516
|
+
|
517
|
+
this.handleNewResults(testResults);
|
518
|
+
} catch (error) {
|
519
|
+
assertErrorThrown(error);
|
520
|
+
this.editorStore.applicationStore.notificationService.notifyError(error);
|
521
|
+
this.isRunningTestableSuitesState.fail();
|
522
|
+
} finally {
|
523
|
+
this.selectedTestSuite?.testStates.forEach((t) =>
|
524
|
+
t.runningTestAction.complete(),
|
525
|
+
);
|
526
|
+
this.runningSuite = undefined;
|
527
|
+
}
|
528
|
+
}
|
529
|
+
|
530
|
+
handleNewResults(results: TestResult[]): void {
|
531
|
+
if (this.testableResults?.length) {
|
532
|
+
const newSuitesResults = results
|
533
|
+
.map((e) => e.parentSuite?.id)
|
534
|
+
.filter(isNonNullable);
|
535
|
+
const reducedFilters = this.testableResults.filter(
|
536
|
+
(res) => !newSuitesResults.includes(res.parentSuite?.id ?? ''),
|
537
|
+
);
|
538
|
+
this.setTestableResults([...reducedFilters, ...results]);
|
539
|
+
} else {
|
540
|
+
this.setTestableResults(results);
|
541
|
+
}
|
542
|
+
this.testableResults?.forEach((result) => {
|
543
|
+
const state = this.selectedTestSuite?.testStates.find((testState) =>
|
544
|
+
testState.correspondsToTestResult(result),
|
545
|
+
);
|
546
|
+
state?.handleTestResult(result);
|
547
|
+
});
|
548
|
+
}
|
409
549
|
}
|
@@ -29,29 +29,44 @@ import {
|
|
29
29
|
type AtomicTest,
|
30
30
|
type Class,
|
31
31
|
type EmbeddedDataVisitor,
|
32
|
+
type INTERNAL__UnknownConnection,
|
33
|
+
type DataElementReference,
|
34
|
+
type INTERNAL__UnknownEmbeddedData,
|
35
|
+
type TestResult,
|
36
|
+
type ValueSpecification,
|
37
|
+
type Binding,
|
38
|
+
type RawLambda,
|
32
39
|
ExternalFormatData,
|
33
40
|
RelationalCSVData,
|
34
41
|
ConnectionTestData,
|
35
42
|
EqualToJson,
|
36
43
|
DEFAULT_TEST_ASSERTION_PREFIX,
|
37
44
|
RelationalCSVDataTable,
|
38
|
-
type INTERNAL__UnknownConnection,
|
39
45
|
getAllIdentifiedConnectionsFromRuntime,
|
40
46
|
ModelStoreData,
|
41
47
|
ModelEmbeddedData,
|
42
48
|
PackageableElementExplicitReference,
|
43
|
-
type DataElementReference,
|
44
|
-
type INTERNAL__UnknownEmbeddedData,
|
45
|
-
type TestResult,
|
46
49
|
TestExecuted,
|
47
50
|
TestExecutionStatus,
|
51
|
+
isStubbed_RawLambda,
|
52
|
+
SimpleFunctionExpression,
|
53
|
+
InstanceValue,
|
54
|
+
CollectionInstanceValue,
|
55
|
+
matchFunctionName,
|
56
|
+
PackageableElementImplicitReference,
|
57
|
+
VariableExpression,
|
58
|
+
PrimitiveInstanceValue,
|
59
|
+
PrimitiveType,
|
60
|
+
LambdaFunctionInstanceValue,
|
48
61
|
} from '@finos/legend-graph';
|
49
62
|
import {
|
50
63
|
assertTrue,
|
51
64
|
ContentType,
|
52
65
|
generateEnumerableNameFromToken,
|
66
|
+
getNullableFirstEntry,
|
53
67
|
guaranteeNonEmptyString,
|
54
68
|
isNonNullable,
|
69
|
+
LogEvent,
|
55
70
|
returnUndefOnError,
|
56
71
|
UnsupportedOperationError,
|
57
72
|
uuid,
|
@@ -60,6 +75,8 @@ import { EmbeddedDataType } from '../editor-state/ExternalFormatState.js';
|
|
60
75
|
import type { EditorStore } from '../EditorStore.js';
|
61
76
|
import { createMockDataForMappingElementSource } from './MockDataUtils.js';
|
62
77
|
import type { DSL_Data_LegendStudioApplicationPlugin_Extension } from '../../extensions/DSL_Data_LegendStudioApplicationPlugin_Extension.js';
|
78
|
+
import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '@finos/legend-query-builder';
|
79
|
+
import { LEGEND_STUDIO_APP_EVENT } from '../../../__lib__/LegendStudioEvent.js';
|
63
80
|
|
64
81
|
export const DEFAULT_TEST_ASSERTION_ID = 'assertion_1';
|
65
82
|
export const DEFAULT_TEST_ID = 'test_1';
|
@@ -359,3 +376,126 @@ export const TEMPORARY__createRelationalDataFromCSV = (
|
|
359
376
|
export const isTestPassing = (testResult: TestResult): boolean =>
|
360
377
|
testResult instanceof TestExecuted &&
|
361
378
|
testResult.testExecutionStatus === TestExecutionStatus.PASS;
|
379
|
+
|
380
|
+
// external format param type
|
381
|
+
export interface TestParamContentType {
|
382
|
+
contentType: string;
|
383
|
+
param: string;
|
384
|
+
}
|
385
|
+
export const getContentTypeWithParamRecursively = (
|
386
|
+
expression: ValueSpecification | undefined,
|
387
|
+
): TestParamContentType[] => {
|
388
|
+
let currentExpression = expression;
|
389
|
+
const res: TestParamContentType[] = [];
|
390
|
+
// use if statement to safely scan service query without breaking the app
|
391
|
+
while (currentExpression instanceof SimpleFunctionExpression) {
|
392
|
+
if (
|
393
|
+
matchFunctionName(
|
394
|
+
currentExpression.functionName,
|
395
|
+
QUERY_BUILDER_SUPPORTED_FUNCTIONS.INTERNALIZE,
|
396
|
+
) ||
|
397
|
+
matchFunctionName(
|
398
|
+
currentExpression.functionName,
|
399
|
+
QUERY_BUILDER_SUPPORTED_FUNCTIONS.GET_RUNTIME_WITH_MODEL_QUERY_CONNECTION,
|
400
|
+
)
|
401
|
+
) {
|
402
|
+
if (currentExpression.parametersValues[1] instanceof InstanceValue) {
|
403
|
+
if (
|
404
|
+
currentExpression.parametersValues[1].values[0] instanceof
|
405
|
+
PackageableElementImplicitReference &&
|
406
|
+
currentExpression.parametersValues[2] instanceof VariableExpression
|
407
|
+
) {
|
408
|
+
res.push({
|
409
|
+
contentType: (
|
410
|
+
currentExpression.parametersValues[1].values[0].value as Binding
|
411
|
+
).contentType,
|
412
|
+
param: currentExpression.parametersValues[2].name,
|
413
|
+
});
|
414
|
+
} else if (
|
415
|
+
matchFunctionName(
|
416
|
+
currentExpression.functionName,
|
417
|
+
QUERY_BUILDER_SUPPORTED_FUNCTIONS.GET_RUNTIME_WITH_MODEL_QUERY_CONNECTION,
|
418
|
+
) &&
|
419
|
+
currentExpression.parametersValues[1] instanceof
|
420
|
+
PrimitiveInstanceValue &&
|
421
|
+
currentExpression.parametersValues[1].genericType.value.rawType ===
|
422
|
+
PrimitiveType.STRING &&
|
423
|
+
currentExpression.parametersValues[2] instanceof VariableExpression
|
424
|
+
) {
|
425
|
+
res.push({
|
426
|
+
contentType: currentExpression.parametersValues[1]
|
427
|
+
.values[0] as string,
|
428
|
+
param: currentExpression.parametersValues[2].name,
|
429
|
+
});
|
430
|
+
}
|
431
|
+
}
|
432
|
+
currentExpression = currentExpression.parametersValues[1];
|
433
|
+
} else if (
|
434
|
+
matchFunctionName(
|
435
|
+
currentExpression.functionName,
|
436
|
+
QUERY_BUILDER_SUPPORTED_FUNCTIONS.FROM,
|
437
|
+
)
|
438
|
+
) {
|
439
|
+
currentExpression = currentExpression.parametersValues[2];
|
440
|
+
} else if (
|
441
|
+
matchFunctionName(
|
442
|
+
currentExpression.functionName,
|
443
|
+
QUERY_BUILDER_SUPPORTED_FUNCTIONS.MERGERUNTIMES,
|
444
|
+
)
|
445
|
+
) {
|
446
|
+
const collection = currentExpression.parametersValues[0];
|
447
|
+
if (collection instanceof CollectionInstanceValue) {
|
448
|
+
collection.values
|
449
|
+
.map((v) => getContentTypeWithParamRecursively(v))
|
450
|
+
.flat()
|
451
|
+
.map((p) => res.push(p));
|
452
|
+
}
|
453
|
+
currentExpression = collection;
|
454
|
+
} else {
|
455
|
+
currentExpression = getNullableFirstEntry(
|
456
|
+
currentExpression.parametersValues,
|
457
|
+
);
|
458
|
+
}
|
459
|
+
}
|
460
|
+
return res;
|
461
|
+
};
|
462
|
+
|
463
|
+
export const getContentTypeWithParamFromQuery = (
|
464
|
+
query: RawLambda | undefined,
|
465
|
+
editorStore: EditorStore,
|
466
|
+
): TestParamContentType[] => {
|
467
|
+
if (query && !isStubbed_RawLambda(query)) {
|
468
|
+
// safely pass unsupported funtions when building ValueSpecification from Rawlambda
|
469
|
+
try {
|
470
|
+
const valueSpec =
|
471
|
+
editorStore.graphManagerState.graphManager.buildValueSpecification(
|
472
|
+
editorStore.graphManagerState.graphManager.serializeRawValueSpecification(
|
473
|
+
query,
|
474
|
+
),
|
475
|
+
editorStore.graphManagerState.graph,
|
476
|
+
);
|
477
|
+
if (valueSpec instanceof LambdaFunctionInstanceValue) {
|
478
|
+
return getContentTypeWithParamRecursively(
|
479
|
+
valueSpec.values[0]?.expressionSequence.find(
|
480
|
+
(exp) =>
|
481
|
+
exp instanceof SimpleFunctionExpression &&
|
482
|
+
(matchFunctionName(
|
483
|
+
exp.functionName,
|
484
|
+
QUERY_BUILDER_SUPPORTED_FUNCTIONS.SERIALIZE,
|
485
|
+
) ||
|
486
|
+
matchFunctionName(
|
487
|
+
exp.functionName,
|
488
|
+
QUERY_BUILDER_SUPPORTED_FUNCTIONS.EXTERNALIZE,
|
489
|
+
)),
|
490
|
+
),
|
491
|
+
);
|
492
|
+
}
|
493
|
+
} catch (error) {
|
494
|
+
editorStore.applicationStore.logService.error(
|
495
|
+
LogEvent.create(LEGEND_STUDIO_APP_EVENT.SERVICE_TEST_SETUP_FAILURE),
|
496
|
+
error,
|
497
|
+
);
|
498
|
+
}
|
499
|
+
}
|
500
|
+
return [];
|
501
|
+
};
|
@@ -50,6 +50,8 @@ import {
|
|
50
50
|
type INTERNAL__UnknownFunctionActivator,
|
51
51
|
type FunctionStoreTestData,
|
52
52
|
type ObserverContext,
|
53
|
+
type FunctionParameterValue,
|
54
|
+
type FunctionTest,
|
53
55
|
type FunctionTestSuite,
|
54
56
|
type AggregationKind,
|
55
57
|
type EmbeddedData,
|
@@ -73,6 +75,7 @@ import {
|
|
73
75
|
getOtherAssociatedProperty,
|
74
76
|
observe_EmbeddedData,
|
75
77
|
observe_FunctionTestSuite,
|
78
|
+
observe_FunctionParameterValue,
|
76
79
|
} from '@finos/legend-graph';
|
77
80
|
|
78
81
|
// --------------------------------------------- Packageable Element -------------------------------------
|
@@ -415,6 +418,36 @@ export const function_addTestSuite = action(
|
|
415
418
|
},
|
416
419
|
);
|
417
420
|
|
421
|
+
export const function_setParameterValueSpec = action(
|
422
|
+
(parameterValue: FunctionParameterValue, val: object) => {
|
423
|
+
parameterValue.value = val;
|
424
|
+
},
|
425
|
+
);
|
426
|
+
|
427
|
+
export const function_setParameterValues = action(
|
428
|
+
(test: FunctionTest, values: FunctionParameterValue[]) => {
|
429
|
+
test.parameters = values.map(observe_FunctionParameterValue);
|
430
|
+
},
|
431
|
+
);
|
432
|
+
|
433
|
+
export const function_deleteParameterValue = action(
|
434
|
+
(test: FunctionTest, value: FunctionParameterValue) => {
|
435
|
+
deleteEntry(test.parameters ?? [], value);
|
436
|
+
},
|
437
|
+
);
|
438
|
+
|
439
|
+
export const function_addParameterValue = action(
|
440
|
+
(test: FunctionTest, value: FunctionParameterValue) => {
|
441
|
+
test.parameters?.push(observe_FunctionParameterValue(value));
|
442
|
+
},
|
443
|
+
);
|
444
|
+
|
445
|
+
export const function_setParameterName = action(
|
446
|
+
(parameterValue: FunctionParameterValue, val: string) => {
|
447
|
+
parameterValue.name = val;
|
448
|
+
},
|
449
|
+
);
|
450
|
+
|
418
451
|
// --------------------------------------------- Enumeration -------------------------------------
|
419
452
|
|
420
453
|
export const enum_setName = action((val: Enum, value: string): void => {
|