@finos/legend-application-studio
Version:
Legend Studio application core
151 lines • 14.9 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
* Copyright (c) 2020-present, Goldman Sachs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useState, useCallback, forwardRef } from 'react';
import { observer } from 'mobx-react-lite';
import { useDrop } from 'react-dnd';
import { MAPPING_TEST_EDITOR_TAB_TYPE, TEST_RESULT, } from '../../../../stores/editor/editor-state/element-editor-state/mapping/legacy/DEPRECATED__MappingTestState.js';
import { clsx, ContextMenu, ProgressBar, PlayIcon, EmptyCircleIcon, TimesCircleIcon, CheckCircleIcon, CircleNotchIcon, PlusIcon, EmptyStopCircleIcon, ExclamationCircleIcon, PauseCircleIcon, PanelDropZone, MenuContent, MenuContentItem, Panel, WarningIcon, } from '@finos/legend-art';
import { CORE_DND_TYPE, } from '../../../../stores/editor/utils/DnDUtils.js';
import { ClassMappingSelectorModal } from './MappingExecutionBuilder.js';
import { flowResult } from 'mobx';
import { useEditorStore } from '../../EditorStoreProvider.js';
import { useApplicationStore } from '@finos/legend-application';
import { SetImplementation } from '@finos/legend-graph';
import { MappingEditorState } from '../../../../stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js';
export const MappingTestExplorerContextMenu = observer(forwardRef(function MappingTestExplorerContextMenu(props, ref) {
const { mappingTestState, isReadOnly, showCreateNewTestModal } = props;
const applicationStore = useApplicationStore();
const runMappingTest = () => {
if (mappingTestState) {
flowResult(mappingTestState.runTest()).catch(applicationStore.alertUnhandledError);
}
};
const removeMappingTest = () => {
if (mappingTestState) {
flowResult(mappingTestState.mappingEditorState.deleteTest(mappingTestState.test)).catch(applicationStore.alertUnhandledError);
}
};
const toggleSkipTest = () => mappingTestState?.toggleSkipTest();
const viewTestResult = () => {
if (mappingTestState) {
mappingTestState.mappingEditorState.openTest(mappingTestState.test, MAPPING_TEST_EDITOR_TAB_TYPE.RESULT);
}
};
const editTest = () => {
if (mappingTestState) {
mappingTestState.mappingEditorState.openTest(mappingTestState.test, MAPPING_TEST_EDITOR_TAB_TYPE.SETUP);
}
};
return (_jsxs(MenuContent, { ref: ref, children: [mappingTestState && (_jsx(MenuContentItem, { onClick: runMappingTest, children: "Run" })), mappingTestState && mappingTestState.result !== TEST_RESULT.NONE && (_jsx(MenuContentItem, { onClick: viewTestResult, children: "View Result" })), mappingTestState && (_jsx(MenuContentItem, { onClick: editTest, children: "Edit" })), mappingTestState && (_jsx(MenuContentItem, { onClick: toggleSkipTest, children: mappingTestState.isSkipped ? 'Unskip' : 'Skip' })), !isReadOnly && mappingTestState && (_jsx(MenuContentItem, { onClick: removeMappingTest, children: "Delete" })), !isReadOnly && !mappingTestState && showCreateNewTestModal && (_jsx(MenuContentItem, { onClick: showCreateNewTestModal, children: "Create new test" }))] }));
}));
export const MappingTestStatusIndicator = (props) => {
const { testState } = props;
if (testState.isSkipped) {
return (_jsx("div", { title: "Test is skipped", className: "mapping-test-status-indicator mapping-test-status-indicator--skipped", children: _jsx(EmptyStopCircleIcon, {}) }));
}
if (testState.isRunningTest) {
return (_jsx("div", { title: "Test is running", className: "mapping-test-status-indicator mapping-test-status-indicator--in-progress", children: _jsx(CircleNotchIcon, {}) }));
}
return (_jsxs(_Fragment, { children: [testState.result === TEST_RESULT.NONE && (_jsx("div", { title: "Test did not run", className: "mapping-test-status-indicator mapping-test-status-indicator--none", children: _jsx(EmptyCircleIcon, {}) })), testState.result === TEST_RESULT.ERROR && (_jsx("div", { title: "Test failed due to error", className: "mapping-test-status-indicator mapping-test-status-indicator--error", children: _jsx(TimesCircleIcon, {}) })), testState.result === TEST_RESULT.FAILED && (_jsx("div", { title: "Test failed assertion", className: "mapping-test-status-indicator mapping-test-status-indicator--failed", children: _jsx(ExclamationCircleIcon, {}) })), testState.result === TEST_RESULT.PASSED && (_jsx("div", { title: "Test passed", className: "mapping-test-status-indicator mapping-test-status-indicator--passed", children: _jsx(CheckCircleIcon, {}) }))] }));
};
export const MappingTestExplorer = observer((props) => {
const { isReadOnly, testState } = props;
const editorStore = useEditorStore();
const applicationStore = useApplicationStore();
const mappingEditorState = editorStore.tabManagerState.getCurrentEditorState(MappingEditorState);
const openTest = applicationStore.guardUnhandledError(() => flowResult(mappingEditorState.openTest(testState.test)));
const runTest = applicationStore.guardUnhandledError(() => flowResult(testState.runTest()));
const cancelTest = () => {
testState.setIsRunningTest(false);
testState.setTestRunPromise(undefined);
};
const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] = useState(false);
const onContextMenuOpen = () => setIsSelectedFromContextMenu(true);
const onContextMenuClose = () => setIsSelectedFromContextMenu(false);
const isActive = mappingEditorState.currentTabState === testState;
return (_jsx(ContextMenu, { content: _jsx(MappingTestExplorerContextMenu, { mappingTestState: testState, isReadOnly: isReadOnly }), menuProps: { elevation: 7 }, onOpen: onContextMenuOpen, onClose: onContextMenuClose, children: _jsxs("div", { className: clsx('mapping-test-explorer__item', {
'mapping-explorer__item--selected-from-context-menu': !isActive && isSelectedFromContextMenu,
}, { 'mapping-test-explorer__item--active': isActive }), children: [_jsxs("button", { className: "mapping-test-explorer__item__label", onClick: openTest, tabIndex: -1, children: [_jsx("div", { className: "mapping-test-explorer__item__label__icon mapping-test-explorer__test-result-indicator__container", children: _jsx(MappingTestStatusIndicator, { testState: testState }) }), _jsx("div", { className: "mapping-test-explorer__item__label__text", children: testState.test.name }), testState.result !== TEST_RESULT.NONE && (_jsxs("div", { className: "mapping-test-explorer__item__run-time", children: [testState.runTime, "ms"] }))] }), _jsx("div", { className: "mapping-test-explorer__item__actions", children: testState.isRunningTest ? (_jsx("button", { className: "mapping-test-explorer__item__action mapping-test-explorer__stop-test-btn", onClick: cancelTest, disabled: testState.mappingEditorState.isRunningAllTests, tabIndex: -1, title: `Stop ${testState.test.name}`, children: _jsx(PauseCircleIcon, {}) })) : (_jsx("button", { className: "mapping-test-explorer__item__action mapping-test-explorer__run-test-btn", onClick: runTest, disabled: testState.mappingEditorState.isRunningAllTests, tabIndex: -1, title: `Run ${testState.test.name}`, children: _jsx(PlayIcon, {}) })) })] }) }));
});
export const MappingTestsExplorer = observer((props) => {
const { isReadOnly } = props;
const editorStore = useEditorStore();
const applicationStore = useApplicationStore();
const mappingEditorState = editorStore.tabManagerState.getCurrentEditorState(MappingEditorState);
const runAllTests = applicationStore.guardUnhandledError(() => flowResult(mappingEditorState.runTests()));
// all test run report summary
const numberOfTests = mappingEditorState.DEPRECATED_mappingTestStates.length;
const numberOfTestsPassed = mappingEditorState.DEPRECATED_mappingTestStates.filter((testState) => testState.result === TEST_RESULT.PASSED).length;
const numberOfTestsFailed = mappingEditorState.DEPRECATED_mappingTestStates.filter((testState) => testState.result === TEST_RESULT.FAILED ||
testState.result === TEST_RESULT.ERROR).length;
const numberOfTestSkipped = mappingEditorState.DEPRECATED_mappingTestStates.filter((testState) => testState.isSkipped).length;
const percentageTestRun = Math.floor((mappingEditorState.DEPRECATED_mappingTestStates.filter((testState) => testState.result !== TEST_RESULT.NONE).length /
numberOfTests) *
100);
let testReportSummary = '';
switch (mappingEditorState.testSuiteResult) {
case TEST_RESULT.NONE:
testReportSummary = mappingEditorState.isRunningAllTests
? `Running ${numberOfTests} tests...`
: 'No tests run!';
break;
case TEST_RESULT.FAILED:
testReportSummary = `${numberOfTestsFailed} of ${numberOfTests} failed`;
break;
case TEST_RESULT.PASSED:
testReportSummary =
numberOfTestsPassed === numberOfTests
? `All ${numberOfTests} passed`
: `${numberOfTestsPassed} of ${numberOfTests} passed`;
break;
default:
break;
}
// Drag and Drop
const handleDrop = useCallback((item) => {
if (isReadOnly) {
return;
}
if (item.data instanceof SetImplementation) {
flowResult(mappingEditorState.createNewTest(item.data)).catch(applicationStore.alertUnhandledError);
}
}, [applicationStore.alertUnhandledError, isReadOnly, mappingEditorState]);
const [{ isDragOver }, dropConnector] = useDrop(() => ({
accept: CORE_DND_TYPE.MAPPING_EXPLORER_CLASS_MAPPING,
drop: (item) => handleDrop(item),
collect: (monitor) => ({
isDragOver: monitor.isOver({ shallow: true }),
}),
}), [handleDrop]);
// Class mapping selector
const [openClassMappingSelectorModal, setOpenClassMappingSelectorModal] = useState(false);
const openMigrationtool = () => mappingEditorState.openMigrationTool();
const showClassMappingSelectorModal = () => setOpenClassMappingSelectorModal(true);
const hideClassMappingSelectorModal = () => setOpenClassMappingSelectorModal(false);
const changeClassMapping = useCallback((setImplementation) => {
if (setImplementation) {
flowResult(mappingEditorState.createNewTest(setImplementation)).catch(applicationStore.alertUnhandledError);
hideClassMappingSelectorModal();
}
}, [applicationStore, mappingEditorState]);
return (_jsxs(Panel, { className: "mapping-test-explorer", children: [_jsxs("div", { className: "panel__header", title: testReportSummary, children: [_jsxs("div", { className: "mapping-test-explorer__header__info", children: [_jsx("div", { className: "panel__header__title", children: _jsxs("div", { className: "panel__header__title__content mapping-test-explorer__header__report", children: [_jsxs("div", { className: "mapping-test-explorer__header__report__overview", children: [_jsxs("div", { className: "mapping-test-explorer__header__report__overview__stat mapping-test-explorer__header__report__overview__stat--total", children: [numberOfTests, " total"] }), _jsxs("div", { className: "mapping-test-explorer__header__report__overview__stat mapping-test-explorer__header__report__overview__stat--passed", children: [numberOfTestsPassed, " passed"] }), _jsxs("div", { className: "mapping-test-explorer__header__report__overview__stat mapping-test-explorer__header__report__overview__stat--failed", children: [numberOfTestsFailed, " failed"] }), Boolean(numberOfTestSkipped) && (_jsxs("div", { className: "mapping-test-explorer__header__report__overview__stat mapping-test-explorer__header__report__overview__stat--skipped", children: [numberOfTestSkipped, " skipped"] }))] }), mappingEditorState.testSuiteResult !== TEST_RESULT.NONE && (_jsxs("div", { className: "mapping-test-explorer__header__report__time", children: [mappingEditorState.allTestRunTime, "ms"] }))] }) }), _jsxs("div", { className: "panel__header__actions", children: [Boolean(mappingEditorState.mapping.test.length) && (_jsx("button", { className: "panel__header__action", onClick: openMigrationtool, disabled: isReadOnly, tabIndex: -1, title: "Please migrate to new mapping test framework", children: _jsx(WarningIcon, {}) })), _jsx("button", { className: "panel__header__action", onClick: showClassMappingSelectorModal, disabled: isReadOnly, tabIndex: -1, title: "Add Test", children: _jsx(PlusIcon, {}) }), _jsx("button", { className: "panel__header__action", onClick: runAllTests, disabled: !mappingEditorState.DEPRECATED_mappingTestStates.length ||
mappingEditorState.isRunningAllTests, tabIndex: -1, title: "Run All Tests", children: _jsx(PlayIcon, {}) })] })] }), _jsx("div", { className: "mapping-test-explorer__header__status", children: _jsx(ProgressBar, { className: `mapping-test-explorer__header__progress-bar mapping-test-explorer__header__progress-bar--${mappingEditorState.testSuiteResult.toLowerCase()}`, classes: {
bar: `mapping-test-explorer__header__progress-bar__bar mapping-test-explorer__header__progress-bar__bar--${mappingEditorState.testSuiteResult.toLowerCase()}`,
}, variant: "determinate", value: percentageTestRun }) })] }), _jsx(ContextMenu, { className: "panel__content", disabled: isReadOnly, content: _jsx(MappingTestExplorerContextMenu, { isReadOnly: isReadOnly, showCreateNewTestModal: showClassMappingSelectorModal }), menuProps: { elevation: 7 }, children: _jsx(PanelDropZone, { isDragOver: isDragOver && !isReadOnly, dropTargetConnector: dropConnector, children: _jsx("div", { className: "mapping-test-explorer__content", children: Boolean(mappingEditorState.DEPRECATED_mappingTestStates.length) &&
mappingEditorState.DEPRECATED_mappingTestStates.slice().map((testState) => (_jsx(MappingTestExplorer, { testState: testState, isReadOnly: isReadOnly }, testState.test._UUID))) }) }) }), openClassMappingSelectorModal && (_jsx(ClassMappingSelectorModal, { mappingEditorState: mappingEditorState, hideClassMappingSelectorModal: hideClassMappingSelectorModal, changeClassMapping: changeClassMapping }))] }));
});
//# sourceMappingURL=MappingTestsExplorer.js.map