@finos/legend-application-studio 28.13.1 → 28.13.3

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 (92) hide show
  1. package/lib/__lib__/LegendStudioApplicationNavigationContext.d.ts +1 -0
  2. package/lib/__lib__/LegendStudioApplicationNavigationContext.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioApplicationNavigationContext.js +1 -0
  4. package/lib/__lib__/LegendStudioApplicationNavigationContext.js.map +1 -1
  5. package/lib/application/LegendStudioApplicationConfig.d.ts +5 -9
  6. package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
  7. package/lib/application/LegendStudioApplicationConfig.js +6 -10
  8. package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
  9. package/lib/components/editor/ActivityBar.d.ts.map +1 -1
  10. package/lib/components/editor/ActivityBar.js +2 -2
  11. package/lib/components/editor/ActivityBar.js.map +1 -1
  12. package/lib/components/editor/editor-group/function-activator/FunctionEditor.d.ts +1 -1
  13. package/lib/components/editor/editor-group/function-activator/FunctionEditor.d.ts.map +1 -1
  14. package/lib/components/editor/editor-group/function-activator/FunctionEditor.js +46 -95
  15. package/lib/components/editor/editor-group/function-activator/FunctionEditor.js.map +1 -1
  16. package/lib/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.d.ts.map +1 -1
  17. package/lib/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.js +3 -3
  18. package/lib/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.js.map +1 -1
  19. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.d.ts +22 -0
  20. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.d.ts.map +1 -0
  21. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js +231 -0
  22. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js.map +1 -0
  23. package/lib/components/editor/side-bar/Explorer.d.ts.map +1 -1
  24. package/lib/components/editor/side-bar/Explorer.js +1 -25
  25. package/lib/components/editor/side-bar/Explorer.js.map +1 -1
  26. package/lib/index.css +1 -1
  27. package/lib/package.json +1 -1
  28. package/lib/stores/editor/editor-state/element-editor-state/{FunctionActivatorPromoteState.d.ts → FunctionActivatorState.d.ts} +9 -9
  29. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorState.d.ts.map +1 -0
  30. package/lib/stores/editor/editor-state/element-editor-state/{FunctionActivatorPromoteState.js → FunctionActivatorState.js} +24 -25
  31. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorState.js.map +1 -0
  32. package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.d.ts +6 -5
  33. package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.d.ts.map +1 -1
  34. package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.js +6 -5
  35. package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.js.map +1 -1
  36. package/lib/stores/editor/editor-state/element-editor-state/{FunctionActivatorBuilderState.d.ts → ToDelete_FunctionActivatorBuilderState.d.ts} +1 -1
  37. package/lib/stores/editor/editor-state/element-editor-state/ToDelete_FunctionActivatorBuilderState.d.ts.map +1 -0
  38. package/lib/stores/editor/editor-state/element-editor-state/{FunctionActivatorBuilderState.js → ToDelete_FunctionActivatorBuilderState.js} +1 -1
  39. package/lib/stores/editor/editor-state/element-editor-state/ToDelete_FunctionActivatorBuilderState.js.map +1 -0
  40. package/lib/stores/editor/editor-state/element-editor-state/function-activator/INTERNAL__UnknownFunctionActivatorEditorState.js +1 -1
  41. package/lib/stores/editor/editor-state/element-editor-state/function-activator/INTERNAL__UnknownFunctionActivatorEditorState.js.map +1 -1
  42. package/lib/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.d.ts +1 -1
  43. package/lib/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.d.ts.map +1 -1
  44. package/lib/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.js +3 -2
  45. package/lib/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.js.map +1 -1
  46. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts +81 -0
  47. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts.map +1 -0
  48. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js +286 -0
  49. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -0
  50. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.d.ts.map +1 -1
  51. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js +1 -1
  52. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js.map +1 -1
  53. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts +3 -17
  54. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts.map +1 -1
  55. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js +8 -69
  56. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js.map +1 -1
  57. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.d.ts +26 -3
  58. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.d.ts.map +1 -1
  59. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.js +72 -1
  60. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.js.map +1 -1
  61. package/lib/stores/graph-modifier/DomainGraphModifierHelper.d.ts +3 -1
  62. package/lib/stores/graph-modifier/DomainGraphModifierHelper.d.ts.map +1 -1
  63. package/lib/stores/graph-modifier/DomainGraphModifierHelper.js +7 -1
  64. package/lib/stores/graph-modifier/DomainGraphModifierHelper.js.map +1 -1
  65. package/lib/stores/graph-modifier/Testable_GraphModifierHelper.d.ts +3 -2
  66. package/lib/stores/graph-modifier/Testable_GraphModifierHelper.d.ts.map +1 -1
  67. package/lib/stores/graph-modifier/Testable_GraphModifierHelper.js +3 -0
  68. package/lib/stores/graph-modifier/Testable_GraphModifierHelper.js.map +1 -1
  69. package/package.json +4 -4
  70. package/src/__lib__/LegendStudioApplicationNavigationContext.ts +1 -0
  71. package/src/application/LegendStudioApplicationConfig.ts +7 -12
  72. package/src/components/editor/ActivityBar.tsx +3 -2
  73. package/src/components/editor/editor-group/function-activator/FunctionEditor.tsx +59 -276
  74. package/src/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.tsx +3 -10
  75. package/src/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.tsx +748 -0
  76. package/src/components/editor/side-bar/Explorer.tsx +0 -59
  77. package/src/stores/editor/editor-state/element-editor-state/{FunctionActivatorPromoteState.ts → FunctionActivatorState.ts} +23 -26
  78. package/src/stores/editor/editor-state/element-editor-state/FunctionEditorState.ts +7 -6
  79. package/src/stores/editor/editor-state/element-editor-state/function-activator/INTERNAL__UnknownFunctionActivatorEditorState.ts +1 -1
  80. package/src/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.ts +5 -2
  81. package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +414 -0
  82. package/src/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.ts +1 -4
  83. package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.ts +16 -96
  84. package/src/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.ts +105 -3
  85. package/src/stores/graph-modifier/DomainGraphModifierHelper.ts +23 -2
  86. package/src/stores/graph-modifier/Testable_GraphModifierHelper.ts +9 -1
  87. package/tsconfig.json +4 -2
  88. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorBuilderState.d.ts.map +0 -1
  89. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorBuilderState.js.map +0 -1
  90. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorPromoteState.d.ts.map +0 -1
  91. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorPromoteState.js.map +0 -1
  92. /package/src/stores/editor/editor-state/element-editor-state/{FunctionActivatorBuilderState.ts → ToDelete_FunctionActivatorBuilderState.ts} +0 -0
