UNPKG

@finos/legend-studio

Version:
157 lines 15.2 kB
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-state/element-editor-state/mapping/MappingTestState.js'; import { MappingEditorState } from '../../../../stores/editor-state/element-editor-state/mapping/MappingEditorState.js'; import { clsx, ContextMenu, ProgressBar, VerticalAlignBottomIcon, AddIcon, PlayIcon, EmptyCircleIcon, TimesCircleIcon, CheckCircleIcon, CircleNotchIcon, PlusIcon, EmptyStopCircleIcon, ExclamationCircleIcon, } from '@finos/legend-art'; import { CORE_DND_TYPE, } from '../../../../stores/shared/DnDUtil.js'; import { ClassMappingSelectorModal } from './MappingExecutionBuilder.js'; import { flowResult } from 'mobx'; import { Randomizer } from '@finos/legend-shared'; import { useEditorStore } from '../../EditorStoreProvider.js'; import { useApplicationStore } from '@finos/legend-application'; import { SetImplementation } from '@finos/legend-graph'; const addTestPromps = [ `Let's add some test!`, `"A test a day keeps the QA away"`, ]; 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("div", { ref: ref, className: "mapping-test-explorer__context-menu", children: [mappingTestState && (_jsx("div", { className: "mapping-test-explorer__context-menu__item", onClick: runMappingTest, children: "Run" })), mappingTestState && mappingTestState.result !== TEST_RESULT.NONE && (_jsx("div", { className: "mapping-test-explorer__context-menu__item", onClick: viewTestResult, children: "View Result" })), mappingTestState && (_jsx("div", { className: "mapping-test-explorer__context-menu__item", onClick: editTest, children: "Edit" })), mappingTestState && (_jsx("div", { className: "mapping-test-explorer__context-menu__item", onClick: toggleSkipTest, children: mappingTestState.isSkipped ? 'Unskip' : 'Skip' })), !isReadOnly && mappingTestState && (_jsx("div", { className: "mapping-test-explorer__context-menu__item", onClick: removeMappingTest, children: "Delete" })), !isReadOnly && !mappingTestState && (_jsx("div", { className: "mapping-test-explorer__context-menu__item", 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.getCurrentEditorState(MappingEditorState); const openTest = applicationStore.guardUnhandledError(() => flowResult(mappingEditorState.openTest(testState.test))); const runTest = applicationStore.guardUnhandledError(() => flowResult(testState.runTest())); 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: _jsx("button", { className: "mapping-test-explorer__item__action mapping-test-explorer__run-test-btn", onClick: runTest, disabled: testState.isRunningTest || 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.getCurrentEditorState(MappingEditorState); const runAllTests = applicationStore.guardUnhandledError(() => flowResult(mappingEditorState.runTests())); // all test run report summary const numberOfTests = mappingEditorState.mappingTestStates.length; const numberOfTestsPassed = mappingEditorState.mappingTestStates.filter((testState) => testState.result === TEST_RESULT.PASSED).length; const numberOfTestsFailed = mappingEditorState.mappingTestStates.filter((testState) => testState.result === TEST_RESULT.FAILED || testState.result === TEST_RESULT.ERROR).length; const numberOfTestSkipped = mappingEditorState.mappingTestStates.filter((testState) => testState.isSkipped).length; const percentageTestRun = Math.floor((mappingEditorState.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 }, dropRef] = 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 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("div", { className: "panel 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: [_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.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: _jsxs("div", { ref: dropRef, className: clsx('mapping-test-explorer__content', { 'mapping-test-explorer__content--dnd-over': isDragOver && !isReadOnly, }), children: [Boolean(mappingEditorState.mappingTestStates.length) && mappingEditorState.mappingTestStates .slice() .map((testState) => (_jsx(MappingTestExplorer, { testState: testState, isReadOnly: isReadOnly }, testState.test._UUID))), !isReadOnly && !mappingEditorState.mappingTestStates.length && (_jsxs("div", { className: "mapping-test-explorer__content mapping-test-explorer__content__adder", onClick: showClassMappingSelectorModal, children: [_jsx("div", { className: "mapping-test-explorer__content__adder__text", children: new Randomizer().getRandomItemInCollection(addTestPromps) ?? addTestPromps[0] }), _jsxs("div", { className: "mapping-test-explorer__content__adder__action", children: [_jsx(VerticalAlignBottomIcon, { className: "mapping-test-explorer__content__adder__action__dnd-icon" }), _jsx(AddIcon, { className: "mapping-test-explorer__content__adder__action__add-icon" })] })] }))] }) }), openClassMappingSelectorModal && (_jsx(ClassMappingSelectorModal, { mappingEditorState: mappingEditorState, hideClassMappingSelectorModal: hideClassMappingSelectorModal, changeClassMapping: changeClassMapping }))] })); }); //# sourceMappingURL=MappingTestsExplorer.js.map