@finos/legend-application-studio 28.11.3 → 28.12.0
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/__lib__/LegendStudioUserDataHelper.d.ts +24 -0
- package/lib/__lib__/LegendStudioUserDataHelper.d.ts.map +1 -0
- package/lib/__lib__/LegendStudioUserDataHelper.js +29 -0
- package/lib/__lib__/LegendStudioUserDataHelper.js.map +1 -0
- package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.js +0 -1
- package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
- package/lib/components/editor/side-bar/testable/GlobalTestRunner.d.ts +6 -0
- package/lib/components/editor/side-bar/testable/GlobalTestRunner.d.ts.map +1 -1
- package/lib/components/editor/side-bar/testable/GlobalTestRunner.js +87 -44
- package/lib/components/editor/side-bar/testable/GlobalTestRunner.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/sidebar-state/testable/GlobalTestRunnerState.d.ts +17 -8
- package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.d.ts.map +1 -1
- package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.js +70 -22
- package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.js.map +1 -1
- package/package.json +4 -4
- package/src/__lib__/LegendStudioUserDataHelper.ts +43 -0
- package/src/application/LegendStudioApplicationConfig.ts +0 -1
- package/src/components/editor/side-bar/testable/GlobalTestRunner.tsx +278 -143
- package/src/stores/editor/sidebar-state/testable/GlobalTestRunnerState.ts +102 -28
- package/tsconfig.json +1 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
import type { UserDataService } from '@finos/legend-application';
|
2
|
+
import { returnUndefOnError } from '@finos/legend-shared';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Copyright (c) 2020-present, Goldman Sachs
|
6
|
+
*
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
* you may not use this file except in compliance with the License.
|
9
|
+
* You may obtain a copy of the License at
|
10
|
+
*
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
*
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
* See the License for the specific language governing permissions and
|
17
|
+
* limitations under the License.
|
18
|
+
*/
|
19
|
+
export enum LEGEND_STUDIO_USER_DATA_KEY {
|
20
|
+
GLOBAL_TEST_RUNNER_SHOW_DEPENDENCIES = 'studio-editor.global-test-runner-showDependencyPanel',
|
21
|
+
}
|
22
|
+
|
23
|
+
export class LegendStudioUserDataHelper {
|
24
|
+
static globalTestRunner_getShowDependencyPanel(
|
25
|
+
service: UserDataService,
|
26
|
+
): boolean | undefined {
|
27
|
+
return returnUndefOnError(() =>
|
28
|
+
service.getBooleanValue(
|
29
|
+
LEGEND_STUDIO_USER_DATA_KEY.GLOBAL_TEST_RUNNER_SHOW_DEPENDENCIES,
|
30
|
+
),
|
31
|
+
);
|
32
|
+
}
|
33
|
+
|
34
|
+
static globalTestRunner_setShowDependencyPanel(
|
35
|
+
service: UserDataService,
|
36
|
+
val: boolean,
|
37
|
+
): void {
|
38
|
+
service.persistValue(
|
39
|
+
LEGEND_STUDIO_USER_DATA_KEY.GLOBAL_TEST_RUNNER_SHOW_DEPENDENCIES,
|
40
|
+
val,
|
41
|
+
);
|
42
|
+
}
|
43
|
+
}
|
@@ -95,7 +95,6 @@ class LegendStudioApplicationCoreOptions {
|
|
95
95
|
TEMPORARY__serviceRegistrationConfig: ServiceRegistrationEnvironmentConfig[] =
|
96
96
|
[];
|
97
97
|
|
98
|
-
// TODO- change it to false
|
99
98
|
/**
|
100
99
|
* This flag can be removed when the support for end-to-end workflow is official
|
101
100
|
*/
|
@@ -42,6 +42,14 @@ import {
|
|
42
42
|
Panel,
|
43
43
|
PanelHeader,
|
44
44
|
OffIcon,
|
45
|
+
DropdownMenu,
|
46
|
+
MenuContentItemIcon,
|
47
|
+
CheckIcon,
|
48
|
+
MenuContentItemLabel,
|
49
|
+
MoreVerticalIcon,
|
50
|
+
ResizablePanelGroup,
|
51
|
+
ResizablePanel,
|
52
|
+
ResizablePanelSplitter,
|
45
53
|
} from '@finos/legend-art';
|
46
54
|
import {
|
47
55
|
AssertFail,
|
@@ -56,7 +64,7 @@ import {
|
|
56
64
|
prettyCONSTName,
|
57
65
|
} from '@finos/legend-shared';
|
58
66
|
import { observer } from 'mobx-react-lite';
|
59
|
-
import { forwardRef, useEffect, useState } from 'react';
|
67
|
+
import React, { forwardRef, useEffect, useState } from 'react';
|
60
68
|
import { TEST_RUNNER_TABS } from '../../../../stores/editor/EditorConfig.js';
|
61
69
|
import {
|
62
70
|
type TestableExplorerTreeNodeData,
|
@@ -195,7 +203,7 @@ const TestFailViewer = observer(
|
|
195
203
|
>
|
196
204
|
<Modal darkMode={true} className="editor-modal">
|
197
205
|
<PanelLoadingIndicator
|
198
|
-
isLoading={globalTestRunnerState.
|
206
|
+
isLoading={globalTestRunnerState.isDispatchingOwnProjectAction}
|
199
207
|
/>
|
200
208
|
<ModalHeader title={id} />
|
201
209
|
<ModalBody>
|
@@ -256,17 +264,12 @@ const TestableExplorerContextMenu = observer(
|
|
256
264
|
return (
|
257
265
|
<MenuContent data-testid={LEGEND_STUDIO_TEST_ID.EXPLORER_CONTEXT_MENU}>
|
258
266
|
<MenuContentItem
|
259
|
-
disabled={globalTestRunnerState.
|
267
|
+
disabled={globalTestRunnerState.isDispatchingOwnProjectAction}
|
260
268
|
onClick={runTest}
|
261
269
|
>
|
262
270
|
Run
|
263
271
|
</MenuContentItem>
|
264
|
-
<MenuContentItem
|
265
|
-
disabled={globalTestRunnerState.isDispatchingAction}
|
266
|
-
onClick={visitTestable}
|
267
|
-
>
|
268
|
-
Open Testable
|
269
|
-
</MenuContentItem>
|
272
|
+
<MenuContentItem onClick={visitTestable}>Open Testable</MenuContentItem>
|
270
273
|
{error &&
|
271
274
|
(error instanceof TestError || error instanceof AssertFail) && (
|
272
275
|
<MenuContentItem onClick={(): void => viewError(error)}>
|
@@ -297,11 +300,13 @@ const TestableTreeNodeContainer: React.FC<
|
|
297
300
|
globalTestRunnerState: GlobalTestRunnerState;
|
298
301
|
testableState: TestableState;
|
299
302
|
treeData: TreeData<TestableExplorerTreeNodeData>;
|
303
|
+
isDependency?: boolean | undefined;
|
300
304
|
}
|
301
305
|
>
|
302
306
|
> = (props) => {
|
303
307
|
const { node, level, stepPaddingInRem, onNodeSelect } = props;
|
304
|
-
const { treeData, testableState, globalTestRunnerState } =
|
308
|
+
const { treeData, testableState, globalTestRunnerState, isDependency } =
|
309
|
+
props.innerProps;
|
305
310
|
const editorStore = useEditorStore();
|
306
311
|
const results = testableState.results;
|
307
312
|
const expandIcon =
|
@@ -326,7 +331,10 @@ const TestableTreeNodeContainer: React.FC<
|
|
326
331
|
const resultIcon = getTestableResultIcon(
|
327
332
|
getNodeTestableResult(
|
328
333
|
node,
|
329
|
-
|
334
|
+
isDependency
|
335
|
+
? testableState.globalTestRunnerState.isRunningDependencyTests
|
336
|
+
.isInProgress
|
337
|
+
: testableState.globalTestRunnerState.isRunningTests.isInProgress,
|
330
338
|
results,
|
331
339
|
),
|
332
340
|
);
|
@@ -420,44 +428,96 @@ const TestableTreeNodeContainer: React.FC<
|
|
420
428
|
);
|
421
429
|
};
|
422
430
|
|
423
|
-
|
424
|
-
// - Handle Multi Execution Test Results
|
425
|
-
// - Add `Visit Test` to open test editors when Testable Editors are complete
|
426
|
-
export const GlobalTestRunner = observer(
|
431
|
+
export const TestablePanelRunner = observer(
|
427
432
|
(props: { globalTestRunnerState: GlobalTestRunnerState }) => {
|
428
|
-
const
|
429
|
-
const
|
430
|
-
|
431
|
-
|
432
|
-
const
|
433
|
-
|
434
|
-
);
|
435
|
-
|
436
|
-
const extractTestRunnerTabConfigurations = editorStore.pluginManager
|
437
|
-
.getApplicationPlugins()
|
438
|
-
.flatMap(
|
439
|
-
(plugin) => plugin.getExtraTestRunnerViewConfigurations?.() ?? [],
|
440
|
-
)
|
441
|
-
.filter((configuration) => configuration.renderer(editorStore));
|
442
|
-
|
443
|
-
const testRunnerTabs = (Object.values(TEST_RUNNER_TABS) as string[])
|
444
|
-
.map((e) => ({
|
445
|
-
value: e,
|
446
|
-
label: prettyCONSTName(e),
|
447
|
-
}))
|
448
|
-
.concat(
|
449
|
-
extractTestRunnerTabConfigurations.map((config) => ({
|
450
|
-
value: config.key,
|
451
|
-
label: config.title,
|
452
|
-
})),
|
453
|
-
);
|
454
|
-
|
455
|
-
const changeTab = (tab: string): void => {
|
456
|
-
setSelectedTab(tab);
|
433
|
+
const { globalTestRunnerState } = props;
|
434
|
+
const isDispatchingAction =
|
435
|
+
globalTestRunnerState.isDispatchingOwnProjectAction;
|
436
|
+
const showDependencyPanel = globalTestRunnerState.showDependencyPanel;
|
437
|
+
const toggleShowDependencyTests = (): void => {
|
438
|
+
globalTestRunnerState.setShowDependencyPanel(!showDependencyPanel);
|
457
439
|
};
|
440
|
+
const runAllTests = (): GeneratorFn<void> =>
|
441
|
+
globalTestRunnerState.runAllTests();
|
442
|
+
const reset = (): void => globalTestRunnerState.initOwnTestables(true);
|
443
|
+
|
444
|
+
//
|
445
|
+
const runDependencyTests = (): GeneratorFn<void> =>
|
446
|
+
globalTestRunnerState.runDependenciesTests();
|
447
|
+
const isDispatchingDependencyAction =
|
448
|
+
globalTestRunnerState.isDispatchingDependencyAction;
|
458
449
|
|
459
450
|
const renderTestables = (): React.ReactNode => (
|
460
451
|
<>
|
452
|
+
<PanelHeader>
|
453
|
+
<div className="panel__header__title">
|
454
|
+
<div className="panel__header__title__content">TESTABLES</div>
|
455
|
+
</div>
|
456
|
+
<div className="panel__header__actions side-bar__header__actions">
|
457
|
+
<button
|
458
|
+
className={clsx(
|
459
|
+
'panel__header__action side-bar__header__action global-test-runner__refresh-btn',
|
460
|
+
{
|
461
|
+
'global-test-runner__refresh-btn--loading':
|
462
|
+
isDispatchingAction,
|
463
|
+
},
|
464
|
+
)}
|
465
|
+
disabled={isDispatchingAction}
|
466
|
+
onClick={reset}
|
467
|
+
tabIndex={-1}
|
468
|
+
title="Reset"
|
469
|
+
>
|
470
|
+
<RefreshIcon />
|
471
|
+
</button>
|
472
|
+
<button
|
473
|
+
className="panel__header__action side-bar__header__action global-test-runner__refresh-btn"
|
474
|
+
disabled={isDispatchingAction}
|
475
|
+
onClick={runAllTests}
|
476
|
+
tabIndex={-1}
|
477
|
+
title="Run All Tests"
|
478
|
+
>
|
479
|
+
<PlayIcon />
|
480
|
+
</button>
|
481
|
+
<div
|
482
|
+
className="global-test-runner__count"
|
483
|
+
data-testid={
|
484
|
+
LEGEND_STUDIO_TEST_ID.SIDEBAR_PANEL_HEADER__CHANGES_COUNT
|
485
|
+
}
|
486
|
+
>
|
487
|
+
{globalTestRunnerState.testableStates?.length ?? '0'}
|
488
|
+
</div>
|
489
|
+
|
490
|
+
<DropdownMenu
|
491
|
+
className="panel__header__action"
|
492
|
+
title="Show Options Menu..."
|
493
|
+
content={
|
494
|
+
<MenuContent>
|
495
|
+
<MenuContentItem onClick={toggleShowDependencyTests}>
|
496
|
+
<MenuContentItemIcon>
|
497
|
+
{showDependencyPanel ? <CheckIcon /> : null}
|
498
|
+
</MenuContentItemIcon>
|
499
|
+
<MenuContentItemLabel>
|
500
|
+
Show from dependency tests
|
501
|
+
</MenuContentItemLabel>
|
502
|
+
</MenuContentItem>
|
503
|
+
</MenuContent>
|
504
|
+
}
|
505
|
+
menuProps={{
|
506
|
+
anchorOrigin: {
|
507
|
+
vertical: 'bottom',
|
508
|
+
horizontal: 'left',
|
509
|
+
},
|
510
|
+
transformOrigin: {
|
511
|
+
vertical: 'top',
|
512
|
+
horizontal: 'left',
|
513
|
+
},
|
514
|
+
elevation: 7,
|
515
|
+
}}
|
516
|
+
>
|
517
|
+
<MoreVerticalIcon className="query-builder__icon__more-options" />
|
518
|
+
</DropdownMenu>
|
519
|
+
</div>
|
520
|
+
</PanelHeader>
|
461
521
|
{(globalTestRunnerState.testableStates ?? []).map((testableState) => {
|
462
522
|
const onNodeSelect = (node: TestableExplorerTreeNodeData): void => {
|
463
523
|
testableState.onTreeNodeSelect(node, testableState.treeData);
|
@@ -492,116 +552,191 @@ export const GlobalTestRunner = observer(
|
|
492
552
|
</>
|
493
553
|
);
|
494
554
|
|
495
|
-
|
496
|
-
|
497
|
-
|
555
|
+
const renderDependenciesTestables = (): React.ReactNode => (
|
556
|
+
<>
|
557
|
+
<PanelHeader>
|
558
|
+
<div className="panel__header__title">
|
559
|
+
<div className="panel__header__title__content">
|
560
|
+
DEPENDENCY TESTABLES
|
561
|
+
</div>
|
562
|
+
</div>
|
563
|
+
<div className="panel__header__actions side-bar__header__actions">
|
564
|
+
<button
|
565
|
+
className="panel__header__action side-bar__header__action global-test-runner__refresh-btn"
|
566
|
+
disabled={isDispatchingDependencyAction}
|
567
|
+
onClick={runDependencyTests}
|
568
|
+
tabIndex={-1}
|
569
|
+
title="Run Dependency Tests"
|
570
|
+
>
|
571
|
+
<PlayIcon />
|
572
|
+
</button>
|
573
|
+
<div
|
574
|
+
className="global-test-runner__count"
|
575
|
+
data-testid={
|
576
|
+
LEGEND_STUDIO_TEST_ID.SIDEBAR_PANEL_HEADER__CHANGES_COUNT
|
577
|
+
}
|
578
|
+
>
|
579
|
+
{globalTestRunnerState.dependencyTestableStates?.length ?? '0'}
|
580
|
+
</div>
|
581
|
+
</div>
|
582
|
+
</PanelHeader>
|
583
|
+
{(globalTestRunnerState.dependencyTestableStates ?? []).map(
|
584
|
+
(testableState) => {
|
585
|
+
const onNodeSelect = (node: TestableExplorerTreeNodeData): void => {
|
586
|
+
testableState.onTreeNodeSelect(node, testableState.treeData);
|
587
|
+
};
|
588
|
+
const getChildNodes = (
|
589
|
+
node: TestableExplorerTreeNodeData,
|
590
|
+
): TestableExplorerTreeNodeData[] => {
|
591
|
+
if (node.childrenIds) {
|
592
|
+
return node.childrenIds
|
593
|
+
.map((id) => testableState.treeData.nodes.get(id))
|
594
|
+
.filter(isNonNullable);
|
595
|
+
}
|
596
|
+
return [];
|
597
|
+
};
|
598
|
+
return (
|
599
|
+
<TreeView
|
600
|
+
components={{
|
601
|
+
TreeNodeContainer: TestableTreeNodeContainer,
|
602
|
+
}}
|
603
|
+
key={testableState.uuid}
|
604
|
+
treeData={testableState.treeData}
|
605
|
+
onNodeSelect={onNodeSelect}
|
606
|
+
getChildNodes={getChildNodes}
|
607
|
+
innerProps={{
|
608
|
+
globalTestRunnerState,
|
609
|
+
testableState,
|
610
|
+
treeData: testableState.treeData,
|
611
|
+
isDependency: true,
|
612
|
+
}}
|
613
|
+
/>
|
614
|
+
);
|
615
|
+
},
|
616
|
+
)}
|
617
|
+
</>
|
618
|
+
);
|
498
619
|
|
499
|
-
|
500
|
-
|
620
|
+
return (
|
621
|
+
<Panel className="side-bar__panel">
|
622
|
+
{!showDependencyPanel && (
|
623
|
+
<PanelContent>{renderTestables()}</PanelContent>
|
624
|
+
)}
|
625
|
+
{showDependencyPanel && (
|
626
|
+
<ResizablePanelGroup>
|
627
|
+
<ResizablePanel>
|
628
|
+
<PanelContent>{renderTestables()}</PanelContent>
|
629
|
+
</ResizablePanel>
|
630
|
+
<ResizablePanelSplitter />
|
631
|
+
<ResizablePanel>
|
632
|
+
<PanelContent>{renderDependenciesTestables()}</PanelContent>
|
633
|
+
</ResizablePanel>
|
634
|
+
</ResizablePanelGroup>
|
635
|
+
)}
|
636
|
+
{globalTestRunnerState.failureViewing && (
|
637
|
+
<TestFailViewer
|
638
|
+
globalTestRunnerState={globalTestRunnerState}
|
639
|
+
failure={globalTestRunnerState.failureViewing}
|
640
|
+
/>
|
641
|
+
)}
|
642
|
+
</Panel>
|
643
|
+
);
|
644
|
+
},
|
645
|
+
);
|
646
|
+
|
647
|
+
// TODO:
|
648
|
+
// - Handle Multi Execution Test Results
|
649
|
+
export const GlobalTestRunner = observer(
|
650
|
+
(props: { globalTestRunnerState: GlobalTestRunnerState }) => {
|
651
|
+
const editorStore = useEditorStore();
|
652
|
+
const globalTestRunnerState = props.globalTestRunnerState;
|
653
|
+
const isDispatchingAction =
|
654
|
+
globalTestRunnerState.isDispatchingOwnProjectAction;
|
655
|
+
|
656
|
+
const [selectedTab, setSelectedTab] = useState(
|
657
|
+
TEST_RUNNER_TABS.TEST_RUNNER.valueOf(),
|
658
|
+
);
|
501
659
|
|
502
|
-
const
|
660
|
+
const extractTestRunnerTabConfigurations = editorStore.pluginManager
|
661
|
+
.getApplicationPlugins()
|
662
|
+
.flatMap(
|
663
|
+
(plugin) => plugin.getExtraTestRunnerViewConfigurations?.() ?? [],
|
664
|
+
)
|
665
|
+
.filter((configuration) => configuration.renderer(editorStore));
|
503
666
|
|
504
|
-
const
|
667
|
+
const testRunnerTabs = (Object.values(TEST_RUNNER_TABS) as string[])
|
668
|
+
.map((e) => ({
|
669
|
+
value: e,
|
670
|
+
label: prettyCONSTName(e),
|
671
|
+
}))
|
672
|
+
.concat(
|
673
|
+
extractTestRunnerTabConfigurations.map((config) => ({
|
674
|
+
value: config.key,
|
675
|
+
label: config.title,
|
676
|
+
})),
|
677
|
+
);
|
678
|
+
|
679
|
+
const changeTab = (tab: string): void => {
|
680
|
+
setSelectedTab(tab);
|
681
|
+
};
|
682
|
+
|
683
|
+
useEffect(() => {
|
684
|
+
editorStore.globalTestRunnerState.initOwnTestables();
|
685
|
+
}, [editorStore.globalTestRunnerState]);
|
686
|
+
|
687
|
+
const renderSelectedTab = (): React.ReactNode => {
|
505
688
|
if (selectedTab === TEST_RUNNER_TABS.TEST_RUNNER) {
|
506
689
|
return (
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
<div className="panel__header__title__content side-bar__header__title__content">
|
514
|
-
GLOBAL TEST RUNNER
|
515
|
-
</div>
|
516
|
-
</div>
|
517
|
-
<div className="panel__header__actions side-bar__header__actions">
|
518
|
-
<button
|
519
|
-
className={clsx(
|
520
|
-
'panel__header__action side-bar__header__action global-test-runner__refresh-btn',
|
521
|
-
{
|
522
|
-
'global-test-runner__refresh-btn--loading':
|
523
|
-
isDispatchingAction,
|
524
|
-
},
|
525
|
-
)}
|
526
|
-
disabled={isDispatchingAction}
|
527
|
-
onClick={reset}
|
528
|
-
tabIndex={-1}
|
529
|
-
title="Reset"
|
530
|
-
>
|
531
|
-
<RefreshIcon />
|
532
|
-
</button>
|
533
|
-
<button
|
534
|
-
className="panel__header__action side-bar__header__action global-test-runner__refresh-btn"
|
535
|
-
disabled={isDispatchingAction}
|
536
|
-
onClick={runAllTests}
|
537
|
-
tabIndex={-1}
|
538
|
-
title="Run All Tests"
|
539
|
-
>
|
540
|
-
<PlayIcon />
|
541
|
-
</button>
|
542
|
-
</div>
|
543
|
-
</PanelHeader>
|
544
|
-
<div className="panel__header__tabs panel__header__test__runner__tabs">
|
545
|
-
{testRunnerTabs.map((tab) => (
|
546
|
-
<div
|
547
|
-
key={tab.value}
|
548
|
-
onClick={() => changeTab(tab.value)}
|
549
|
-
className={clsx('panel__header__tab', {
|
550
|
-
['panel__header__tab--active']: tab.value === selectedTab,
|
551
|
-
})}
|
552
|
-
>
|
553
|
-
{tab.label}
|
554
|
-
</div>
|
555
|
-
))}
|
556
|
-
</div>
|
557
|
-
<PanelContent className="side-bar__content">
|
558
|
-
<PanelLoadingIndicator isLoading={isDispatchingAction} />
|
559
|
-
<Panel className="side-bar__panel">
|
560
|
-
<PanelHeader>
|
561
|
-
<div className="panel__header__title">
|
562
|
-
<div className="panel__header__title__content">
|
563
|
-
TESTABLES
|
564
|
-
</div>
|
565
|
-
</div>
|
566
|
-
<div
|
567
|
-
className="side-bar__panel__header__changes-count"
|
568
|
-
data-testid={
|
569
|
-
LEGEND_STUDIO_TEST_ID.SIDEBAR_PANEL_HEADER__CHANGES_COUNT
|
570
|
-
}
|
571
|
-
>
|
572
|
-
{globalTestRunnerState.testableStates?.length ?? '0'}
|
573
|
-
</div>
|
574
|
-
</PanelHeader>
|
575
|
-
<PanelContent>{renderTestables()}</PanelContent>
|
576
|
-
{globalTestRunnerState.failureViewing && (
|
577
|
-
<TestFailViewer
|
578
|
-
globalTestRunnerState={globalTestRunnerState}
|
579
|
-
failure={globalTestRunnerState.failureViewing}
|
580
|
-
/>
|
581
|
-
)}
|
582
|
-
</Panel>
|
583
|
-
</PanelContent>
|
584
|
-
</div>
|
690
|
+
<>
|
691
|
+
<PanelLoadingIndicator isLoading={isDispatchingAction} />
|
692
|
+
<TestablePanelRunner
|
693
|
+
globalTestRunnerState={globalTestRunnerState}
|
694
|
+
/>
|
695
|
+
</>
|
585
696
|
);
|
586
|
-
}
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
}
|
697
|
+
}
|
698
|
+
for (const testRunnerTabConfiguration of extractTestRunnerTabConfigurations) {
|
699
|
+
if (testRunnerTabConfiguration.key === selectedTab) {
|
700
|
+
return testRunnerTabConfiguration.renderer(editorStore);
|
591
701
|
}
|
592
|
-
return (
|
593
|
-
<UnsupportedEditorPanel
|
594
|
-
text="Can't display this tab"
|
595
|
-
isReadOnly={true}
|
596
|
-
/>
|
597
|
-
);
|
598
702
|
}
|
703
|
+
return (
|
704
|
+
<UnsupportedEditorPanel
|
705
|
+
text="Can't display this tab"
|
706
|
+
isReadOnly={true}
|
707
|
+
/>
|
708
|
+
);
|
599
709
|
};
|
600
710
|
|
601
711
|
return (
|
602
|
-
<
|
603
|
-
|
604
|
-
|
712
|
+
<div
|
713
|
+
data-testid={LEGEND_STUDIO_TEST_ID.TEST_RUNNER}
|
714
|
+
className="panel global-test-runner"
|
715
|
+
>
|
716
|
+
<PanelHeader className="panel__header side-bar__header">
|
717
|
+
<div className="panel__header__title global-test-runner__header__title">
|
718
|
+
<div className="panel__header__title__content side-bar__header__title__content">
|
719
|
+
GLOBAL TEST RUNNER
|
720
|
+
</div>
|
721
|
+
</div>
|
722
|
+
</PanelHeader>
|
723
|
+
<div className="panel__header__tabs panel__header__test__runner__tabs">
|
724
|
+
{testRunnerTabs.map((tab) => (
|
725
|
+
<div
|
726
|
+
key={tab.value}
|
727
|
+
onClick={() => changeTab(tab.value)}
|
728
|
+
className={clsx('panel__header__tab', {
|
729
|
+
['panel__header__tab--active']: tab.value === selectedTab,
|
730
|
+
})}
|
731
|
+
>
|
732
|
+
{tab.label}
|
733
|
+
</div>
|
734
|
+
))}
|
735
|
+
</div>
|
736
|
+
<PanelContent className="side-bar__content">
|
737
|
+
{renderSelectedTab()}
|
738
|
+
</PanelContent>
|
739
|
+
</div>
|
605
740
|
);
|
606
741
|
},
|
607
742
|
);
|