UNPKG

@finos/legend-application-studio

Version:
339 lines 13.7 kB
/** * 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 { AssertFail, TestExecuted, TestError, EqualToJson, ExternalFormatData, EqualToJsonAssertFail, MultiExecutionServiceTestResult, AssertPass, TestExecutionStatus, EqualTo, observe_ValueSpecification, } from '@finos/legend-graph'; import { ActionState, assertErrorThrown, ContentType, UnsupportedOperationError, assertTrue, isNonNullable, IllegalStateError, guaranteeNonNullable, guaranteeType, returnUndefOnError, } from '@finos/legend-shared'; import { action, flow, flowResult, makeObservable, observable } from 'mobx'; import { externalFormatData_setData } from '../../../../graph-modifier/DSL_Data_GraphModifierHelper.js'; import { getTestableResultFromAssertionStatus, TESTABLE_RESULT, } from '../../../sidebar-state/testable/GlobalTestRunnerState.js'; import { isTestPassing } from '../../../utils/TestableUtils.js'; import { equalTo_setExpected } from '../../../../graph-modifier/Testable_GraphModifierHelper.js'; export var TEST_ASSERTION_TAB; (function (TEST_ASSERTION_TAB) { TEST_ASSERTION_TAB["EXPECTED"] = "EXPECTED"; TEST_ASSERTION_TAB["RESULT"] = "RESULT"; })(TEST_ASSERTION_TAB || (TEST_ASSERTION_TAB = {})); export class TestAssertionStatusState { resultState; status; constructor(resultState, status) { this.resultState = resultState; this.status = status; } } export class AssertFailState extends TestAssertionStatusState { constructor(resultState, status) { super(resultState, status); this.status = status; makeObservable(this, { status: observable, }); } } export class EqualToAssertFailState extends AssertFailState { diffModal = false; constructor(resultState, status) { super(resultState, status); makeObservable(this, { diffModal: observable, setDiffModal: action, }); } setDiffModal(val) { this.diffModal = val; } } export class EqualToJsonAssertFailState extends AssertFailState { diffModal = false; constructor(resultState, status) { super(resultState, status); this.status = status; makeObservable(this, { diffModal: observable, setDiffModal: action, }); } setDiffModal(val) { this.diffModal = val; } } export class UnsupportedAssertionStatusState extends TestAssertionStatusState { } export class TestAssertionResultState { testResult; statusState; editorStore; assertionState; constructor(editorStore, assertionState) { makeObservable(this, { testResult: observable, setTestResult: action, statusState: observable, }); this.editorStore = editorStore; this.assertionState = assertionState; } setTestResult(val) { this.testResult = val; this.statusState = undefined; if (val instanceof TestExecuted) { const status = val.assertStatuses.find((_status) => _status.assertion === this.assertionState.assertion); this.statusState = this.buildStatus(status); } else if (val instanceof MultiExecutionServiceTestResult) { const statusMap = new Map(); Array.from(val.keyIndexedTestResults.entries()).forEach((keyedResult) => { const resultState = new TestAssertionResultState(this.editorStore, this.assertionState); resultState.setTestResult(keyedResult[1]); statusMap.set(keyedResult[0], resultState); }); this.statusState = statusMap; } } buildStatus(val) { if (val) { if (val instanceof EqualToJsonAssertFail) { return new EqualToJsonAssertFailState(this, val); } if (val instanceof AssertFail) { if (this.assertionState.assertion instanceof EqualTo) { const message = val.message ?? ''; const hasExpectedFoundPattern = message.includes('expected:') && message.includes('Found :'); if (hasExpectedFoundPattern) { return new EqualToAssertFailState(this, val); } } return new AssertFailState(this, val); } return new UnsupportedAssertionStatusState(this, val); } return undefined; } get result() { if (this.assertionState.testState.runningTestAction.isInProgress) { return TESTABLE_RESULT.IN_PROGRESS; } if (this.testResult instanceof TestError) { return TESTABLE_RESULT.ERROR; } else if (this.testResult instanceof TestExecuted && this.testResult.testExecutionStatus === TestExecutionStatus.PASS) { return TESTABLE_RESULT.PASSED; } else if (this.testResult instanceof TestExecuted && this.testResult.testExecutionStatus === TestExecutionStatus.FAIL && this.statusState instanceof TestAssertionStatusState) { return getTestableResultFromAssertionStatus(this.statusState.status); } else if (this.testResult instanceof MultiExecutionServiceTestResult) { const passed = Array.from(this.testResult.keyIndexedTestResults.entries()).every((keyResult) => { const result = keyResult[1]; if (result instanceof TestExecuted && result.testExecutionStatus === TestExecutionStatus.PASS) { return true; } if (result instanceof TestExecuted && result.testExecutionStatus === TestExecutionStatus.FAIL) { const status = result.assertStatuses.find((_status) => _status.assertion === this.assertionState.assertion); if (status instanceof AssertPass) { return true; } } return false; }); if (passed) { return TESTABLE_RESULT.PASSED; } const assertionErrors = Array.from(this.testResult.keyIndexedTestResults.values()).find((t) => t instanceof TestError); if (assertionErrors) { return TESTABLE_RESULT.ERROR; } return TESTABLE_RESULT.FAILED; } return TESTABLE_RESULT.DID_NOT_RUN; } } export class TestAssertionState { editorStore; assertion; result; constructor(editorStore, assertionState) { this.editorStore = editorStore; this.assertion = assertionState.assertion; this.result = new TestAssertionResultState(editorStore, assertionState); } } export class EqualToJsonAssertionState extends TestAssertionState { setExpectedValue(val) { externalFormatData_setData(this.assertion.expected, val); } get supportsGeneratingAssertion() { return true; } generateExpected(status) { if (status instanceof EqualToJsonAssertFail) { const expected = status.actual; this.setExpectedValue(expected); return true; } return false; } generateBare() { const bareAssertion = new EqualToJson(); bareAssertion.expected = new ExternalFormatData(); bareAssertion.expected.contentType = ContentType.APPLICATION_JSON; bareAssertion.expected.data = ''; return bareAssertion; } label() { return 'EqualToJSON'; } } export class EqualToAssertionState extends TestAssertionState { valueSpec; constructor(editorStore, assertionState, valueSpec) { super(editorStore, assertionState); makeObservable(this, { valueSpec: observable, assertion: observable, updateValueSpec: action, }); this.valueSpec = observe_ValueSpecification(valueSpec, this.editorStore.changeDetectionState.observerContext); } updateValueSpec(val) { this.valueSpec = observe_ValueSpecification(val, this.editorStore.changeDetectionState.observerContext); const object = this.editorStore.graphManagerState.graphManager.serializeValueSpecification(val); equalTo_setExpected(this.assertion, object); } generateExpected(status) { throw new Error('Method not implemented.'); } generateBare() { const equal = new EqualTo(); equal.expected = {}; return equal; } label() { return 'Equal To'; } get supportsGeneratingAssertion() { return false; } } export class UnsupportedAssertionState extends TestAssertionState { get supportsGeneratingAssertion() { return false; } generateBare() { throw new UnsupportedOperationError(); } generateExpected(status) { return false; } label() { return 'Unsupported'; } } export class TestAssertionEditorState { editorStore; testState; assertionState; assertionResultState; assertion; selectedTab = TEST_ASSERTION_TAB.EXPECTED; generatingExpectedAction = ActionState.create(); constructor(editorStore, assertion, testState) { makeObservable(this, { selectedTab: observable, assertionResultState: observable, setSelectedTab: action, generateExpected: flow, }); this.editorStore = editorStore; this.assertion = assertion; this.testState = testState; this.assertionState = this.buildAssertionState(assertion); this.assertionResultState = new TestAssertionResultState(editorStore, this); } setSelectedTab(val) { this.selectedTab = val; } *generateExpected() { try { assertTrue(this.assertionState.supportsGeneratingAssertion, 'Assertion does not support generation'); this.generatingExpectedAction.inProgress(); const result = (yield flowResult(this.testState.fetchTestResult())); let testExecuted; if (result instanceof TestExecuted) { testExecuted = result; } else if (result instanceof MultiExecutionServiceTestResult) { testExecuted = guaranteeNonNullable(Array.from(result.keyIndexedTestResults.values()) .map((testResult) => { if (testResult instanceof TestExecuted) { return testResult; } else if (testResult instanceof TestError) { throw new IllegalStateError(testResult.error); } return undefined; }) .filter(isNonNullable)[0], 'Unable to derive expected result from test result'); } else { throw new UnsupportedOperationError('Unable to derive expected result from test result'); } // if test is passing, update UI and return // if test errors report error if (isTestPassing(testExecuted)) { this.testState.handleTestResult(testExecuted); return; } else if (testExecuted instanceof TestError) { throw new IllegalStateError(testExecuted.error); } const assertionStatus = testExecuted.assertStatuses.find((aStatus) => aStatus.assertion.id === this.assertion.id && aStatus instanceof AssertFail); const assertFail = guaranteeType(assertionStatus, AssertFail, 'Unable to derive expected result from test result'); const generated = this.assertionState.generateExpected(assertFail); if (generated) { this.setSelectedTab(TEST_ASSERTION_TAB.EXPECTED); } this.editorStore.applicationStore.notificationService.notifySuccess(`Expected results generated!`); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.notificationService.notifyError(`Error generating expected result, please check data input: ${error.message}.`); this.setSelectedTab(TEST_ASSERTION_TAB.EXPECTED); this.generatingExpectedAction.fail(); } finally { this.generatingExpectedAction.complete(); } } buildAssertionState(assertion) { if (assertion instanceof EqualToJson) { return new EqualToJsonAssertionState(this.editorStore, this); } else if (assertion instanceof EqualTo) { const val = returnUndefOnError(() => this.editorStore.graphManagerState.graphManager.buildValueSpecification(assertion.expected, this.editorStore.graphManagerState.graph)); if (val) { return new EqualToAssertionState(this.editorStore, this, val); } } return new UnsupportedAssertionState(this.editorStore, this); } } //# sourceMappingURL=TestAssertionState.js.map