Add link to open "Evaluation Run" from the model editor (#3435)

This commit is contained in:
Shati Patel
2024-03-04 17:07:32 +00:00
committed by GitHub
parent 54737a0221
commit ad9f78ca2b
3 changed files with 168 additions and 24 deletions

View File

@@ -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>

View File

@@ -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>
)}
</>
);
};

View File

@@ -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();
});
});
});