CodeQL model editor: Make Type a selectable model kind for Ruby (#3224)
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import type { ChangeEvent } from "react";
|
import type { ChangeEvent } from "react";
|
||||||
import { useCallback } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
import type {
|
import type {
|
||||||
ModeledMethod,
|
ModeledMethod,
|
||||||
ModeledMethodType,
|
ModeledMethodType,
|
||||||
@@ -12,19 +12,11 @@ import type { Method } from "../../model-editor/method";
|
|||||||
import { createEmptyModeledMethod } from "../../model-editor/modeled-method-empty";
|
import { createEmptyModeledMethod } from "../../model-editor/modeled-method-empty";
|
||||||
import type { Mutable } from "../../common/mutable";
|
import type { Mutable } from "../../common/mutable";
|
||||||
import { ReadonlyDropdown } from "../common/ReadonlyDropdown";
|
import { ReadonlyDropdown } from "../common/ReadonlyDropdown";
|
||||||
import type { QueryLanguage } from "../../common/query-language";
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
import { getModelsAsDataLanguage } from "../../model-editor/languages";
|
import { getModelsAsDataLanguage } from "../../model-editor/languages";
|
||||||
import type { ModelingStatus } from "../../model-editor/shared/modeling-status";
|
import type { ModelingStatus } from "../../model-editor/shared/modeling-status";
|
||||||
import { InputDropdown } from "./InputDropdown";
|
import { InputDropdown } from "./InputDropdown";
|
||||||
|
|
||||||
const options: Array<{ value: ModeledMethodType; label: string }> = [
|
|
||||||
{ value: "none", label: "Unmodeled" },
|
|
||||||
{ value: "source", label: "Source" },
|
|
||||||
{ value: "sink", label: "Sink" },
|
|
||||||
{ value: "summary", label: "Flow summary" },
|
|
||||||
{ value: "neutral", label: "Neutral" },
|
|
||||||
];
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
language: QueryLanguage;
|
language: QueryLanguage;
|
||||||
method: Method;
|
method: Method;
|
||||||
@@ -40,6 +32,21 @@ export const ModelTypeDropdown = ({
|
|||||||
modelingStatus,
|
modelingStatus,
|
||||||
onChange,
|
onChange,
|
||||||
}: Props): JSX.Element => {
|
}: Props): JSX.Element => {
|
||||||
|
const options = useMemo(() => {
|
||||||
|
const baseOptions: Array<{ value: ModeledMethodType; label: string }> = [
|
||||||
|
{ value: "none", label: "Unmodeled" },
|
||||||
|
{ value: "source", label: "Source" },
|
||||||
|
{ value: "sink", label: "Sink" },
|
||||||
|
{ value: "summary", label: "Flow summary" },
|
||||||
|
{ value: "neutral", label: "Neutral" },
|
||||||
|
];
|
||||||
|
if (language === QueryLanguage.Ruby) {
|
||||||
|
baseOptions.push({ value: "type", label: "Type" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseOptions;
|
||||||
|
}, [language]);
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
(e: ChangeEvent<HTMLSelectElement>) => {
|
(e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { userEvent } from "@testing-library/user-event";
|
||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import { createNoneModeledMethod } from "../../../../test/factories/model-editor/modeled-method-factories";
|
||||||
|
import { QueryLanguage } from "../../../common/query-language";
|
||||||
|
import { ModelTypeDropdown } from "../ModelTypeDropdown";
|
||||||
|
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||||
|
|
||||||
|
describe(ModelTypeDropdown.name, () => {
|
||||||
|
const onChange = jest.fn();
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
onChange.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows changing the type", async () => {
|
||||||
|
const method = createMethod();
|
||||||
|
const modeledMethod = createNoneModeledMethod();
|
||||||
|
|
||||||
|
render(
|
||||||
|
<ModelTypeDropdown
|
||||||
|
language={QueryLanguage.Java}
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
modelingStatus="unsaved"
|
||||||
|
onChange={onChange}
|
||||||
|
method={method}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
await userEvent.selectOptions(screen.getByRole("combobox"), "source");
|
||||||
|
expect(onChange).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: "source",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows changing the type to 'Type' for Ruby", async () => {
|
||||||
|
const method = createMethod();
|
||||||
|
const modeledMethod = createNoneModeledMethod();
|
||||||
|
|
||||||
|
render(
|
||||||
|
<ModelTypeDropdown
|
||||||
|
language={QueryLanguage.Ruby}
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
modelingStatus="unsaved"
|
||||||
|
onChange={onChange}
|
||||||
|
method={method}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
await userEvent.selectOptions(screen.getByRole("combobox"), "type");
|
||||||
|
expect(onChange).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: "type",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow changing the type to 'Type' for Java", async () => {
|
||||||
|
const method = createMethod();
|
||||||
|
const modeledMethod = createNoneModeledMethod();
|
||||||
|
|
||||||
|
render(
|
||||||
|
<ModelTypeDropdown
|
||||||
|
language={QueryLanguage.Java}
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
modelingStatus="unsaved"
|
||||||
|
onChange={onChange}
|
||||||
|
method={method}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.queryByRole("option", { name: "Type" }),
|
||||||
|
).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user