diff --git a/src/frontend/src/components/tableComponent/components/tableNodeCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableNodeCellRender/index.tsx index bc912a971a11..8482a0da4737 100644 --- a/src/frontend/src/components/tableComponent/components/tableNodeCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableNodeCellRender/index.tsx @@ -2,6 +2,7 @@ import { CustomCellRendererProps } from "ag-grid-react"; import { cloneDeep } from "lodash"; import { useState } from "react"; import useFlowStore from "../../../../stores/flowStore"; +import { APIClassType } from "../../../../types/api"; import { convertObjToArray, convertValuesToNumbers, @@ -24,24 +25,31 @@ import ToggleShadComponent from "../../../toggleShadComponent"; export default function TableNodeCellRender({ node: { data }, - value: { value, nodeClass, handleOnNewValue: handleOnNewValueNode }, + value: { + value, + nodeClass, + handleOnNewValue: handleOnNewValueNode, + handleNodeClass, + }, }: CustomCellRendererProps) { const handleOnNewValue = (newValue: any, name: string, dbValue?: boolean) => { handleOnNewValueNode(newValue, name, dbValue); setTemplateData((old) => { let newData = cloneDeep(old); newData.value = newValue; - if (dbValue) { + if (dbValue !== undefined) { newData.load_from_db = newValue; } return newData; }); setTemplateValue(newValue); }; + const setNodeClass = (value: APIClassType, code?: string, type?: string) => { + handleNodeClass(value, templateData.key, code, type); + }; const [templateValue, setTemplateValue] = useState(value); const [templateData, setTemplateData] = useState(data); - const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); const edges = useFlowStore((state) => state.edges); @@ -220,9 +228,7 @@ export default function TableNodeCellRender({ editNode={true} disabled={disabled} nodeClass={nodeClass} - setNodeClass={(value) => { - nodeClass = value; - }} + setNodeClass={setNodeClass} value={templateValue ?? ""} onChange={(value: string | string[]) => { handleOnNewValue(value, templateData.key); @@ -237,9 +243,7 @@ export default function TableNodeCellRender({ { - nodeClass = value; - }} + setNodeClass={setNodeClass} nodeClass={nodeClass} disabled={disabled} editNode={true} diff --git a/src/frontend/src/modals/editNodeModal/hooks/use-column-defs.tsx b/src/frontend/src/modals/editNodeModal/hooks/use-column-defs.tsx index cad877aa634e..b6230e3a67a9 100644 --- a/src/frontend/src/modals/editNodeModal/hooks/use-column-defs.tsx +++ b/src/frontend/src/modals/editNodeModal/hooks/use-column-defs.tsx @@ -1,12 +1,19 @@ import { ColDef, ValueGetterParams } from "ag-grid-community"; -import { useMemo } from "react"; +import { useMemo, useState } from "react"; import TableNodeCellRender from "../../../components/tableComponent/components/tableNodeCellRender"; import TableToggleCellRender from "../../../components/tableComponent/components/tableToggleCellRender"; +import { APIClassType } from "../../../types/api"; import { NodeDataType } from "../../../types/flow"; const useColumnDefs = ( - myData: NodeDataType, + nodeClass: APIClassType, handleOnNewValue: (newValue: any, name: string, setDb?: boolean) => void, + handleNodeClass: ( + newNodeClass: APIClassType, + name: string, + code: string, + type?: string, + ) => void, changeAdvanced: (n: string) => void, open: boolean, ) => { @@ -46,8 +53,9 @@ const useColumnDefs = ( valueGetter: (params: ValueGetterParams) => { return { value: params.data.value, - nodeClass: myData.node, + nodeClass: nodeClass, handleOnNewValue: handleOnNewValue, + handleNodeClass: handleNodeClass, }; }, minWidth: 340, @@ -75,7 +83,7 @@ const useColumnDefs = ( cellClass: "no-border", }, ], - [open, myData], + [open, nodeClass], ); return columnDefs; diff --git a/src/frontend/src/modals/editNodeModal/hooks/use-handle-change-advanced.tsx b/src/frontend/src/modals/editNodeModal/hooks/use-handle-change-advanced.tsx new file mode 100644 index 000000000000..fdb9102dcc98 --- /dev/null +++ b/src/frontend/src/modals/editNodeModal/hooks/use-handle-change-advanced.tsx @@ -0,0 +1,29 @@ +import { cloneDeep } from "lodash"; +import { NodeDataType } from "../../../types/flow"; + +const useHandleChangeAdvanced = ( + data: NodeDataType, + takeSnapshot: () => void, + setNode: (id: string, callback: (oldNode: any) => any) => void, + updateNodeInternals: (id: string) => void, +) => { + const handleChangeAdvanced = (name) => { + if (!data.node) return; + takeSnapshot(); + + setNode(data.id, (oldNode) => { + let newNode = cloneDeep(oldNode); + + newNode.data.node.template[name].advanced = + !newNode.data.node.template[name].advanced; + + return newNode; + }); + + updateNodeInternals(data.id); + }; + + return { handleChangeAdvanced }; +}; + +export default useHandleChangeAdvanced; diff --git a/src/frontend/src/modals/editNodeModal/hooks/use-handle-new-value.tsx b/src/frontend/src/modals/editNodeModal/hooks/use-handle-new-value.tsx new file mode 100644 index 000000000000..58351fd2d462 --- /dev/null +++ b/src/frontend/src/modals/editNodeModal/hooks/use-handle-new-value.tsx @@ -0,0 +1,84 @@ +import { cloneDeep } from "lodash"; +import { + ERROR_UPDATING_COMPONENT, + TITLE_ERROR_UPDATING_COMPONENT, +} from "../../../constants/constants"; +import useAlertStore from "../../../stores/alertStore"; +import { ResponseErrorTypeAPI } from "../../../types/api"; +import { NodeDataType } from "../../../types/flow"; + +const useHandleOnNewValue = ( + data: NodeDataType, + takeSnapshot: () => void, + handleUpdateValues: (name: string, data: NodeDataType) => Promise, + debouncedHandleUpdateValues: any, + setNode: (id: string, callback: (oldNode: any) => any) => void, +) => { + const setErrorData = useAlertStore((state) => state.setErrorData); + + const handleOnNewValue = async ( + newValue, + name, + dbValue, + skipSnapshot = false, + ) => { + const nodeTemplate = data.node!.template[name]; + const currentValue = nodeTemplate.value; + + if (currentValue !== newValue && !skipSnapshot) { + takeSnapshot(); + } + + const shouldUpdate = + data.node?.template[name].real_time_refresh && + !data.node?.template[name].refresh_button && + currentValue !== newValue; + + const typeToDebounce = nodeTemplate.type; + + nodeTemplate.value = newValue; + + let newTemplate; + if (shouldUpdate) { + try { + if (["int"].includes(typeToDebounce)) { + newTemplate = await handleUpdateValues(name, data); + } else { + newTemplate = await debouncedHandleUpdateValues(name, data); + } + } catch (error) { + let responseError = error as ResponseErrorTypeAPI; + setErrorData({ + title: TITLE_ERROR_UPDATING_COMPONENT, + list: [ + responseError?.response?.data?.detail.error ?? + ERROR_UPDATING_COMPONENT, + ], + }); + } + } + + setNode(data.id, (oldNode) => { + const newNode = cloneDeep(oldNode); + newNode.data = { + ...newNode.data, + }; + + if (dbValue !== undefined) { + newNode.data.node.template[name].load_from_db = dbValue; + } + + if (data.node?.template[name].real_time_refresh && newTemplate) { + newNode.data.node.template = newTemplate; + } else { + newNode.data.node.template[name].value = newValue; + } + + return newNode; + }); + }; + + return { handleOnNewValue }; +}; + +export default useHandleOnNewValue; diff --git a/src/frontend/src/modals/editNodeModal/hooks/use-handle-node-class.tsx b/src/frontend/src/modals/editNodeModal/hooks/use-handle-node-class.tsx new file mode 100644 index 000000000000..9ad9eec62b7d --- /dev/null +++ b/src/frontend/src/modals/editNodeModal/hooks/use-handle-node-class.tsx @@ -0,0 +1,39 @@ +import { cloneDeep } from "lodash"; +import { NodeDataType } from "../../../types/flow"; + +const useHandleNodeClass = ( + data: NodeDataType, + takeSnapshot: () => void, + setNode: (id: string, callback: (oldNode: any) => any) => void, + updateNodeInternals: (id: string) => void, +) => { + const handleNodeClass = (newNodeClass, name, code, type?: string) => { + if (!data.node) return; + if (data.node!.template[name].value !== code) { + takeSnapshot(); + } + + setNode(data.id, (oldNode) => { + let newNode = cloneDeep(oldNode); + + newNode.data = { + ...newNode.data, + node: newNodeClass, + description: newNodeClass.description ?? data.node!.description, + display_name: newNodeClass.display_name ?? data.node!.display_name, + }; + if (type) { + newNode.data.node.template[name].type = type; + } + newNode.data.node.template[name].value = code; + + return newNode; + }); + + updateNodeInternals(data.id); + }; + + return { handleNodeClass }; +}; + +export default useHandleNodeClass; diff --git a/src/frontend/src/modals/editNodeModal/hooks/use-row-data.tsx b/src/frontend/src/modals/editNodeModal/hooks/use-row-data.tsx index e2cd5a7723fe..375b3337f63f 100644 --- a/src/frontend/src/modals/editNodeModal/hooks/use-row-data.tsx +++ b/src/frontend/src/modals/editNodeModal/hooks/use-row-data.tsx @@ -1,8 +1,13 @@ import { useMemo } from "react"; import { LANGFLOW_SUPPORTED_TYPES } from "../../../constants/constants"; +import { APIClassType } from "../../../types/api"; import { NodeDataType } from "../../../types/flow"; -const useRowData = (myData: NodeDataType, open: boolean) => { +const useRowData = ( + myData: NodeDataType, + nodeClass: APIClassType, + open: boolean, +) => { const rowData = useMemo(() => { return Object.keys(myData.node!.template) .filter((key: string) => { @@ -25,7 +30,7 @@ const useRowData = (myData: NodeDataType, open: boolean) => { id: key, }; }); - }, [open, myData]); + }, [open, nodeClass]); return rowData; }; diff --git a/src/frontend/src/modals/editNodeModal/index.tsx b/src/frontend/src/modals/editNodeModal/index.tsx index e267b6bac11d..0fb52b128e26 100644 --- a/src/frontend/src/modals/editNodeModal/index.tsx +++ b/src/frontend/src/modals/editNodeModal/index.tsx @@ -1,13 +1,23 @@ -import { ColDef, GridApi } from "ag-grid-community"; -import { cloneDeep } from "lodash"; -import { forwardRef, useEffect, useRef, useState } from "react"; +import { ColDef } from "ag-grid-community"; +import { forwardRef, useState } from "react"; +import { useUpdateNodeInternals } from "reactflow"; import TableComponent from "../../components/tableComponent"; import { Badge } from "../../components/ui/badge"; +import { Button } from "../../components/ui/button"; import { useDarkStore } from "../../stores/darkStore"; import useFlowStore from "../../stores/flowStore"; +import useFlowsManagerStore from "../../stores/flowsManagerStore"; +import { APIClassType } from "../../types/api"; import { NodeDataType } from "../../types/flow"; +import { + debouncedHandleUpdateValues, + handleUpdateValues, +} from "../../utils/parameterUtils"; import BaseModal from "../baseModal"; import useColumnDefs from "./hooks/use-column-defs"; +import useHandleChangeAdvanced from "./hooks/use-handle-change-advanced"; +import useHandleOnNewValue from "./hooks/use-handle-new-value"; +import useHandleNodeClass from "./hooks/use-handle-node-class"; import useRowData from "./hooks/use-row-data"; const EditNodeModal = forwardRef( @@ -25,42 +35,51 @@ const EditNodeModal = forwardRef( }, ref, ) => { - const myData = useRef(cloneDeep(data)); - const isDark = useDarkStore((state) => state.dark); - const setNode = useFlowStore((state) => state.setNode); + const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot); + const updateNodeInternals = useUpdateNodeInternals(); + + const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue( + data, + takeSnapshot, + handleUpdateValues, + debouncedHandleUpdateValues, + setNode, + ); + + const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass( + data, + takeSnapshot, + setNode, + updateNodeInternals, + ); - function changeAdvanced(n) { - myData.current.node!.template[n].advanced = - !myData.current.node!.template[n]?.advanced; - } + const [nodeClass, setNodeClass] = useState(data.node!); - const handleOnNewValue = (newValue: any, key: string, setDb?: boolean) => { - myData.current.node!.template[key].value = newValue; - if (setDb) { - myData.current.node!.template[key].load_from_db = newValue; - } + const handleNodeClass = ( + newNodeClass: APIClassType, + name: string, + code: string, + type?: string, + ) => { + handleNodeClassHook(newNodeClass, name, code, type); + setNodeClass(newNodeClass); }; - const rowData = useRowData(data, open); + const { handleChangeAdvanced: handleChangeAdvancedHook } = + useHandleChangeAdvanced(data, takeSnapshot, setNode, updateNodeInternals); + + const rowData = useRowData(data, nodeClass, open); const columnDefs: ColDef[] = useColumnDefs( - data, - handleOnNewValue, - changeAdvanced, + nodeClass, + handleOnNewValueHook, + handleNodeClass, + handleChangeAdvancedHook, open, ); - const [gridApi, setGridApi] = useState(null); - - useEffect(() => { - if (gridApi && open) { - myData.current = cloneDeep(data); - gridApi.refreshCells(); - } - }, [gridApi, open]); - return ( @@ -80,9 +99,6 @@ const EditNodeModal = forwardRef( {nodeLength > 0 && ( { - setGridApi(params.api); - }} tooltipShowDelay={0.5} columnDefs={columnDefs} rowData={rowData} @@ -91,22 +107,11 @@ const EditNodeModal = forwardRef( - - { - setNode(data.id, (old) => ({ - ...old, - data: { - ...old.data, - node: myData.current.node, - }, - })); - setOpen(false); - }, - }} - /> + +
+ +
+
); }, diff --git a/src/frontend/tests/end-to-end/chatInputOutputUser-shard-0.spec.ts b/src/frontend/tests/end-to-end/chatInputOutputUser-shard-0.spec.ts index 1a8eedb4597f..5475e2f8d272 100644 --- a/src/frontend/tests/end-to-end/chatInputOutputUser-shard-0.spec.ts +++ b/src/frontend/tests/end-to-end/chatInputOutputUser-shard-0.spec.ts @@ -54,7 +54,7 @@ test("user must be able to send an image on chat", async ({ page }) => { await page.getByText("Chat Input", { exact: true }).click(); await page.getByTestId("more-options-modal").click(); await page.getByTestId("edit-button-modal").click(); - await page.getByText("Save Changes").click(); + await page.getByText("Close").last().click(); await page.getByText("Playground", { exact: true }).click(); diff --git a/src/frontend/tests/end-to-end/chatInputOutputUser-shard-2.spec.ts b/src/frontend/tests/end-to-end/chatInputOutputUser-shard-2.spec.ts index afbedca30352..6bcd35dbea9a 100644 --- a/src/frontend/tests/end-to-end/chatInputOutputUser-shard-2.spec.ts +++ b/src/frontend/tests/end-to-end/chatInputOutputUser-shard-2.spec.ts @@ -93,12 +93,12 @@ test("user must interact with chat with Input/Output", async ({ page }) => { await page.getByText("Chat Input", { exact: true }).click(); await page.getByTestId("advanced-button-modal").click(); await page.getByTestId("showsender_name").click(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.getByText("Chat Output", { exact: true }).click(); await page.getByTestId("advanced-button-modal").click(); await page.getByTestId("showsender_name").click(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page .getByTestId("popover-anchor-input-sender_name") diff --git a/src/frontend/tests/end-to-end/decisionFlow.spec.ts b/src/frontend/tests/end-to-end/decisionFlow.spec.ts index d275e43a88c8..83d0c67f1233 100644 --- a/src/frontend/tests/end-to-end/decisionFlow.spec.ts +++ b/src/frontend/tests/end-to-end/decisionFlow.spec.ts @@ -472,7 +472,7 @@ AI: .getByTestId("popover-anchor-input-input_message-edit") .nth(0) .fill("You're Happy! 🤪"); - await page.getByText("Save Changes").click(); + await page.getByText("Close").last().click(); await page.getByTitle("zoom in").click(); await page.getByTitle("zoom in").click(); @@ -495,7 +495,7 @@ AI: .getByTestId("popover-anchor-input-input_message-edit") .nth(0) .fill("You're Sad! 🥲"); - await page.getByText("Save Changes").click(); + await page.getByText("Close").last().click(); await page.getByTitle("fit view").click({ force: true, diff --git a/src/frontend/tests/end-to-end/dropdownComponent.spec.ts b/src/frontend/tests/end-to-end/dropdownComponent.spec.ts index a0a6ee906cba..ced3ee3f8f61 100644 --- a/src/frontend/tests/end-to-end/dropdownComponent.spec.ts +++ b/src/frontend/tests/end-to-end/dropdownComponent.spec.ts @@ -144,7 +144,7 @@ test("dropDownComponent", async ({ page }) => { expect(false).toBeTruthy(); } - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); value = await page.getByTestId("dropdown-model_id").innerText(); if (value !== "cohere.embed-multilingual-v3") { diff --git a/src/frontend/tests/end-to-end/floatComponent.spec.ts b/src/frontend/tests/end-to-end/floatComponent.spec.ts index 2dfd4495162c..c0ec5e440519 100644 --- a/src/frontend/tests/end-to-end/floatComponent.spec.ts +++ b/src/frontend/tests/end-to-end/floatComponent.spec.ts @@ -99,7 +99,7 @@ test("FloatComponent", async ({ page }) => { await page.locator('//*[@id="showmirostat_tau"]').isChecked(), ).toBeFalsy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); const plusButtonLocator = page.locator('//*[@id="float-input"]'); const elementCount = await plusButtonLocator?.count(); @@ -115,7 +115,7 @@ test("FloatComponent", async ({ page }) => { await page.locator('//*[@id="showtemperature"]').isChecked(), ).toBeTruthy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.locator('//*[@id="float-input"]').click(); await page.locator('//*[@id="float-input"]').fill("3"); diff --git a/src/frontend/tests/end-to-end/inputComponent.spec.ts b/src/frontend/tests/end-to-end/inputComponent.spec.ts index c9e9a8f11368..0ea77b473a38 100644 --- a/src/frontend/tests/end-to-end/inputComponent.spec.ts +++ b/src/frontend/tests/end-to-end/inputComponent.spec.ts @@ -135,7 +135,7 @@ test("InputComponent", async ({ page }) => { .getByTestId("popover-anchor-input-collection_name-edit") .fill("NEW_collection_name_test_123123123!@#$&*(&%$@ÇÇÇÀõe"); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); const plusButtonLocator = page.getByTestId("input-collection_name"); const elementCount = await plusButtonLocator?.count(); @@ -152,7 +152,7 @@ test("InputComponent", async ({ page }) => { await page.locator('//*[@id="showcollection_name"]').isChecked(), ).toBeTruthy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); let value = await page .getByTestId("popover-anchor-input-collection_name") diff --git a/src/frontend/tests/end-to-end/inputListComponent.spec.ts b/src/frontend/tests/end-to-end/inputListComponent.spec.ts index 5450e6b71587..7992a429b340 100644 --- a/src/frontend/tests/end-to-end/inputListComponent.spec.ts +++ b/src/frontend/tests/end-to-end/inputListComponent.spec.ts @@ -87,7 +87,7 @@ test("InputListComponent", async ({ page }) => { expect(false).toBeTruthy(); } - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.getByTestId("input-list-minus-btn_urls-2").isHidden(); diff --git a/src/frontend/tests/end-to-end/intComponent.spec.ts b/src/frontend/tests/end-to-end/intComponent.spec.ts index a7acf3659820..20804a9b6ac3 100644 --- a/src/frontend/tests/end-to-end/intComponent.spec.ts +++ b/src/frontend/tests/end-to-end/intComponent.spec.ts @@ -51,7 +51,7 @@ test("IntComponent", async ({ page }) => { await page.getByTestId("edit-button-modal").click(); await page.getByTestId("showmax_tokens").click(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.getByTestId("int-input-max_tokens").click(); await page .getByTestId("int-input-max_tokens") @@ -172,7 +172,7 @@ test("IntComponent", async ({ page }) => { await page.locator('//*[@id="showtemperature"]').isChecked(), ).toBeFalsy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); const plusButtonLocator = page.getByTestId("int-input-max_tokens"); const elementCount = await plusButtonLocator?.count(); @@ -195,7 +195,7 @@ test("IntComponent", async ({ page }) => { expect(false).toBeTruthy(); } - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.getByTestId("int-input-max_tokens").click(); await page.getByTestId("int-input-max_tokens").fill("3"); diff --git a/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts b/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts index 94e7934f3d5e..43b0700dd616 100644 --- a/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts +++ b/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts @@ -47,7 +47,7 @@ test("KeypairListComponent", async ({ page }) => { await page.getByTestId("showmodel_kwargs").click(); expect(await page.getByTestId("showmodel_kwargs").isChecked()).toBeTruthy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.locator('//*[@id="keypair0"]').click(); await page.locator('//*[@id="keypair0"]').fill("testtesttesttest"); @@ -92,7 +92,7 @@ test("KeypairListComponent", async ({ page }) => { expect( await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), ).toBeFalsy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); const plusButtonLocator = page.locator('//*[@id="plusbtn0"]'); const elementCount = await plusButtonLocator?.count(); @@ -115,7 +115,7 @@ test("KeypairListComponent", async ({ page }) => { const elementKeyCount = await keyPairVerification?.count(); if (elementKeyCount === 1) { - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.getByTestId("div-generic-node").click(); diff --git a/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts b/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts index 4275223e3961..37636352e2fd 100644 --- a/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts +++ b/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts @@ -60,7 +60,7 @@ test("LangflowShortcuts", async ({ page }) => { await page.getByTitle("zoom out").click(); await page.getByTestId("generic-node-title-arrangement").click(); await page.keyboard.press(`${control}+Shift+A`); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.getByTestId("generic-node-title-arrangement").click(); await page.keyboard.press(`${control}+d`); diff --git a/src/frontend/tests/end-to-end/nestedComponent.spec.ts b/src/frontend/tests/end-to-end/nestedComponent.spec.ts index bd419f4dd718..a7a413938e2b 100644 --- a/src/frontend/tests/end-to-end/nestedComponent.spec.ts +++ b/src/frontend/tests/end-to-end/nestedComponent.spec.ts @@ -174,5 +174,5 @@ test("NestedComponent", async ({ page }) => { await page.locator('//*[@id="showtext_key"]').isChecked(), ).toBeTruthy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); }); diff --git a/src/frontend/tests/end-to-end/promptModalComponent.spec.ts b/src/frontend/tests/end-to-end/promptModalComponent.spec.ts index 94ef0dc78ec1..fb24a243ec14 100644 --- a/src/frontend/tests/end-to-end/promptModalComponent.spec.ts +++ b/src/frontend/tests/end-to-end/promptModalComponent.spec.ts @@ -182,7 +182,7 @@ test("PromptTemplateComponent", async ({ page }) => { await page.locator('//*[@id="showprompt"]').click(); expect(await page.locator('//*[@id="showprompt"]').isChecked()).toBeTruthy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.getByTestId("more-options-modal").click(); await page.getByTestId("edit-button-modal").click(); diff --git a/src/frontend/tests/end-to-end/toggleComponent.spec.ts b/src/frontend/tests/end-to-end/toggleComponent.spec.ts index eded6b2b3fd8..118095984caa 100644 --- a/src/frontend/tests/end-to-end/toggleComponent.spec.ts +++ b/src/frontend/tests/end-to-end/toggleComponent.spec.ts @@ -62,7 +62,7 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="showload_hidden"]').isChecked(), ).toBeTruthy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.waitForSelector('[title="fit view"]', { timeout: 100000, @@ -152,7 +152,7 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="showuse_multithreading"]').isChecked(), ).toBeFalsy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); const plusButtonLocator = page.getByTestId("toggle-load_hidden"); const elementCount = await plusButtonLocator?.count(); @@ -173,7 +173,7 @@ test("ToggleComponent", async ({ page }) => { await page.getByTestId("toggle-edit-load_hidden").isChecked(), ).toBeTruthy(); - await page.getByText("Save Changes", { exact: true }).click(); + await page.getByText("Close").last().click(); await page.getByTestId("toggle-load_hidden").click(); expect(