From 70ac19740acbcc6b557a3253881cad37db163769 Mon Sep 17 00:00:00 2001 From: Cristhian Zanforlin Lousa Date: Fri, 30 Aug 2024 18:35:51 -0300 Subject: [PATCH] tests: add new tests to tableComponent (#3627) * refactor: modularized categories and fixed Discover More not appearing * refactor: modularized categories and fixed Discover More not appearing * refactor: modularized categories and fixed Discover More not appearing * refactor: add end-to-end test for interacting with table input component * refactor: Remove duplicate ID in filterSidebar.spec.ts and remove commented code in tableInputComponent.spec.ts --- .../end-to-end/filterEdge-shard-0.spec.ts | 57 ++---- .../tests/end-to-end/filterSidebar.spec.ts | 144 +++++++------ .../filterEdge-shard-1.spec.ts | 110 +++++----- .../tableInputComponent.spec.ts | 192 ++++++++++++++++++ 4 files changed, 354 insertions(+), 149 deletions(-) create mode 100644 src/frontend/tests/scheduled-end-to-end/tableInputComponent.spec.ts diff --git a/src/frontend/tests/end-to-end/filterEdge-shard-0.spec.ts b/src/frontend/tests/end-to-end/filterEdge-shard-0.spec.ts index ee8faad6c..790f01ed3 100644 --- a/src/frontend/tests/end-to-end/filterEdge-shard-0.spec.ts +++ b/src/frontend/tests/end-to-end/filterEdge-shard-0.spec.ts @@ -54,46 +54,25 @@ test("user must see on handle hover a tooltip with possibility connections", asy } await visibleElementHandle.hover().then(async () => { - await expect( - page.getByTestId("available-output-inputs").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-chains").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-textsplitters").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-retrievers").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-prototypes").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-embeddings").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-data").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-vectorstores").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-memories").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-models").first(), - ).toBeVisible(); + const testIds = [ + "available-output-inputs", + "available-output-chains", + "available-output-textsplitters", + "available-output-retrievers", + "available-output-prototypes", + "available-output-embeddings", + "available-output-data", + "available-output-vectorstores", + "available-output-memories", + "available-output-models", + "available-output-outputs", + "available-output-agents", + "available-output-helpers", + ]; - await expect( - page.getByTestId("available-output-outputs").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-agents").first(), - ).toBeVisible(); - await expect( - page.getByTestId("available-output-helpers").first(), - ).toBeVisible(); + await Promise.all( + testIds.map((id) => expect(page.getByTestId(id).first()).toBeVisible()), + ); await page.getByTestId("icon-X").click(); await page.waitForTimeout(500); diff --git a/src/frontend/tests/end-to-end/filterSidebar.spec.ts b/src/frontend/tests/end-to-end/filterSidebar.spec.ts index b4fafbc89..02f34990d 100644 --- a/src/frontend/tests/end-to-end/filterSidebar.spec.ts +++ b/src/frontend/tests/end-to-end/filterSidebar.spec.ts @@ -54,73 +54,101 @@ test("user must see on handle click the possibility connections - LLMChain", asy await page.getByTestId("handle-apirequest-shownode-urls-left").click(); - await expect(page.getByTestId("disclosure-inputs")).toBeVisible(); - await expect(page.getByTestId("disclosure-outputs")).toBeVisible(); - await expect(page.getByTestId("disclosure-prompts")).toBeVisible(); - await expect(page.getByTestId("disclosure-models")).toBeVisible(); - await expect(page.getByTestId("disclosure-helpers")).toBeVisible(); - await expect(page.getByTestId("disclosure-agents")).toBeVisible(); - await expect(page.getByTestId("disclosure-chains")).toBeVisible(); - await expect(page.getByTestId("disclosure-prototypes")).toBeVisible(); + let disclosureTestIds = [ + "disclosure-inputs", + "disclosure-outputs", + "disclosure-prompts", + "disclosure-models", + "disclosure-helpers", + "disclosure-agents", + "disclosure-chains", + "disclosure-prototypes", + ]; - await expect(page.getByTestId("inputsChat Input")).toBeVisible(); - await expect(page.getByTestId("outputsChat Output")).toBeVisible(); - await expect(page.getByTestId("promptsPrompt")).toBeVisible(); - await expect(page.getByTestId("modelsAmazon Bedrock")).toBeVisible(); - await expect(page.getByTestId("helpersChat Memory")).toBeVisible(); - await expect(page.getByTestId("agentsCSVAgent")).toBeVisible(); - await expect(page.getByTestId("chainsConversationChain")).toBeVisible(); - await expect(page.getByTestId("prototypesConditional Router")).toBeVisible(); + let specificTestIds = [ + "inputsChat Input", + "outputsChat Output", + "promptsPrompt", + "modelsAmazon Bedrock", + "helpersChat Memory", + "agentsCSVAgent", + "chainsConversationChain", + "prototypesConditional Router", + ]; + + await Promise.all( + disclosureTestIds.map((id) => expect(page.getByTestId(id)).toBeVisible()), + ); + + await Promise.all( + specificTestIds.map((id) => expect(page.getByTestId(id)).toBeVisible()), + ); await page.getByPlaceholder("Search").click(); - await expect(page.getByTestId("inputsChat Input")).not.toBeVisible(); - await expect(page.getByTestId("outputsChat Output")).not.toBeVisible(); - await expect(page.getByTestId("promptsPrompt")).not.toBeVisible(); - await expect(page.getByTestId("modelsAmazon Bedrock")).not.toBeVisible(); - await expect(page.getByTestId("helpersChat Memory")).not.toBeVisible(); - await expect(page.getByTestId("agentsTool Calling Agent")).not.toBeVisible(); - await expect(page.getByTestId("chainsConversationChain")).not.toBeVisible(); - await expect( - page.getByTestId("prototypesConditional Router"), - ).not.toBeVisible(); + let notVisibleTestIds = [ + "inputsChat Input", + "outputsChat Output", + "promptsPrompt", + "modelsAmazon Bedrock", + "helpersChat Memory", + "agentsTool Calling Agent", + "chainsConversationChain", + "prototypesConditional Router", + ]; + + await Promise.all( + notVisibleTestIds.map((id) => + expect(page.getByTestId(id)).not.toBeVisible(), + ), + ); await page.getByTestId("handle-apirequest-shownode-headers-left").click(); - await expect(page.getByTestId("disclosure-data")).toBeVisible(); - await expect(page.getByTestId("disclosure-helpers")).toBeVisible(); - await expect(page.getByTestId("disclosure-vector stores")).toBeVisible(); - await expect(page.getByTestId("disclosure-utilities")).toBeVisible(); - await expect(page.getByTestId("disclosure-prototypes")).toBeVisible(); - await expect(page.getByTestId("disclosure-retrievers")).toBeVisible(); - await expect(page.getByTestId("disclosure-text splitters")).toBeVisible(); - await expect(page.getByTestId("disclosure-tools")).toBeVisible(); + disclosureTestIds = [ + "disclosure-data", + "disclosure-helpers", + "disclosure-vector stores", + "disclosure-utilities", + "disclosure-prototypes", + "disclosure-retrievers", + "disclosure-text splitters", + "disclosure-tools", + ]; - await expect(page.getByTestId("dataAPI Request")).toBeVisible(); - await expect(page.getByTestId("helpersChat Memory")).toBeVisible(); - await expect(page.getByTestId("vectorstoresAstra DB")).toBeVisible(); - await expect(page.getByTestId("toolsSearch API")).toBeVisible(); - await expect(page.getByTestId("prototypesSub Flow")).toBeVisible(); - await expect( - page.getByTestId("retrieversSelf Query Retriever"), - ).toBeVisible(); - await expect( - page.getByTestId("textsplittersCharacterTextSplitter"), - ).toBeVisible(); - await expect(page.getByTestId("toolsSearch API")).toBeVisible(); + specificTestIds = [ + "dataAPI Request", + "helpersChat Memory", + "vectorstoresAstra DB", + "toolsSearch API", + "prototypesSub Flow", + "retrieversSelf Query Retriever", + "textsplittersCharacterTextSplitter", + ]; + + await Promise.all( + disclosureTestIds.map((id) => expect(page.getByTestId(id)).toBeVisible()), + ); + + await Promise.all( + specificTestIds.map((id) => expect(page.getByTestId(id)).toBeVisible()), + ); await page.getByPlaceholder("Search").click(); - await expect(page.getByTestId("dataAPI Request")).not.toBeVisible(); - await expect(page.getByTestId("helpersChat Memory")).not.toBeVisible(); - await expect(page.getByTestId("vectorstoresAstra DB")).not.toBeVisible(); - await expect(page.getByTestId("toolsSearch API")).not.toBeVisible(); - await expect(page.getByTestId("prototypesSub Flow")).not.toBeVisible(); - await expect( - page.getByTestId("retrieversSelf Query Retriever"), - ).not.toBeVisible(); - await expect( - page.getByTestId("textsplittersCharacterTextSplitter"), - ).not.toBeVisible(); - await expect(page.getByTestId("toolsSearch API")).not.toBeVisible(); + notVisibleTestIds = [ + "dataAPI Request", + "helpersChat Memory", + "vectorstoresAstra DB", + "toolsSearch API", + "prototypesSub Flow", + "retrieversSelf Query Retriever", + "textsplittersCharacterTextSplitter", + ]; + + await Promise.all( + notVisibleTestIds.map((id) => + expect(page.getByTestId(id)).not.toBeVisible(), + ), + ); }); diff --git a/src/frontend/tests/scheduled-end-to-end/filterEdge-shard-1.spec.ts b/src/frontend/tests/scheduled-end-to-end/filterEdge-shard-1.spec.ts index b58489a5d..88c12fa93 100644 --- a/src/frontend/tests/scheduled-end-to-end/filterEdge-shard-1.spec.ts +++ b/src/frontend/tests/scheduled-end-to-end/filterEdge-shard-1.spec.ts @@ -70,62 +70,68 @@ test("user must see on handle click the possibility connections - RetrievalQA", force: true, }); - await expect(page.getByTestId("disclosure-inputs")).toBeVisible(); - await expect(page.getByTestId("disclosure-outputs")).toBeVisible(); - await expect(page.getByTestId("disclosure-data")).toBeVisible(); - await expect(page.getByTestId("disclosure-models")).toBeVisible(); - await expect(page.getByTestId("disclosure-helpers")).toBeVisible(); - await expect(page.getByTestId("disclosure-vector stores")).toBeVisible(); - await expect(page.getByTestId("disclosure-embeddings")).toBeVisible(); - await expect(page.getByTestId("disclosure-agents")).toBeVisible(); - await expect(page.getByTestId("disclosure-chains")).toBeVisible(); - await expect(page.getByTestId("disclosure-memories")).toBeVisible(); - await expect(page.getByTestId("disclosure-prototypes")).toBeVisible(); - await expect(page.getByTestId("disclosure-retrievers")).toBeVisible(); - await expect(page.getByTestId("disclosure-text splitters")).toBeVisible(); + const disclosureTestIds = [ + "disclosure-inputs", + "disclosure-outputs", + "disclosure-data", + "disclosure-models", + "disclosure-helpers", + "disclosure-vector stores", + "disclosure-embeddings", + "disclosure-agents", + "disclosure-chains", + "disclosure-memories", + "disclosure-prototypes", + "disclosure-retrievers", + "disclosure-text splitters", + ]; - await expect(page.getByTestId("inputsChat Input").first()).toBeVisible(); - await expect(page.getByTestId("outputsChat Output").first()).toBeVisible(); - await expect(page.getByTestId("dataAPI Request").first()).toBeVisible(); - await expect(page.getByTestId("modelsAmazon Bedrock").first()).toBeVisible(); - await expect(page.getByTestId("helpersChat Memory").first()).toBeVisible(); - await expect(page.getByTestId("vectorstoresAstra DB").first()).toBeVisible(); - await expect( - page.getByTestId("embeddingsAmazon Bedrock Embeddings").first(), - ).toBeVisible(); - await expect( - page.getByTestId("agentsTool Calling Agent").first(), - ).toBeVisible(); - await expect( - page.getByTestId("chainsConversationChain").first(), - ).toBeVisible(); - await expect( - page.getByTestId("memoriesAstra DB Chat Memory").first(), - ).toBeVisible(); - await expect( - page.getByTestId("prototypesConditional Router").first(), - ).toBeVisible(); - await expect( - page.getByTestId("retrieversSelf Query Retriever").first(), - ).toBeVisible(); - await expect( - page.getByTestId("textsplittersCharacterTextSplitter").first(), - ).toBeVisible(); + const elementTestIds = [ + "inputsChat Input", + "outputsChat Output", + "dataAPI Request", + "modelsAmazon Bedrock", + "helpersChat Memory", + "vectorstoresAstra DB", + "embeddingsAmazon Bedrock Embeddings", + "agentsTool Calling Agent", + "chainsConversationChain", + "memoriesAstra DB Chat Memory", + "prototypesConditional Router", + "retrieversSelf Query Retriever", + "textsplittersCharacterTextSplitter", + ]; + + await Promise.all( + disclosureTestIds.map((id) => expect(page.getByTestId(id)).toBeVisible()), + ); + + await Promise.all( + elementTestIds.map((id) => + expect(page.getByTestId(id).first()).toBeVisible(), + ), + ); await page.getByPlaceholder("Search").click(); - await expect(page.getByTestId("model_specsVertexAI")).not.toBeVisible(); - await expect(page.getByTestId("model_specsCTransformers")).not.toBeVisible(); - await expect(page.getByTestId("model_specsAmazon Bedrock")).not.toBeVisible(); - await expect(page.getByTestId("modelsAzure OpenAI")).not.toBeVisible(); - await expect( - page.getByTestId("model_specsAzureChatOpenAI"), - ).not.toBeVisible(); - await expect(page.getByTestId("model_specsChatAnthropic")).not.toBeVisible(); - await expect(page.getByTestId("model_specsChatLiteLLM")).not.toBeVisible(); - await expect(page.getByTestId("model_specsChatOllama")).not.toBeVisible(); - await expect(page.getByTestId("model_specsChatOpenAI")).not.toBeVisible(); - await expect(page.getByTestId("model_specsChatVertexAI")).not.toBeVisible(); + const notVisibleModelSpecsTestIds = [ + "model_specsVertexAI", + "model_specsCTransformers", + "model_specsAmazon Bedrock", + "modelsAzure OpenAI", + "model_specsAzureChatOpenAI", + "model_specsChatAnthropic", + "model_specsChatLiteLLM", + "model_specsChatOllama", + "model_specsChatOpenAI", + "model_specsChatVertexAI", + ]; + + await Promise.all( + notVisibleModelSpecsTestIds.map((id) => + expect(page.getByTestId(id)).not.toBeVisible(), + ), + ); const chainInputElements1 = await page .getByTestId("handle-retrievalqa-shownode-llm-left") diff --git a/src/frontend/tests/scheduled-end-to-end/tableInputComponent.spec.ts b/src/frontend/tests/scheduled-end-to-end/tableInputComponent.spec.ts new file mode 100644 index 000000000..a52873cd0 --- /dev/null +++ b/src/frontend/tests/scheduled-end-to-end/tableInputComponent.spec.ts @@ -0,0 +1,192 @@ +import { expect, test } from "@playwright/test"; + +test("user must be able to interact with table input component", async ({ + page, +}) => { + await page.goto("/"); + await page.waitForSelector('[data-testid="mainpage_title"]', { + timeout: 30000, + }); + + await page.waitForSelector('[id="new-project-btn"]', { + timeout: 30000, + }); + + let modalCount = 0; + try { + const modalTitleElement = await page?.getByTestId("modal-title"); + if (modalTitleElement) { + modalCount = await modalTitleElement.count(); + } + } catch (error) { + modalCount = 0; + } + + const randomText = Math.random().toString(36).substring(7); + const secondRandomText = Math.random().toString(36).substring(7); + const thirdRandomText = Math.random().toString(36).substring(7); + + while (modalCount === 0) { + await page.getByText("New Project", { exact: true }).click(); + await page.waitForTimeout(3000); + modalCount = await page.getByTestId("modal-title")?.count(); + } + await page.waitForSelector('[data-testid="blank-flow"]', { + timeout: 30000, + }); + 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("custom component"); + await page.waitForTimeout(1000); + + await page + .getByTestId("helpersCustom Component") + .dragTo(page.locator('//*[@id="react-flow-id"]')); + + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); + + await page.getByTestId("div-generic-node").click(); + await page.getByTestId("code-button-modal").click(); + + const customCodeWithError = ` +# from langflow.field_typing import Data +from langflow.custom import Component +from langflow.io import TableInput, Output +from langflow.schema import Data + + +class CustomComponent(Component): + display_name = "Custom Component" + description = "Use as a template to create your own component." + documentation: str = "http://docs.langflow.org/components/custom" + icon = "custom_components" + name = "CustomComponent" + + inputs = [ + TableInput( + name="input_value", + display_name="Input Value", + value=[ + {"alpha": "X1", "bravo": "Y2", "charlie": "Z3", "delta": "W4", "echo": "V5"}, + {"alpha": "A6", "bravo": "B7", "charlie": "C8", "delta": "D9", "echo": "E0"}, + {"alpha": "F1", "bravo": "G2", "charlie": "H3", "delta": "I4", "echo": "J5"}, + {"alpha": "K6", "bravo": "L7", "charlie": "M8", "delta": "N9", "echo": "O0"}, + {"alpha": "P1", "bravo": "Q2", "charlie": "R3", "delta": "S4", "echo": "T5"} + ], + table_schema=[ + {"name": "alpha", "display_name": "Alpha"}, + {"name": "bravo", "display_name": "Bravo"}, + {"name": "charlie", "display_name": "Charlie"}, + {"name": "delta", "display_name": "Delta"}, + {"name": "echo", "display_name": "Echo"} + ] +) + ] + + outputs = [ + Output(display_name="Output", name="output", method="build_output"), + ] + + def build_output(self) -> Data: + data = Data(value=self.input_value) + self.status = data + return data + `; + + await page.locator("textarea").press("Control+a"); + await page.locator("textarea").fill(customCodeWithError); + + await page.getByText("Check & Save").last().click(); + + await page.waitForTimeout(1000); + + await page.getByText("Open Table").click(); + + await page.waitForTimeout(1000); + + const visibleTextsGroup1 = ["Alpha", "Bravo", "Charlie", "Delta", "Echo"]; + const visibleTextsGroup2 = ["X1", "Y2", "Z3", "W4", "V5"]; + const visibleTextsGroup3 = ["P1", "Q2", "R3", "S4", "T5"]; + const visibleTextsGroup4 = ["F1", "G2", "H3", "I4", "J5"]; + + const allVisibleTexts = [ + ...visibleTextsGroup1, + ...visibleTextsGroup2, + ...visibleTextsGroup3, + ...visibleTextsGroup4, + ]; + + for (const text of allVisibleTexts) { + await expect(page.getByText(text)).toBeVisible(); + } + + await page.locator(".ag-cell-value").first().click(); + + await page.getByPlaceholder("Empty").fill(randomText); + await page.getByText("Save").last().click(); + await page.waitForTimeout(500); + + await page.locator(".ag-cell-value").nth(12).click(); + + await page.getByPlaceholder("Empty").fill(secondRandomText); + await page.getByText("Save").last().click(); + await page.waitForTimeout(500); + + await page.locator(".ag-cell-value").nth(24).click(); + await page.waitForTimeout(500); + + await page.getByPlaceholder("Empty").fill(thirdRandomText); + await page.getByText("Save").last().click(); + + await page.waitForTimeout(500); + + expect(page.getByText(randomText)).toBeVisible(); + expect(page.getByText(secondRandomText)).toBeVisible(); + expect(page.getByText(thirdRandomText)).toBeVisible(); + + await page.locator('input[type="checkbox"]').last().click(); + + await page.getByTestId("icon-Copy").click(); + + await page.waitForTimeout(500); + + let numberOfCopiedRows = await page.getByText(thirdRandomText).count(); + expect(numberOfCopiedRows).toBe(2); + + await page.locator('input[type="checkbox"]').last().click(); + await page.getByTestId("icon-Trash2").click(); + + await page.waitForTimeout(500); + + await page.locator('input[type="checkbox"]').last().click(); + await page.getByTestId("icon-Trash2").click(); + + numberOfCopiedRows = await page.getByText(thirdRandomText).count(); + expect(numberOfCopiedRows).toBe(0); + + await page.getByText("Close").last().click(); + + await page.waitForTimeout(500); + + await page.getByText("Open Table").click(); + + await page.waitForTimeout(1000); + + const visibleTexts = ["Alpha", "Bravo", "Charlie", "Delta", "Echo"]; + const notVisibleTexts = ["X1", "thirdRandomText"]; + + await Promise.all( + visibleTexts.map((text) => expect(page.getByText(text)).toBeVisible()), + ); + await Promise.all( + notVisibleTexts.map((text) => + expect(page.getByText(text)).not.toBeVisible(), + ), + ); +});