From 1710bca2b68057a2784a1e5e01f76d90f0d2c25a Mon Sep 17 00:00:00 2001 From: Cristhian Zanforlin Lousa <72977554+Cristhianzl@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:22:26 -0300 Subject: [PATCH] tests: add tests to chat memory component (#3039) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ♻️ (crud.py): refactor delete_vertex_builds_by_flow_id function to correctly delete vertex builds by flow_id using relationship attribute instead of column comparison. * 📝 (generalBugs-shard-0.spec.ts): Remove unnecessary test case and add new test case for chat messages clearing functionality ✨ (generalBugs-shard-8.spec.ts): Add new test case for interacting with API request ✨ (generalBugs-shard-9.spec.ts): Add new test case for testing chat memory functionality --- .../database/models/vertex_builds/crud.py | 2 +- .../end-to-end/generalBugs-shard-0.spec.ts | 53 ++---- .../end-to-end/generalBugs-shard-8.spec.ts | 41 +++++ .../end-to-end/generalBugs-shard-9.spec.ts | 171 ++++++++++++++++++ 4 files changed, 226 insertions(+), 41 deletions(-) create mode 100644 src/frontend/tests/end-to-end/generalBugs-shard-8.spec.ts create mode 100644 src/frontend/tests/end-to-end/generalBugs-shard-9.spec.ts diff --git a/src/backend/base/langflow/services/database/models/vertex_builds/crud.py b/src/backend/base/langflow/services/database/models/vertex_builds/crud.py index f8d26404f..f846d03a0 100644 --- a/src/backend/base/langflow/services/database/models/vertex_builds/crud.py +++ b/src/backend/base/langflow/services/database/models/vertex_builds/crud.py @@ -32,5 +32,5 @@ def log_vertex_build(db: Session, vertex_build: VertexBuildBase) -> VertexBuildT def delete_vertex_builds_by_flow_id(db: Session, flow_id: UUID) -> None: - delete(VertexBuildTable).where(col(VertexBuildTable.flow_id == flow_id)) + delete(VertexBuildTable).where(VertexBuildTable.flow.has(id=flow_id)) # type: ignore db.commit() diff --git a/src/frontend/tests/end-to-end/generalBugs-shard-0.spec.ts b/src/frontend/tests/end-to-end/generalBugs-shard-0.spec.ts index 154e67736..bd5417edf 100644 --- a/src/frontend/tests/end-to-end/generalBugs-shard-0.spec.ts +++ b/src/frontend/tests/end-to-end/generalBugs-shard-0.spec.ts @@ -2,46 +2,6 @@ import { expect, test } from "@playwright/test"; import * as dotenv from "dotenv"; import path from "path"; -test("should interact with api request", async ({ page }) => { - await page.goto("/"); - await page.waitForTimeout(2000); - - let modalCount = 0; - try { - const modalTitleElement = await page?.getByTestId("modal-title"); - if (modalTitleElement) { - modalCount = await modalTitleElement.count(); - } - } catch (error) { - modalCount = 0; - } - - while (modalCount === 0) { - await page.getByText("New Project", { exact: true }).click(); - await page.waitForTimeout(5000); - modalCount = await page.getByTestId("modal-title")?.count(); - } - await page.getByTestId("blank-flow").click(); - await page.waitForSelector('[data-testid="extended-disclosure"]', { - timeout: 30000, - }); - await page.getByTestId("extended-disclosure").click(); - await page.getByPlaceholder("Search").click(); - await page.getByPlaceholder("Search").fill("api request"); - - await page.waitForTimeout(1000); - - await page - .getByTestId("dataAPI Request") - .dragTo(page.locator('//*[@id="react-flow-id"]')); - await page.mouse.up(); - await page.mouse.down(); - await page.getByTitle("fit view").click(); - await page.getByTitle("zoom out").click(); - await page.getByTitle("zoom out").click(); - await page.getByTitle("zoom out").click(); -}); - test("erase button should clear the chat messages", async ({ page }) => { test.skip( !process?.env?.OPENAI_API_KEY, @@ -127,4 +87,17 @@ test("erase button should clear the chat messages", async ({ page }) => { await page.getByText("User", { exact: true }).last().isHidden(); await page.getByText("Start a conversation").isVisible(); await page.getByText("Langflow Chat").isVisible(); + + await page.waitForTimeout(2000); + await page.getByPlaceholder("Send a message...").fill("My name is John"); + + await page.waitForSelector('[data-testid="icon-LucideSend"]', { + timeout: 100000, + }); + + await page.getByTestId("icon-LucideSend").click(); + + await page.waitForSelector("text=AI", { timeout: 30000 }); + + await page.getByText("Hello, how are you?").isHidden(); }); diff --git a/src/frontend/tests/end-to-end/generalBugs-shard-8.spec.ts b/src/frontend/tests/end-to-end/generalBugs-shard-8.spec.ts new file mode 100644 index 000000000..eb2253391 --- /dev/null +++ b/src/frontend/tests/end-to-end/generalBugs-shard-8.spec.ts @@ -0,0 +1,41 @@ +import { test } from "@playwright/test"; + +test("should interact with api request", async ({ page }) => { + await page.goto("/"); + await page.waitForTimeout(2000); + + let modalCount = 0; + try { + const modalTitleElement = await page?.getByTestId("modal-title"); + if (modalTitleElement) { + modalCount = await modalTitleElement.count(); + } + } catch (error) { + modalCount = 0; + } + + while (modalCount === 0) { + await page.getByText("New Project", { exact: true }).click(); + await page.waitForTimeout(5000); + modalCount = await page.getByTestId("modal-title")?.count(); + } + await page.getByTestId("blank-flow").click(); + await page.waitForSelector('[data-testid="extended-disclosure"]', { + timeout: 30000, + }); + await page.getByTestId("extended-disclosure").click(); + await page.getByPlaceholder("Search").click(); + await page.getByPlaceholder("Search").fill("api request"); + + await page.waitForTimeout(1000); + + await page + .getByTestId("dataAPI Request") + .dragTo(page.locator('//*[@id="react-flow-id"]')); + await page.mouse.up(); + await page.mouse.down(); + await page.getByTitle("fit view").click(); + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); +}); diff --git a/src/frontend/tests/end-to-end/generalBugs-shard-9.spec.ts b/src/frontend/tests/end-to-end/generalBugs-shard-9.spec.ts new file mode 100644 index 000000000..f2fcc8b57 --- /dev/null +++ b/src/frontend/tests/end-to-end/generalBugs-shard-9.spec.ts @@ -0,0 +1,171 @@ +import { expect, test } from "@playwright/test"; +import * as dotenv from "dotenv"; +import path from "path"; + +test("memory should work as expect", async ({ page }) => { + test.skip( + !process?.env?.OPENAI_API_KEY, + "OPENAI_API_KEY required to run this test", + ); + + if (!process.env.CI) { + dotenv.config({ path: path.resolve(__dirname, "../../.env") }); + } + + await page.goto("/"); + + await page.waitForTimeout(1000); + + let modalCount = 0; + try { + const modalTitleElement = await page?.getByTestId("modal-title"); + if (modalTitleElement) { + modalCount = await modalTitleElement.count(); + } + } catch (error) { + modalCount = 0; + } + + while (modalCount === 0) { + await page.getByText("New Project", { exact: true }).click(); + await page.waitForTimeout(5000); + modalCount = await page.getByTestId("modal-title")?.count(); + } + + await page.getByRole("heading", { name: "Basic Prompting" }).click(); + await page.waitForTimeout(1000); + + await page.getByTitle("fit view").click(); + + await page.getByTestId("extended-disclosure").click(); + await page.getByPlaceholder("Search").click(); + await page.getByPlaceholder("Search").fill("chat memory"); + + // Locate the canvas element + const canvas = page.locator("#react-flow-id"); // Update the selector if needed + + // Get the bounding box of the canvas to determine its position + const canvasBox = await canvas.boundingBox(); + if (!canvasBox) { + throw new Error("Canvas element bounding box not found"); + } + + // Starting point (center of the canvas) + const startX = canvasBox.x + canvasBox.width / 2; + const startY = canvasBox.y + canvasBox.height / 2; + + // End point (move 300 pixels to the right) + const endX = startX + 300; + const endY = startY; + + // Hover over the canvas to focus it + await canvas.hover(); + + // Start the drag operation + await page.mouse.move(startX, startY); + await page.mouse.down(); + + // Move to the new position + await page.mouse.move(endX, endY); + + // Release the mouse button to finish the drag + await page.mouse.up(); + + await page + .getByTestId("helpersChat Memory") + .first() + .dragTo(page.locator('//*[@id="react-flow-id"]')); + + await page.mouse.up(); + await page.mouse.down(); + + await page.waitForTimeout; + + await page.getByTitle("fit view").click(); + + let outdatedComponents = await page.getByTestId("icon-AlertTriangle").count(); + + while (outdatedComponents > 0) { + await page.getByTestId("icon-AlertTriangle").first().click(); + await page.waitForTimeout(1000); + outdatedComponents = await page.getByTestId("icon-AlertTriangle").count(); + } + + await page + .getByTestId("popover-anchor-input-api_key") + .fill(process.env.OPENAI_API_KEY ?? ""); + + await page.getByTestId("dropdown_str_model_name").click(); + await page.getByTestId("gpt-4o-1-option").click(); + + const prompt = ` +{context} + +User: {user_input} + +AI: + `; + + await page + .getByTestId("promptarea_prompt_template-ExternalLink") + .nth(0) + .click(); + + await page.getByTestId("modal-promptarea_prompt_template").fill(prompt); + await page.getByText("Edit Prompt", { exact: true }).click(); + await page.getByText("Check & Save").last().click(); + + //connection 1 + const elementChatMemoryOutput = await page + .getByTestId("handle-memory-shownode-messages (text)-right") + .first(); + await elementChatMemoryOutput.hover(); + await page.mouse.down(); + + const promptInput = await page.getByTestId( + "handle-prompt-shownode-context-left", + ); + + await promptInput.hover(); + await page.mouse.up(); + + await page.locator('//*[@id="react-flow-id"]').hover(); + + await page.waitForTimeout(1000); + + await page.getByText("Playground", { exact: true }).click(); + + await page.waitForSelector('[data-testid="icon-LucideSend"]', { + timeout: 100000, + }); + + await page + .getByPlaceholder("Send a message...") + .fill("hi, my car is blue and I like to eat pizza"); + + await page.getByTestId("icon-LucideSend").click(); + + await page.waitForSelector("text=AI", { timeout: 30000 }); + + await page + .getByPlaceholder("Send a message...") + .fill("what color is my car and what do I like to eat?"); + + await page.getByTestId("icon-LucideSend").click(); + + await page.waitForTimeout(400); + + const textLocator = page.locator("text=AI"); + await textLocator.nth(6).waitFor({ timeout: 30000 }); + await expect(textLocator.nth(1)).toBeVisible(); + + await page.waitForTimeout(3000); + + const memoryResponseText = await page + .locator(".form-modal-chat-text") + .nth(1) + .allTextContents(); + + expect(memoryResponseText[0].includes("pizza")).toBeTruthy(); + expect(memoryResponseText[0].includes("blue")).toBeTruthy(); +});