UNPKG

@finos/legend-studio

Version:
179 lines 23.1 kB
import { jsx as _jsx, jsxs as _jsxs } 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 { BasicValueSpecificationEditor } from '@finos/legend-application'; import { ContextMenu, PlusIcon, ResizablePanel, ResizablePanelGroup, ResizablePanelSplitter, ResizablePanelSplitterLine, MenuContent, MenuContentItem, clsx, FlaskIcon, RunAllIcon, RunErrorsIcon, CheckCircleIcon, TimesCircleIcon, TestTubeIcon, CustomSelectorInput, Dialog, RefreshIcon, TimesIcon, } from '@finos/legend-art'; import { PRIMITIVE_TYPE } from '@finos/legend-graph'; import { filterByType, guaranteeNonNullable, prettyCONSTName, } from '@finos/legend-shared'; import { flowResult } from 'mobx'; import { observer } from 'mobx-react-lite'; import { forwardRef, useEffect, useState } from 'react'; import { ServiceValueSpecificationTestParameterState, } from '../../../../../stores/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js'; import { TESTABLE_TEST_TAB } from '../../../../../stores/editor-state/element-editor-state/testable/TestableEditorState.js'; import { atomicTest_setId, testAssertion_setId, } from '../../../../../stores/graphModifier/Testable_GraphModifierHelper.js'; import { getTestableResultFromTestResult, TESTABLE_RESULT, } from '../../../../../stores/sidebar-state/testable/GlobalTestRunnerState.js'; import { getTestableResultIcon } from '../../../side-bar/testable/GlobalTestRunner.js'; import { TestAssertionEditor } from '../../testable/TestAssertionEditor.js'; import { RenameModal } from './ServiceTestableEditor.js'; const TestAssertionContextMenu = observer(forwardRef(function TestContainerContextMenu(props, ref) { const { serviceTestState, testAssertionState } = props; const rename = () => serviceTestState.setAssertionToRename(testAssertionState.assertion); const remove = () => serviceTestState.deleteAssertion(testAssertionState); const add = () => serviceTestState.addAssertion(); return (_jsxs(MenuContent, { ref: ref, children: [_jsx(MenuContentItem, { onClick: rename, children: "Rename" }), _jsx(MenuContentItem, { onClick: remove, children: "Delete" }), _jsx(MenuContentItem, { onClick: add, children: "Create a new assert" })] })); })); const TestAssertionItem = observer((props) => { const { testAssertionEditorState, isReadOnly, serviceTestState } = props; const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] = useState(false); const isRunning = serviceTestState.runningTestAction.isInProgress; const testAssertion = testAssertionEditorState.assertion; const isActive = serviceTestState.selectedAsertionState?.assertion === testAssertion; const _testableResult = testAssertionEditorState.assertionResultState.result; const testableResult = isRunning ? TESTABLE_RESULT.IN_PROGRESS : _testableResult; const resultIcon = getTestableResultIcon(testableResult); const openTestAssertion = () => serviceTestState.openAssertion(testAssertion); const onContextMenuOpen = () => setIsSelectedFromContextMenu(true); const onContextMenuClose = () => setIsSelectedFromContextMenu(false); return (_jsx(ContextMenu, { className: clsx('testable-test-assertion-explorer__item', { 'testable-test-assertion-explorer__item--selected-from-context-menu': !isActive && isSelectedFromContextMenu, }, { 'testable-test-assertion-explorer__item--active': isActive }), disabled: isReadOnly, content: _jsx(TestAssertionContextMenu, { serviceTestState: serviceTestState, testAssertionState: testAssertionEditorState }), menuProps: { elevation: 7 }, onOpen: onContextMenuOpen, onClose: onContextMenuClose, children: _jsxs("button", { className: clsx('testable-test-assertion-explorer__item__label'), onClick: openTestAssertion, tabIndex: -1, children: [_jsx("div", { className: "testable-test-assertion-explorer__item__label__icon testable-test-assertion-explorer__test-result-indicator__container", children: resultIcon }), _jsx("div", { className: "testable-test-assertion-explorer__item__label__text", children: testAssertion.id })] }) })); }); export const NewParameterModal = observer((props) => { const { setupState, isReadOnly } = props; const currentOption = { value: setupState.newParameterValueName, label: setupState.newParameterValueName, }; const options = setupState.newParamOptions; const closeModal = () => setupState.setShowNewParameterModal(false); const handleSubmit = () => setupState.addParameterValue(); const onChange = (val) => { if (val === null) { setupState.setNewParameterValueName(''); } else if (val.value !== setupState.newParameterValueName) { setupState.setNewParameterValueName(val.value); } }; return (_jsx(Dialog, { open: setupState.showNewParameterModal, onClose: closeModal, classes: { container: 'search-modal__container' }, PaperProps: { classes: { root: 'search-modal__inner-container' } }, children: _jsxs("form", { onSubmit: handleSubmit, className: "modal modal--dark search-modal", children: [_jsx("div", { className: "modal__title", children: "New Test Parameter Value " }), _jsx(CustomSelectorInput, { className: "panel__content__form__section__dropdown", options: options, onChange: onChange, value: currentOption, escapeClearsValue: true, darkMode: true, disable: isReadOnly }), _jsx("div", { className: "search-modal__actions", children: _jsx("button", { className: "btn btn--dark", disabled: isReadOnly, children: "Add" }) })] }) })); }); const ServiceTestParameterEditor = observer((props) => { const { serviceTestState, paramState, isReadOnly } = props; const setupState = serviceTestState.setupState; const paramIsRequired = paramState.varExpression.multiplicity.lowerBound > 0; return (_jsxs("div", { className: "panel__content__form__section", children: [_jsxs("div", { className: "panel__content__form__section__header__label", children: [paramState.parameterValue.name, _jsx("button", { className: clsx('type-tree__node__type__label', {}), tabIndex: -1, title: paramState.varExpression.genericType?.value.rawType.name ?? '', children: paramState.varExpression.genericType?.value.rawType.name ?? 'unknown' })] }), _jsxs("div", { className: "service-test-editor__setup__parameter__value", children: [_jsx(BasicValueSpecificationEditor, { valueSpecification: paramState.valueSpec, setValueSpecification: (val) => { paramState.updateValueSpecification(val); }, graph: setupState.editorStore.graphManagerState.graph, typeCheckOption: { expectedType: paramState.varExpression.genericType?.value.rawType ?? setupState.editorStore.graphManagerState.graph.getPrimitiveType(PRIMITIVE_TYPE.STRING), }, className: "query-builder__parameters__value__editor", resetValue: () => { paramState.resetValueSpec(); } }), _jsx("div", { className: "service-test-editor__setup__parameter__value__actions", children: _jsx("button", { className: "btn--icon btn--dark btn--sm", disabled: isReadOnly || paramIsRequired, onClick: () => setupState.removeParamValueState(paramState), tabIndex: -1, title: paramIsRequired ? 'Parameter Required' : 'Remove Parameter', children: _jsx(TimesIcon, {}) }) })] })] }, paramState.parameterValue.name)); }); const ServiceTestSetupEditor = observer((props) => { const { serviceTestState } = props; const setupState = serviceTestState.setupState; const test = serviceTestState.test; const format = test.serializationFormat; const selectedSerializationFormat = setupState.getSelectedFormatOption(); const options = setupState.options; const isReadOnly = serviceTestState.suiteState.testableState.serviceEditorState.isReadOnly; const onChange = (val) => { if (val === null) { setupState.changeSerializationFormat(undefined); } else if (val.value !== format) { setupState.changeSerializationFormat(val.value); } }; const addParameter = () => { setupState.setShowNewParameterModal(true); }; const generateParameterValues = () => { setupState.generateTestParameterValues(); }; useEffect(() => { setupState.syncWithQuery(); }, [setupState]); return (_jsxs("div", { className: "panel service-test-editor", children: [_jsx("div", { className: "panel__header", children: _jsx("div", { className: "service-test-suite-editor__header__title", children: _jsx("div", { className: "service-test-suite-editor__header__title__label", children: "setup" }) }) }), _jsx("div", { className: "service-test-editor__content", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { size: 200, minSize: 28, children: _jsxs("div", { className: "service-test-data-editor panel", children: [_jsx("div", { className: "service-test-suite-editor__header", children: _jsx("div", { className: "service-test-suite-editor__header__title", children: _jsx("div", { className: "service-test-suite-editor__header__title__label", children: "serialization" }) }) }), _jsx("div", { className: "service-test-editor__setup__serialization", children: _jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Serialization Format" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: "format to serialize execution result" }), _jsx(CustomSelectorInput, { className: "panel__content__form__section__dropdown", options: options, onChange: onChange, value: selectedSerializationFormat, isClearable: true, escapeClearsValue: true, darkMode: true, disable: isReadOnly })] }) })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { minSize: 56, children: _jsxs("div", { className: "service-test-data-editor panel", children: [_jsxs("div", { className: "service-test-suite-editor__header", children: [_jsx("div", { className: "service-test-suite-editor__header__title", children: _jsx("div", { className: "service-test-suite-editor__header__title__label", children: "parameters" }) }), _jsxs("div", { className: "panel__header__actions", children: [_jsx("button", { className: "panel__header__action service-execution-editor__test-data__generate-btn", onClick: generateParameterValues, title: "Generate test parameter values", tabIndex: -1, children: _jsxs("div", { className: "service-execution-editor__test-data__generate-btn__label", children: [_jsx(RefreshIcon, { className: "service-execution-editor__test-data__generate-btn__label__icon" }), _jsx("div", { className: "service-execution-editor__test-data__generate-btn__label__title", children: "Generate" })] }) }), _jsx("button", { className: "panel__header__action", tabIndex: -1, disabled: !setupState.newParamOptions.length, onClick: addParameter, title: "Add Parameter Value", children: _jsx(PlusIcon, {}) })] })] }), _jsx("div", { className: "service-test-editor__setup__parameters", children: setupState.parameterValueStates .filter(filterByType(ServiceValueSpecificationTestParameterState)) .map((paramState) => (_jsx(ServiceTestParameterEditor, { isReadOnly: isReadOnly, paramState: paramState, serviceTestState: serviceTestState }, paramState.uuid))) }), setupState.showNewParameterModal && (_jsx(NewParameterModal, { setupState: setupState, isReadOnly: false }))] }) })] }) })] })); }); const TestAssertionsEditor = observer((props) => { const { serviceTestState } = props; const isReadOnly = serviceTestState.suiteState.testableState.serviceEditorState.isReadOnly; const editorStore = serviceTestState.editorStore; const addAssertion = () => serviceTestState.addAssertion(); const renameAssertion = (val) => testAssertion_setId(guaranteeNonNullable(serviceTestState.assertionToRename), val); const runTest = () => { flowResult(serviceTestState.runTest()).catch(editorStore.applicationStore.alertUnhandledError); }; return (_jsxs("div", { className: "panel service-test-editor", children: [_jsx("div", { className: "service-test-suite-editor__header", children: _jsx("div", { className: "service-test-suite-editor__header__title", children: _jsx("div", { className: "service-test-suite-editor__header__title__label service-test-suite-editor__header__title__label--assertions", children: "assertions" }) }) }), _jsx("div", { className: "service-test-editor__content", children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsxs(ResizablePanel, { minSize: 100, size: 200, children: [_jsxs("div", { className: "binding-editor__header", children: [_jsxs("div", { className: "binding-editor__header__title", children: [_jsxs("div", { className: "testable-test-assertion-explorer__header__summary", children: [_jsx("div", { className: "testable-test-assertion-explorer__header__summary__icon testable-test-assertion-explorer__header__summary__icon--assertion", children: _jsx(TestTubeIcon, {}) }), _jsx("div", { children: serviceTestState.assertionCount })] }), _jsxs("div", { className: "testable-test-assertion-explorer__header__summary", children: [_jsx("div", { className: "testable-test-assertion-explorer__header__summary__icon testable-test-assertion-explorer__header__summary__icon--passed", children: _jsx(CheckCircleIcon, {}) }), _jsx("div", { children: serviceTestState.assertionPassed })] }), _jsxs("div", { className: "testable-test-assertion-explorer__header__summary", children: [_jsx("div", { className: "testable-test-assertion-explorer__header__summary__icon testable-test-assertion-explorer__header__summary__icon--failed", children: _jsx(TimesCircleIcon, {}) }), _jsx("div", { children: serviceTestState.assertionFailed })] })] }), _jsxs("div", { className: "panel__header__actions", children: [_jsx("button", { className: "panel__header__action testable-test-explorer__play__all__icon", tabIndex: -1, onClick: runTest, title: "Run All Assertions", children: _jsx(RunAllIcon, {}) }), _jsx("button", { className: "panel__header__action", tabIndex: -1, onClick: addAssertion, title: "Add Test Assertion", children: _jsx(PlusIcon, {}) })] })] }), _jsx("div", { children: serviceTestState.assertionEditorStates.map((assertionState) => (_jsx(TestAssertionItem, { serviceTestState: serviceTestState, testAssertionEditorState: assertionState, isReadOnly: serviceTestState.suiteState.testableState .serviceEditorState.isReadOnly }, assertionState.assertion.id))) }), serviceTestState.assertionToRename && (_jsx(RenameModal, { val: serviceTestState.assertionToRename.id, isReadOnly: isReadOnly, showModal: true, closeModal: () => serviceTestState.setAssertionToRename(undefined), setValue: renameAssertion }))] }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { children: serviceTestState.selectedAsertionState && (_jsx(TestAssertionEditor, { testAssertionState: serviceTestState.selectedAsertionState })) })] }) })] })); }); const ServiceTestEditor = observer((props) => { const { serviceTestState } = props; const selectedTab = serviceTestState.selectedTab; return (_jsxs("div", { className: "service-test-editor panel", children: [_jsx("div", { className: "panel__header", children: _jsx("div", { className: "panel__header service-test-editor__header--with-tabs", children: _jsx("div", { className: "uml-element-editor__tabs", children: Object.values(TESTABLE_TEST_TAB).map((tab) => (_jsx("div", { onClick: () => serviceTestState.setSelectedTab(tab), className: clsx('service-test-editor__tab', { 'service-test-editor__tab--active': tab === serviceTestState.selectedTab, }), children: prettyCONSTName(tab) }, tab))) }) }) }), _jsxs("div", { className: "service-test-editor", children: [selectedTab === TESTABLE_TEST_TAB.SETUP && (_jsx(ServiceTestSetupEditor, { serviceTestState: serviceTestState })), selectedTab === TESTABLE_TEST_TAB.ASSERTIONS && (_jsx(TestAssertionsEditor, { serviceTestState: serviceTestState }))] })] })); }); const ServiceTestDataContextMenu = observer(forwardRef(function TestContainerContextMenu(props, ref) { const { suiteState, serviceTestState } = props; const addTest = () => { suiteState.addServiceTest(); }; const remove = () => suiteState.deleteTest(serviceTestState); const rename = () => suiteState.setTestToRename(serviceTestState.test); return (_jsxs(MenuContent, { ref: ref, children: [_jsx(MenuContentItem, { onClick: rename, children: "Rename" }), _jsx(MenuContentItem, { onClick: remove, children: "Delete" }), _jsx(MenuContentItem, { onClick: addTest, children: "Add test" })] })); })); const ServiceTestItem = observer((props) => { const { serviceTestState, suiteState } = props; const serviceTest = serviceTestState.test; const isRunning = serviceTestState.runningTestAction.isInProgress; const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] = useState(false); const isReadOnly = suiteState.testableState.serviceEditorState.isReadOnly; const openTest = () => suiteState.setSelectedTestState(serviceTestState); const isActive = suiteState.selectedTestState?.test === serviceTest; const _testableResult = getTestableResultFromTestResult(serviceTestState.testResultState.result); const testableResult = isRunning ? TESTABLE_RESULT.IN_PROGRESS : _testableResult; const resultIcon = getTestableResultIcon(testableResult); const onContextMenuOpen = () => setIsSelectedFromContextMenu(true); const onContextMenuClose = () => setIsSelectedFromContextMenu(false); return (_jsx(ContextMenu, { className: clsx('testable-test-explorer__item', { 'testable-test-explorer__item--selected-from-context-menu': !isActive && isSelectedFromContextMenu, }, { 'testable-test-explorer__item--active': isActive }), disabled: isReadOnly, content: _jsx(ServiceTestDataContextMenu, { suiteState: suiteState, serviceTestState: serviceTestState }), menuProps: { elevation: 7 }, onOpen: onContextMenuOpen, onClose: onContextMenuClose, children: _jsxs("button", { className: clsx('testable-test-explorer__item__label'), onClick: openTest, tabIndex: -1, children: [_jsx("div", { className: "testable-test-explorer__item__label__icon", children: resultIcon }), _jsx("div", { className: "testable-test-explorer__item__label__text", children: serviceTest.id })] }) })); }); export const ServiceTestsEditor = observer((props) => { const { suiteState } = props; const editorStore = suiteState.editorStore; const isReadOnly = suiteState.testableState.serviceEditorState.isReadOnly; const addTest = () => suiteState.addServiceTest(); const runSuite = () => { flowResult(suiteState.runSuite()).catch(editorStore.applicationStore.alertUnhandledError); }; const runFailingTests = () => { flowResult(suiteState.runFailingTests()).catch(editorStore.applicationStore.alertUnhandledError); }; const renameTest = (val) => atomicTest_setId(guaranteeNonNullable(suiteState.testToRename), val); return (_jsxs("div", { className: "panel service-test-editor", children: [_jsx("div", { className: "service-test-suite-editor__header", children: _jsx("div", { className: "service-test-suite-editor__header__title", children: _jsx("div", { className: "service-test-suite-editor__header__title__label service-test-suite-editor__header__title__label--tests", children: "tests" }) }) }), _jsx("div", { className: "service-test-editor__content", children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsxs(ResizablePanel, { minSize: 100, size: 300, children: [_jsxs("div", { className: "binding-editor__header", children: [_jsxs("div", { className: "binding-editor__header__title", children: [_jsxs("div", { className: "testable-test-assertion-explorer__header__summary", children: [_jsx("div", { className: "testable-test-assertion-explorer__header__summary__icon testable-test-assertion-explorer__header__summary__icon--test", children: _jsx(FlaskIcon, {}) }), _jsx("div", { children: suiteState.testCount })] }), _jsxs("div", { className: "testable-test-assertion-explorer__header__summary", children: [_jsx("div", { className: "testable-test-assertion-explorer__header__summary__icon testable-test-assertion-explorer__header__summary__icon--passed", children: _jsx(CheckCircleIcon, {}) }), _jsx("div", { children: suiteState.testPassed })] }), _jsxs("div", { className: "testable-test-assertion-explorer__header__summary", children: [_jsx("div", { className: "testable-test-assertion-explorer__header__summary__icon testable-test-assertion-explorer__header__summary__icon--failed", children: _jsx(TimesCircleIcon, {}) }), _jsx("div", { children: suiteState.testFailed })] })] }), _jsxs("div", { className: "panel__header__actions", children: [_jsx("button", { className: "panel__header__action testable-test-explorer__play__all__icon", tabIndex: -1, onClick: runSuite, title: "Run Suite Tests", children: _jsx(RunAllIcon, {}) }), _jsx("button", { className: "panel__header__action testable-test-explorer__play__all__icon", tabIndex: -1, onClick: runFailingTests, title: "Run All Failing Tests", children: _jsx(RunErrorsIcon, {}) }), _jsx("button", { className: "panel__header__action", tabIndex: -1, onClick: addTest, title: "Add Service Test", children: _jsx(PlusIcon, {}) })] })] }), _jsx("div", { children: suiteState.testStates.map((testState) => (_jsx(ServiceTestItem, { suiteState: suiteState, serviceTestState: testState }, testState.test.id))) }), suiteState.testToRename && (_jsx(RenameModal, { val: suiteState.testToRename.id, isReadOnly: isReadOnly, showModal: true, closeModal: () => suiteState.setTestToRename(undefined), setValue: renameTest }))] }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { children: suiteState.selectedTestState && (_jsx(ServiceTestEditor, { serviceTestState: suiteState.selectedTestState })) })] }) })] })); }); //# sourceMappingURL=ServiceTestsEditor.js.map