@finos/legend-application-studio
Version:
Legend Studio application core
339 lines • 13.7 kB
JavaScript
/**
* 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