Add link to open "Evaluation Run" from the model editor (#3435)
This commit is contained in:
@@ -276,6 +276,10 @@ export function ModelEditor({
|
||||
});
|
||||
}, []);
|
||||
|
||||
const openModelAlertsView = useCallback(() => {
|
||||
// TODO
|
||||
}, []);
|
||||
|
||||
const onGenerateFromSourceClick = useCallback(() => {
|
||||
vscode.postMessage({
|
||||
t: "generateMethod",
|
||||
@@ -401,6 +405,7 @@ export function ModelEditor({
|
||||
modifiedSignatures={modifiedSignatures}
|
||||
onStartEvaluation={onStartEvaluation}
|
||||
onStopEvaluation={onStopEvaluation}
|
||||
openModelAlertsView={openModelAlertsView}
|
||||
evaluationRun={evaluationRun}
|
||||
/>
|
||||
</ButtonsContainer>
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react";
|
||||
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react";
|
||||
import type { ModeledMethod } from "../../model-editor/modeled-method";
|
||||
import type { ModelEditorViewState } from "../../model-editor/shared/view-state";
|
||||
import type { ModelEvaluationRunState } from "../../model-editor/shared/model-evaluation-run-state";
|
||||
import { modelEvaluationRunIsRunning } from "../../model-editor/shared/model-evaluation-run-state";
|
||||
import { ModelEditorProgressRing } from "./ModelEditorProgressRing";
|
||||
import { LinkIconButton } from "../variant-analysis/LinkIconButton";
|
||||
|
||||
type Props = {
|
||||
export type Props = {
|
||||
viewState: ModelEditorViewState;
|
||||
modeledMethods: Record<string, ModeledMethod[]>;
|
||||
modifiedSignatures: Set<string>;
|
||||
onStartEvaluation: () => void;
|
||||
onStopEvaluation: () => void;
|
||||
openModelAlertsView: () => void;
|
||||
evaluationRun: ModelEvaluationRunState | undefined;
|
||||
};
|
||||
|
||||
@@ -20,34 +22,51 @@ export const ModelEvaluation = ({
|
||||
modifiedSignatures,
|
||||
onStartEvaluation,
|
||||
onStopEvaluation,
|
||||
openModelAlertsView,
|
||||
evaluationRun,
|
||||
}: Props) => {
|
||||
if (!viewState.showEvaluationUi) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!evaluationRun || !modelEvaluationRunIsRunning(evaluationRun)) {
|
||||
const customModelsExist = Object.values(modeledMethods).some(
|
||||
(methods) => methods.filter((m) => m.type !== "none").length > 0,
|
||||
);
|
||||
const shouldShowEvaluateButton =
|
||||
!evaluationRun || !modelEvaluationRunIsRunning(evaluationRun);
|
||||
|
||||
const unsavedChanges = modifiedSignatures.size > 0;
|
||||
const shouldShowStopButton = !shouldShowEvaluateButton;
|
||||
|
||||
return (
|
||||
<VSCodeButton
|
||||
onClick={onStartEvaluation}
|
||||
appearance="secondary"
|
||||
disabled={!customModelsExist || unsavedChanges}
|
||||
>
|
||||
Evaluate
|
||||
</VSCodeButton>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<VSCodeButton onClick={onStopEvaluation} appearance="secondary">
|
||||
<ModelEditorProgressRing />
|
||||
Stop evaluation
|
||||
</VSCodeButton>
|
||||
);
|
||||
}
|
||||
const shouldShowEvaluationRunLink = !!evaluationRun;
|
||||
|
||||
const customModelsExist = Object.values(modeledMethods).some(
|
||||
(methods) => methods.filter((m) => m.type !== "none").length > 0,
|
||||
);
|
||||
|
||||
const unsavedChanges = modifiedSignatures.size > 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
{shouldShowEvaluateButton && (
|
||||
<VSCodeButton
|
||||
onClick={onStartEvaluation}
|
||||
appearance="secondary"
|
||||
disabled={!customModelsExist || unsavedChanges}
|
||||
>
|
||||
Evaluate
|
||||
</VSCodeButton>
|
||||
)}
|
||||
{shouldShowStopButton && (
|
||||
<VSCodeButton onClick={onStopEvaluation} appearance="secondary">
|
||||
<ModelEditorProgressRing />
|
||||
Stop evaluation
|
||||
</VSCodeButton>
|
||||
)}
|
||||
{shouldShowEvaluationRunLink && (
|
||||
<VSCodeLink>
|
||||
<LinkIconButton onClick={openModelAlertsView}>
|
||||
<span slot="end" className="codicon codicon-link-external"></span>
|
||||
Evaluation run
|
||||
</LinkIconButton>
|
||||
</VSCodeLink>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
import { render as reactRender, screen } from "@testing-library/react";
|
||||
import type { Props } from "../ModelEvaluation";
|
||||
import { ModelEvaluation } from "../ModelEvaluation";
|
||||
import { createMockModelEditorViewState } from "../../../../test/factories/model-editor/view-state";
|
||||
import type { ModeledMethod } from "../../../model-editor/modeled-method";
|
||||
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||
import { createMockVariantAnalysis } from "../../../../test/factories/variant-analysis/shared/variant-analysis";
|
||||
import { VariantAnalysisStatus } from "../../../variant-analysis/shared/variant-analysis";
|
||||
import { createSummaryModeledMethod } from "../../../../test/factories/model-editor/modeled-method-factories";
|
||||
|
||||
describe(ModelEvaluation.name, () => {
|
||||
const method = createMethod();
|
||||
const modeledMethodsMap: Record<string, ModeledMethod[]> = {};
|
||||
modeledMethodsMap[method.signature] = [createSummaryModeledMethod(method)];
|
||||
|
||||
const render = (props: Partial<Props> = {}) =>
|
||||
reactRender(
|
||||
<ModelEvaluation
|
||||
viewState={createMockModelEditorViewState({ showEvaluationUi: true })}
|
||||
modeledMethods={modeledMethodsMap}
|
||||
modifiedSignatures={new Set()}
|
||||
onStartEvaluation={jest.fn()}
|
||||
onStopEvaluation={jest.fn()}
|
||||
openModelAlertsView={jest.fn()}
|
||||
evaluationRun={undefined}
|
||||
{...props}
|
||||
/>,
|
||||
);
|
||||
|
||||
describe("when showEvaluationUi is false", () => {
|
||||
it("does not render anything", () => {
|
||||
render({
|
||||
viewState: createMockModelEditorViewState({ showEvaluationUi: false }),
|
||||
});
|
||||
expect(screen.queryByText("Evaluate")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Stop evaluation")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Evaluation run")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when showEvaluationUi is true", () => {
|
||||
it("renders evaluation UI with 'Evaluate' button enabled", () => {
|
||||
render();
|
||||
|
||||
const evaluateButton = screen.queryByText("Evaluate");
|
||||
expect(evaluateButton).toBeInTheDocument();
|
||||
expect(evaluateButton?.getElementsByTagName("input")[0]).toBeEnabled();
|
||||
|
||||
expect(screen.queryByText("Stop evaluation")).not.toBeInTheDocument();
|
||||
|
||||
expect(screen.queryByText("Evaluation run")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("disables 'Evaluate' button when there are no custom models", () => {
|
||||
render({
|
||||
modeledMethods: {},
|
||||
});
|
||||
|
||||
const evaluateButton = screen.queryByText("Evaluate");
|
||||
expect(evaluateButton).toBeInTheDocument();
|
||||
expect(evaluateButton?.getElementsByTagName("input")[0]).toBeDisabled();
|
||||
|
||||
expect(screen.queryByText("Stop evaluation")).not.toBeInTheDocument();
|
||||
|
||||
expect(screen.queryByText("Evaluation run")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("disables 'Evaluate' button when there are unsaved changes", () => {
|
||||
render({
|
||||
modifiedSignatures: new Set([method.signature]),
|
||||
});
|
||||
|
||||
const evaluateButton = screen.queryByText("Evaluate");
|
||||
expect(evaluateButton).toBeInTheDocument();
|
||||
expect(evaluateButton?.getElementsByTagName("input")[0]).toBeDisabled();
|
||||
|
||||
expect(screen.queryByText("Stop evaluation")).not.toBeInTheDocument();
|
||||
|
||||
expect(screen.queryByText("Evaluation run")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders 'Evaluate' button and 'Evaluation run' link when there is a completed evaluation", () => {
|
||||
render({
|
||||
evaluationRun: {
|
||||
isPreparing: false,
|
||||
variantAnalysis: createMockVariantAnalysis({
|
||||
status: VariantAnalysisStatus.Succeeded,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const evaluateButton = screen.queryByText("Evaluate");
|
||||
expect(evaluateButton).toBeInTheDocument();
|
||||
expect(evaluateButton?.getElementsByTagName("input")[0]).toBeEnabled();
|
||||
|
||||
expect(screen.queryByText("Evaluation run")).toBeInTheDocument();
|
||||
|
||||
expect(screen.queryByText("Stop evaluation")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders 'Stop evaluation' button and 'Evaluation run' link when there is an in progress evaluation", () => {
|
||||
render({
|
||||
evaluationRun: {
|
||||
isPreparing: true,
|
||||
variantAnalysis: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const stopEvaluationButton = screen.queryByText("Stop evaluation");
|
||||
expect(stopEvaluationButton).toBeInTheDocument();
|
||||
expect(
|
||||
stopEvaluationButton?.getElementsByTagName("input")[0],
|
||||
).toBeEnabled();
|
||||
|
||||
expect(screen.queryByText("Evaluation run")).toBeInTheDocument();
|
||||
|
||||
expect(screen.queryByText("Evaluate")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user