@@ -0,0 +1,748 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { observer } from 'mobx-react-lite';
18
+ import {
19
+ BlankPanelPlaceholder,
20
+ ContextMenu,
21
+ MenuContent,
22
+ MenuContentItem,
23
+ PanelContent,
24
+ PlayIcon,
25
+ PlusIcon,
26
+ ResizablePanel,
27
+ ResizablePanelGroup,
28
+ ResizablePanelSplitter,
29
+ ResizablePanelSplitterLine,
30
+ RunAllIcon,
31
+ RunErrorsIcon,
32
+ clsx,
33
+ } from '@finos/legend-art';
34
+ import { forwardRef, useEffect, useState } from 'react';
35
+ import {
36
+ type FunctionTestSuite,
37
+ type DataElement,
38
+ type EmbeddedData,
39
+ DataElementReference,
40
+ PackageableElementExplicitReference,
41
+ RelationalCSVData,
42
+ ModelStoreData,
43
+ ExternalFormatData,
44
+ ModelEmbeddedData,
45
+ } from '@finos/legend-graph';
46
+ import type {
47
+ FunctionStoreTestDataState,
48
+ FunctionTestState,
49
+ FunctionTestSuiteState,
50
+ FunctionTestableState,
51
+ } from '../../../../../stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js';
52
+ import {
53
+ TESTABLE_RESULT,
54
+ getTestableResultFromTestResult,
55
+ getTestableResultFromTestResults,
56
+ } from '../../../../../stores/editor/sidebar-state/testable/GlobalTestRunnerState.js';
57
+ import { flowResult } from 'mobx';
58
+ import { getTestableResultIcon } from '../../../side-bar/testable/GlobalTestRunner.js';
59
+ import { atomicTest_setDoc } from '../../../../../stores/graph-modifier/Testable_GraphModifierHelper.js';
60
+ import {
61
+ RenameModal,
62
+ SharedDataElementModal,
63
+ TestAssertionEditor,
64
+ } from '../../testable/TestableSharedComponents.js';
65
+ import { returnUndefOnError } from '@finos/legend-shared';
66
+ import {
67
+ EmbeddedDataCreatorFromEmbeddedData,
68
+ validateTestableId,
69
+ } from '../../../../../stores/editor/utils/TestableUtils.js';
70
+ import { EmbeddedDataEditor } from '../../data-editor/EmbeddedDataEditor.js';
71
+ import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../../__lib__/LegendStudioApplicationNavigationContext.js';
72
+ import { useApplicationNavigationContext } from '@finos/legend-application';
73
+
74
+ const FunctionTestableContextMenu = observer(
75
+ forwardRef<
76
+ HTMLDivElement,
77
+ {
78
+ addName?: string;
79
+ _delete?: () => void;
80
+ rename?: () => void;
81
+ add?: () => void;
82
+ }
83
+ >(function TestContainerContextMenu(props, ref) {
84
+ const { addName, add, rename, _delete } = props;
85
+ const addTest = (): void => {
86
+ add?.();
87
+ };
88
+ const remove = (): void => _delete?.();
89
+ const handleRename = (): void => rename?.();
90
+ return (
91
+ <MenuContent ref={ref}>
92
+ {rename && (
93
+ <MenuContentItem onClick={handleRename}>Rename</MenuContentItem>
94
+ )}
95
+ {_delete && <MenuContentItem onClick={remove}>Delete</MenuContentItem>}
96
+ {addName && rename && (
97
+ <MenuContentItem
98
+ onClick={addTest}
99
+ >{`Add ${addName}`}</MenuContentItem>
100
+ )}
101
+ </MenuContent>
102
+ );
103
+ }),
104
+ );
105
+
106
+ const FunctionTestSuiteItem = observer(
107
+ (props: {
108
+ suite: FunctionTestSuite;
109
+ functionTestableState: FunctionTestableState;
110
+ }) => {
111
+ const { suite, functionTestableState } = props;
112
+ const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] =
113
+ useState(false);
114
+ const isReadOnly = functionTestableState.functionEditorState.isReadOnly;
115
+ const openSuite = (): void => functionTestableState.changeSuite(suite);
116
+ const results = functionTestableState.testableResults?.filter(
117
+ (t) => t.parentSuite?.id === suite.id,
118
+ );
119
+ const isRunning =
120
+ functionTestableState.isRunningTestableSuitesState.isInProgress ||
121
+ (functionTestableState.isRunningFailingSuitesState.isInProgress &&
122
+ functionTestableState.failingSuites.includes(suite)) ||
123
+ functionTestableState.runningSuite === suite;
124
+ const isActive = functionTestableState.selectedTestSuite?.suite === suite;
125
+ const _testableResult = getTestableResultFromTestResults(results);
126
+ const testableResult = isRunning
127
+ ? TESTABLE_RESULT.IN_PROGRESS
128
+ : _testableResult;
129
+ const resultIcon = getTestableResultIcon(testableResult);
130
+ const onContextMenuOpen = (): void => setIsSelectedFromContextMenu(true);
131
+ const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
132
+ const add = (): void => {
133
+ // TODO
134
+ };
135
+ const _delete = (): void => {
136
+ functionTestableState.deleteTestSuite(suite);
137
+ };
138
+ const rename = (): void => {
139
+ functionTestableState.setRenameComponent(suite);
140
+ };
141
+ const runSuite = (): void => {
142
+ flowResult(functionTestableState.runSuite(suite)).catch(
143
+ functionTestableState.editorStore.applicationStore.alertUnhandledError,
144
+ );
145
+ };
146
+ return (
147
+ <ContextMenu
148
+ className={clsx(
149
+ 'testable-test-explorer__item',
150
+ {
151
+ 'testable-test-explorer__item--selected-from-context-menu':
152
+ !isActive && isSelectedFromContextMenu,
153
+ },
154
+ { 'testable-test-explorer__item--active': isActive },
155
+ )}
156
+ disabled={isReadOnly}
157
+ content={
158
+ <FunctionTestableContextMenu
159
+ addName="Suite"
160
+ add={add}
161
+ _delete={_delete}
162
+ rename={rename}
163
+ />
164
+ }
165
+ menuProps={{ elevation: 7 }}
166
+ onOpen={onContextMenuOpen}
167
+ onClose={onContextMenuClose}
168
+ >
169
+ <button
170
+ className={clsx('testable-test-explorer__item__label')}
171
+ onClick={openSuite}
172
+ tabIndex={-1}
173
+ >
174
+ <div className="testable-test-explorer__item__label__icon">
175
+ {resultIcon}
176
+ </div>
177
+ <div className="testable-test-explorer__item__label__text">
178
+ {suite.id}
179
+ </div>
180
+ <div className="mapping-test-explorer__item__actions">
181
+ <button
182
+ className="mapping-test-explorer__item__action mapping-test-explorer__run-test-btn"
183
+ onClick={runSuite}
184
+ disabled={isRunning}
185
+ tabIndex={-1}
186
+ title={`Run ${suite.id}`}
187
+ >
188
+ {<PlayIcon />}
189
+ </button>
190
+ </div>
191
+ </button>
192
+ </ContextMenu>
193
+ );
194
+ },
195
+ );
196
+
197
+ const FunctionTestDataStateEditor = observer(
198
+ (props: {
199
+ functionTestSuiteState: FunctionTestSuiteState;
200
+ storeTestDataState: FunctionStoreTestDataState;
201
+ }) => {
202
+ const { functionTestSuiteState, storeTestDataState } = props;
203
+ const functionTestableState = functionTestSuiteState.functionTestableState;
204
+ const isReadOnly = functionTestableState.functionEditorState.isReadOnly;
205
+ const embeddedState = storeTestDataState.embeddedEditorState;
206
+ const currentData = embeddedState.embeddedData;
207
+ const isUsingReference = currentData instanceof DataElementReference;
208
+ const open = (): void => storeTestDataState.setDataElementModal(true);
209
+ const close = (): void => storeTestDataState.setDataElementModal(false);
210
+ const changeToUseMyOwn = (): void => {
211
+ if (isUsingReference) {
212
+ const newBare = returnUndefOnError(() =>
213
+ currentData.accept_EmbeddedDataVisitor(
214
+ new EmbeddedDataCreatorFromEmbeddedData(
215
+ functionTestableState.editorStore,
216
+ ),
217
+ ),
218
+ );
219
+ if (newBare) {
220
+ storeTestDataState.changeEmbeddedData(newBare);
221
+ }
222
+ }
223
+ };
224
+
225
+ const sharedDataHandler = (val: DataElement): void => {
226
+ const dataRef = new DataElementReference();
227
+ dataRef.dataElement = PackageableElementExplicitReference.create(val);
228
+ const dataElementValue = val.data;
229
+ let embeddedData: EmbeddedData = dataRef;
230
+ if (
231
+ currentData instanceof ModelStoreData &&
232
+ dataElementValue instanceof ExternalFormatData
233
+ ) {
234
+ const modelStoreVal = currentData.modelData?.[0];
235
+ if (modelStoreVal instanceof ModelEmbeddedData) {
236
+ const newModelEmbeddedData = new ModelEmbeddedData();
237
+ newModelEmbeddedData.model =
238
+ PackageableElementExplicitReference.create(
239
+ modelStoreVal.model.value,
240
+ );
241
+
242
+ newModelEmbeddedData.data = dataRef;
243
+ const modelStoreData = new ModelStoreData();
244
+ modelStoreData.modelData = [newModelEmbeddedData];
245
+ embeddedData = modelStoreData;
246
+ }
247
+ }
248
+ storeTestDataState.changeEmbeddedData(embeddedData);
249
+ };
250
+
251
+ const dataElements =
252
+ functionTestSuiteState.editorStore.graphManagerState.graph.dataElements;
253
+
254
+ const filter = (val: DataElement): boolean => {
255
+ const dataElementData = val.data;
256
+ if (currentData instanceof RelationalCSVData) {
257
+ if (dataElementData instanceof RelationalCSVData) {
258
+ return true;
259
+ }
260
+ return false;
261
+ } else if (currentData instanceof ModelStoreData) {
262
+ if (
263
+ dataElementData instanceof ExternalFormatData ||
264
+ dataElementData instanceof ModelStoreData
265
+ ) {
266
+ return true;
267
+ }
268
+ return false;
269
+ }
270
+ return true;
271
+ };
272
+ return (
273
+ <div className="service-test-data-editor">
274
+ <div className="service-test-suite-editor__header">
275
+ <div className="service-test-suite-editor__header__title">
276
+ <div className="service-test-suite-editor__header__title__label">
277
+ input data
278
+ </div>
279
+ </div>
280
+ <div className="panel__header__actions">
281
+ {isUsingReference ? (
282
+ <button
283
+ className="panel__header__action service-execution-editor__test-data__generate-btn"
284
+ onClick={changeToUseMyOwn}
285
+ disabled={!isUsingReference}
286
+ title="Use own data"
287
+ tabIndex={-1}
288
+ >
289
+ <div className="service-execution-editor__test-data__generate-btn__label">
290
+ <div className="service-execution-editor__test-data__generate-btn__label__title">
291
+ Own Data
292
+ </div>
293
+ </div>
294
+ </button>
295
+ ) : (
296
+ <button
297
+ className="panel__header__action service-execution-editor__test-data__generate-btn"
298
+ onClick={open}
299
+ title="Use Shared Data via Defined Data Element"
300
+ disabled={!dataElements.length}
301
+ tabIndex={-1}
302
+ >
303
+ <div className="service-execution-editor__test-data__generate-btn__label">
304
+ <div className="service-execution-editor__test-data__generate-btn__label__title">
305
+ Shared Data
306
+ </div>
307
+ </div>
308
+ </button>
309
+ )}
310
+ </div>
311
+ </div>
312
+
313
+ {storeTestDataState.dataElementModal && (
314
+ <SharedDataElementModal
315
+ isReadOnly={false}
316
+ editorStore={storeTestDataState.editorStore}
317
+ close={close}
318
+ filterBy={filter}
319
+ handler={sharedDataHandler}
320
+ />
321
+ )}
322
+ <EmbeddedDataEditor
323
+ isReadOnly={isReadOnly}
324
+ embeddedDataEditorState={storeTestDataState.embeddedEditorState}
325
+ />
326
+ </div>
327
+ );
328
+ },
329
+ );
330
+
331
+ const FunctionTestEditor = observer(
332
+ (props: { functionTestState: FunctionTestState }) => {
333
+ const { functionTestState } = props;
334
+ const mappingTest = functionTestState.test;
335
+ return (
336
+ <div className="service-test-editor panel">
337
+ <div className="panel mapping-testable-editor">
338
+ <div className="mapping-testable-editor__content">
339
+ <ResizablePanelGroup orientation="horizontal">
340
+ <ResizablePanel size={120}>
341
+ <div className="service-test-data-editor panel">
342
+ <div className="service-test-editor__setup__configuration">
343
+ <div className="panel__content__form__section">
344
+ <div className="panel__content__form__section__header__label">
345
+ Test Documentation
346
+ </div>
347
+ <textarea
348
+ className="panel__content__form__section__textarea mapping-testable-editor__doc__textarea"
349
+ spellCheck={false}
350
+ value={mappingTest.doc ?? ''}
351
+ onChange={(event) => {
352
+ atomicTest_setDoc(
353
+ mappingTest,
354
+ event.target.value ? event.target.value : undefined,
355
+ );
356
+ }}
357
+ />
358
+ </div>
359
+ </div>
360
+ </div>
361
+ </ResizablePanel>
362
+ <ResizablePanelSplitter>
363
+ <ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
364
+ </ResizablePanelSplitter>
365
+ <ResizablePanel>
366
+ {functionTestState.selectedAsertionState && (
367
+ <TestAssertionEditor
368
+ testAssertionState={functionTestState.selectedAsertionState}
369
+ />
370
+ )}
371
+ </ResizablePanel>
372
+ </ResizablePanelGroup>
373
+ </div>
374
+ </div>
375
+ </div>
376
+ );
377
+ },
378
+ );
379
+
380
+ const FunctionTestItem = observer(
381
+ (props: {
382
+ suiteState: FunctionTestSuiteState;
383
+ functionTestState: FunctionTestState;
384
+ }) => {
385
+ const { functionTestState, suiteState } = props;
386
+ const mappingTest = functionTestState.test;
387
+ const isRunning = functionTestState.runningTestAction.isInProgress;
388
+ const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] =
389
+ useState(false);
390
+ const isReadOnly =
391
+ suiteState.functionTestableState.functionEditorState.isReadOnly;
392
+ const openTest = (): void => suiteState.changeTest(mappingTest);
393
+ const isActive = suiteState.selectTestState?.test === mappingTest;
394
+ const _testableResult = getTestableResultFromTestResult(
395
+ functionTestState.testResultState.result,
396
+ );
397
+
398
+ const testableResult = isRunning
399
+ ? TESTABLE_RESULT.IN_PROGRESS
400
+ : _testableResult;
401
+ const resultIcon = getTestableResultIcon(testableResult);
402
+ const onContextMenuOpen = (): void => setIsSelectedFromContextMenu(true);
403
+ const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
404
+ const add = (): void => {
405
+ // TODO
406
+ };
407
+ const _delete = (): void => {
408
+ suiteState.deleteTest(mappingTest);
409
+ };
410
+
411
+ const rename = (): void => {
412
+ // suiteState.mappingTestableState.setRenameComponent(mappingTest);
413
+ };
414
+ const runTest = (): void => {
415
+ flowResult(functionTestState.runTest()).catch(
416
+ functionTestState.editorStore.applicationStore.alertUnhandledError,
417
+ );
418
+ };
419
+ return (
420
+ <ContextMenu
421
+ className={clsx(
422
+ 'testable-test-explorer__item',
423
+ {
424
+ 'testable-test-explorer__item--selected-from-context-menu':
425
+ !isActive && isSelectedFromContextMenu,
426
+ },
427
+ { 'testable-test-explorer__item--active': isActive },
428
+ )}
429
+ disabled={isReadOnly}
430
+ content={
431
+ <FunctionTestableContextMenu
432
+ addName="Test"
433
+ add={add}
434
+ _delete={_delete}
435
+ rename={rename}
436
+ />
437
+ }
438
+ menuProps={{ elevation: 7 }}
439
+ onOpen={onContextMenuOpen}
440
+ onClose={onContextMenuClose}
441
+ >
442
+ <button
443
+ className={clsx('testable-test-explorer__item__label')}
444
+ onClick={openTest}
445
+ tabIndex={-1}
446
+ >
447
+ <div className="testable-test-explorer__item__label__icon">
448
+ {resultIcon}
449
+ </div>
450
+ <div className="testable-test-explorer__item__label__text">
451
+ {mappingTest.id}
452
+ </div>
453
+ <div className="mapping-test-explorer__item__actions">
454
+ <button
455
+ className="mapping-test-explorer__item__action mapping-test-explorer__run-test-btn"
456
+ onClick={runTest}
457
+ disabled={functionTestState.runningTestAction.isInProgress}
458
+ tabIndex={-1}
459
+ title={`Run ${functionTestState.test.id}`}
460
+ >
461
+ {<PlayIcon />}
462
+ </button>
463
+ </div>
464
+ </button>
465
+ </ContextMenu>
466
+ );
467
+ },
468
+ );
469
+
470
+ const FunctionTestSuiteEditor = observer(
471
+ (props: { functionTestSuiteState: FunctionTestSuiteState }) => {
472
+ const { functionTestSuiteState } = props;
473
+ const dataState = functionTestSuiteState.dataState;
474
+ const editorStore = functionTestSuiteState.editorStore;
475
+ const selectedTestState = functionTestSuiteState.selectTestState;
476
+ const addTest = (): void => {
477
+ // TODO
478
+ };
479
+ const runTests = (): void => {
480
+ flowResult(functionTestSuiteState.runSuite()).catch(
481
+ editorStore.applicationStore.alertUnhandledError,
482
+ );
483
+ };
484
+ const runFailingTests = (): void => {
485
+ flowResult(functionTestSuiteState.runFailingTests()).catch(
486
+ editorStore.applicationStore.alertUnhandledError,
487
+ );
488
+ };
489
+
490
+ const addStoreTestData = (): void => {
491
+ // mappingTestableDataState.setShowModal(true);
492
+ };
493
+
494
+ const renderMappingTestEditor = (): React.ReactNode => {
495
+ if (selectedTestState) {
496
+ return <FunctionTestEditor functionTestState={selectedTestState} />;
497
+ } else if (!functionTestSuiteState.suite.tests.length) {
498
+ return (
499
+ <BlankPanelPlaceholder
500
+ text="Add Function Test"
501
+ onClick={addTest}
502
+ clickActionType="add"
503
+ tooltipText="Click to add function test"
504
+ />
505
+ );
506
+ }
507
+ return null;
508
+ };
509
+ return (
510
+ <ResizablePanelGroup orientation="horizontal">
511
+ <ResizablePanel size={300} minSize={28}>
512
+ <div className="service-test-data-editor panel">
513
+ {functionTestSuiteState.dataState.dataHolder.testData?.length ? (
514
+ <>
515
+ {dataState.selectedDataState && (
516
+ <FunctionTestDataStateEditor
517
+ functionTestSuiteState={functionTestSuiteState}
518
+ storeTestDataState={dataState.selectedDataState}
519
+ />
520
+ )}
521
+ </>
522
+ ) : (
523
+ <BlankPanelPlaceholder
524
+ text="Add Store Test Data"
525
+ onClick={addStoreTestData}
526
+ clickActionType="add"
527
+ tooltipText="Click to add store test data"
528
+ />
529
+ )}
530
+ {/* {mappingTestableDataState.showNewModal && (
531
+ <CreateStoreTestDataModal mappingTestState={mappingTestState} />
532
+ )} */}
533
+ </div>
534
+ </ResizablePanel>
535
+ <ResizablePanelSplitter>
536
+ <ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
537
+ </ResizablePanelSplitter>
538
+ <ResizablePanel minSize={56}>
539
+ <ResizablePanelGroup orientation="vertical">
540
+ <ResizablePanel size={200} minSize={28}>
541
+ <div className="binding-editor__header">
542
+ <div className="binding-editor__header__title">
543
+ <div className="panel__header__title__content">Tests</div>
544
+ </div>
545
+ <div className="panel__header__actions">
546
+ <button
547
+ className="panel__header__action testable-test-explorer__play__all__icon"
548
+ tabIndex={-1}
549
+ onClick={runTests}
550
+ title="Run All Tests"
551
+ >
552
+ <RunAllIcon />
553
+ </button>
554
+ <button
555
+ className="panel__header__action testable-test-explorer__play__all__icon"
556
+ tabIndex={-1}
557
+ onClick={runFailingTests}
558
+ title="Run All Failing Tests"
559
+ >
560
+ <RunErrorsIcon />
561
+ </button>
562
+ <button
563
+ className="panel__header__action"
564
+ tabIndex={-1}
565
+ onClick={addTest}
566
+ title="Add Mapping Test"
567
+ >
568
+ <PlusIcon />
569
+ </button>
570
+ </div>
571
+ </div>
572
+ <PanelContent>
573
+ {functionTestSuiteState.testStates.map((test) => (
574
+ <FunctionTestItem
575
+ key={test.uuid}
576
+ functionTestState={test}
577
+ suiteState={functionTestSuiteState}
578
+ />
579
+ ))}
580
+ {/* {mappingTestSuiteState.showCreateModal && (
581
+ <CreateTestModal mappingSuiteState={mappingTestSuiteState} />
582
+ )} */}
583
+ </PanelContent>
584
+ </ResizablePanel>
585
+ <ResizablePanelSplitter>
586
+ <ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
587
+ </ResizablePanelSplitter>
588
+ <ResizablePanel minSize={28}>
589
+ {renderMappingTestEditor()}
590
+ </ResizablePanel>
591
+ </ResizablePanelGroup>
592
+ </ResizablePanel>
593
+ </ResizablePanelGroup>
594
+ );
595
+ },
596
+ );
597
+
598
+ export const FunctionTestableEditor = observer(
599
+ (props: { functionTestableState: FunctionTestableState }) => {
600
+ const { functionTestableState } = props;
601
+ const suites = functionTestableState.function.tests;
602
+ const functionEditorState = functionTestableState.functionEditorState;
603
+ const isReadOnly = functionEditorState.isReadOnly;
604
+ const selectedSuiteState = functionTestableState.selectedTestSuite;
605
+ // use effect
606
+ useEffect(() => {
607
+ functionTestableState.init();
608
+ }, [functionTestableState]);
609
+
610
+ const runSuites = (): void => {
611
+ functionTestableState.runTestable();
612
+ };
613
+
614
+ const runFailingTests = (): void => {
615
+ functionTestableState.runAllFailingSuites();
616
+ };
617
+ const addSuite = (): void => {
618
+ // TODO
619
+ };
620
+
621
+ const renderSuiteState = (): React.ReactNode => {
622
+ if (selectedSuiteState) {
623
+ return (
624
+ <FunctionTestSuiteEditor
625
+ functionTestSuiteState={selectedSuiteState}
626
+ />
627
+ );
628
+ } else if (!suites.length) {
629
+ return (
630
+ <BlankPanelPlaceholder
631
+ text="Add Test Suite"
632
+ onClick={addSuite}
633
+ clickActionType="add"
634
+ tooltipText="Click to add test suite"
635
+ />
636
+ );
637
+ }
638
+ return null;
639
+ };
640
+
641
+ const renameTestingComponent = (val: string): void => {
642
+ functionTestableState.renameTestableComponent(val);
643
+ };
644
+ useApplicationNavigationContext(
645
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.MAPPING_EDITOR_TEST,
646
+ );
647
+
648
+ return (
649
+ <div className="service-test-suite-editor panel">
650
+ <div className="service-test-suite-editor">
651
+ <ResizablePanelGroup orientation="vertical">
652
+ <ResizablePanel size={200} minSize={28}>
653
+ <div className="binding-editor__header">
654
+ <div className="binding-editor__header__title">
655
+ <div className="panel__header__title__content">
656
+ Test Suites
657
+ </div>
658
+ </div>
659
+
660
+ <div className="panel__header__actions">
661
+ <button
662
+ className="panel__header__action testable-test-explorer__play__all__icon"
663
+ tabIndex={-1}
664
+ onClick={runSuites}
665
+ title="Run All Suites"
666
+ >
667
+ <RunAllIcon />
668
+ </button>
669
+ <button
670
+ className="panel__header__action testable-test-explorer__play__all__icon"
671
+ tabIndex={-1}
672
+ onClick={runFailingTests}
673
+ title="Run All Failing Tests"
674
+ >
675
+ <RunErrorsIcon />
676
+ </button>
677
+ <button
678
+ className="panel__header__action"
679
+ tabIndex={-1}
680
+ onClick={addSuite}
681
+ title="Add Function Suite"
682
+ >
683
+ <PlusIcon />
684
+ </button>
685
+ </div>
686
+ </div>
687
+ <PanelContent>
688
+ {suites.map((suite) => (
689
+ <FunctionTestSuiteItem
690
+ key={suite.id}
691
+ functionTestableState={functionTestableState}
692
+ suite={suite}
693
+ />
694
+ ))}
695
+ {!suites.length && (
696
+ <BlankPanelPlaceholder
697
+ text="Add Test Suite"
698
+ onClick={addSuite}
699
+ clickActionType="add"
700
+ tooltipText="Click to add test suite"
701
+ />
702
+ )}
703
+ </PanelContent>
704
+ {!suites.length && (
705
+ <BlankPanelPlaceholder
706
+ disabled={functionEditorState.isReadOnly}
707
+ onClick={addSuite}
708
+ text="Add a Test Suite"
709
+ clickActionType="add"
710
+ tooltipText="Click to add a new function test suite"
711
+ />
712
+ )}
713
+ </ResizablePanel>
714
+ <ResizablePanelSplitter>
715
+ <ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
716
+ </ResizablePanelSplitter>
717
+ <ResizablePanel minSize={56}>
718
+ <div className="panel mapping-testable-editorr">
719
+ <div className="mapping-testable-editor__content">
720
+ {renderSuiteState()}
721
+ </div>
722
+ </div>
723
+ </ResizablePanel>
724
+ </ResizablePanelGroup>
725
+ {/* {mappingTestableState.createSuiteState && (
726
+ <CreateTestSuiteModal
727
+ creatorState={mappingTestableState.createSuiteState}
728
+ />
729
+ )} */}
730
+ {functionTestableState.testableComponentToRename && (
731
+ <RenameModal
732
+ val={functionTestableState.testableComponentToRename.id}
733
+ isReadOnly={isReadOnly}
734
+ showModal={true}
735
+ closeModal={(): void =>
736
+ functionTestableState.setRenameComponent(undefined)
737
+ }
738
+ setValue={(val: string): void => renameTestingComponent(val)}
739
+ errorMessageFunc={(_val: string | undefined) =>
740
+ validateTestableId(_val, undefined)
741
+ }
742
+ />
743
+ )}
744
+ </div>
745
+ </div>
746
+ );
747
+ },
748
+ );