diff --git a/src/frontend/src/components/core/parameterRenderComponent/components/inputGlobalComponent/__tests__/index.test.tsx b/src/frontend/src/components/core/parameterRenderComponent/components/inputGlobalComponent/__tests__/index.test.tsx index 0904bda55a..593b49f06e 100644 --- a/src/frontend/src/components/core/parameterRenderComponent/components/inputGlobalComponent/__tests__/index.test.tsx +++ b/src/frontend/src/components/core/parameterRenderComponent/components/inputGlobalComponent/__tests__/index.test.tsx @@ -2,6 +2,7 @@ import { render, waitFor } from "@testing-library/react"; import InputGlobalComponent from ".."; const mockUseGetGlobalVariables = jest.fn(); +const mockInputComponent = jest.fn().mockReturnValue(null); jest.mock("@/controllers/API/queries/variables", () => ({ useGetGlobalVariables: () => mockUseGetGlobalVariables(), @@ -32,7 +33,10 @@ jest.mock( "@/components/core/parameterRenderComponent/components/inputComponent", () => ({ __esModule: true, - default: () => null, + default: (props: Record) => { + mockInputComponent(props); + return null; + }, }), ); @@ -104,4 +108,112 @@ describe("InputGlobalComponent", () => { expect(handleOnNewValue).not.toHaveBeenCalled(); }); }); + + describe("options passed to InputComponent", () => { + const configuredVariables = [ + { name: "MY_API_KEY" }, + { name: "ANOTHER_VAR" }, + ]; + + beforeEach(() => { + mockUseGetGlobalVariables.mockReturnValue({ + data: configuredVariables, + isFetchedAfterMount: true, + isFetching: false, + isSuccess: true, + }); + }); + + const getRenderedOptions = (): string[] => + mockInputComponent.mock.calls[mockInputComponent.mock.calls.length - 1][0] + .options as string[]; + + it("does not add typed camelCase text to the dropdown", () => { + render( + , + ); + + expect(getRenderedOptions()).not.toContain("invalidKey"); + expect(getRenderedOptions()).toEqual(["MY_API_KEY", "ANOTHER_VAR"]); + }); + + it("does not add SCREAMING_SNAKE_CASE typed text to the dropdown", () => { + render( + , + ); + + expect(getRenderedOptions()).not.toContain("OPENAI_API_KEY"); + expect(getRenderedOptions()).toEqual(["MY_API_KEY", "ANOTHER_VAR"]); + }); + + it("shows only configured global variables when the field is not a password field", () => { + render( + , + ); + + expect(getRenderedOptions()).toEqual(["MY_API_KEY", "ANOTHER_VAR"]); + }); + + it("temporarily includes an orphaned variable reference while it is being cleared", () => { + render( + , + ); + + expect(getRenderedOptions()).toContain("DELETED_VAR"); + }); + + it("does not duplicate a variable that already exists in the configured list", () => { + render( + , + ); + + const options = getRenderedOptions(); + expect(options.filter((o) => o === "MY_API_KEY")).toHaveLength(1); + }); + }); }); diff --git a/src/frontend/src/components/core/parameterRenderComponent/components/inputGlobalComponent/index.tsx b/src/frontend/src/components/core/parameterRenderComponent/components/inputGlobalComponent/index.tsx index 52ddee8429..a23dac5949 100644 --- a/src/frontend/src/components/core/parameterRenderComponent/components/inputGlobalComponent/index.tsx +++ b/src/frontend/src/components/core/parameterRenderComponent/components/inputGlobalComponent/index.tsx @@ -1,7 +1,6 @@ import { useEffect } from "react"; import { useGetGlobalVariables } from "@/controllers/API/queries/variables"; import GeneralDeleteConfirmationModal from "@/shared/components/delete-confirmation-modal"; -import { looksLikeVariableName } from "../../../../../utils/reactflowUtils"; import { cn } from "../../../../../utils/utils"; import ForwardedIconComponent from "../../../../common/genericIconComponent"; import { CommandItem } from "../../../../ui/command"; @@ -143,14 +142,11 @@ export default function InputGlobalComponent({ let variableOptions = typedGlobalVariables.map((variable) => variable.name); - const isEnvVarName = - password && currentValue && looksLikeVariableName(currentValue); if ( - (loadFromDb && - currentValue && - !valueExists && - !variableOptions.includes(currentValue)) || - (isEnvVarName && !variableOptions.includes(currentValue)) + loadFromDb && + currentValue && + !valueExists && + !variableOptions.includes(currentValue) ) { variableOptions = [...variableOptions, currentValue]; }