mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-24 02:47:59 +08:00
test: Refactor Playwright suite with shared helpers and remove redundant tests (#13278)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
cf3c2d30c4
commit
63ee455a2b
@ -1,7 +1,8 @@
|
||||
import { test } from "../../fixtures";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"select and delete a flow",
|
||||
{ tag: ["@release", "@mainpage"] },
|
||||
@ -9,7 +10,9 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 100000,
|
||||
@ -26,15 +29,17 @@ test(
|
||||
timeout: 1000,
|
||||
});
|
||||
// click on the delete button
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
await page.getByText("This can't be undone.").isVisible({
|
||||
timeout: 1000,
|
||||
});
|
||||
|
||||
//confirm the deletion in the modal
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
|
||||
await page.getByText("Selected items deleted successfully").isVisible();
|
||||
await expect(
|
||||
page.getByText("Selected items deleted successfully"),
|
||||
).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
@ -42,7 +47,9 @@ test("search flows", { tag: ["@release", "@mainpage"] }, async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 100000,
|
||||
@ -50,7 +57,7 @@ test("search flows", { tag: ["@release", "@mainpage"] }, async ({ page }) => {
|
||||
|
||||
await page.getByTestId("icon-ChevronLeft").first().click();
|
||||
|
||||
await page.getByText("New Flow").isVisible();
|
||||
await expect(page.getByText("New Flow")).toBeVisible();
|
||||
await page.getByTestId("new-project-btn").click();
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Memory Chatbot" }).click();
|
||||
@ -70,9 +77,11 @@ test("search flows", { tag: ["@release", "@mainpage"] }, async ({ page }) => {
|
||||
|
||||
await page.getByTestId("icon-ChevronLeft").first().click();
|
||||
await page.getByPlaceholder("Search flows").fill("Memory Chatbot");
|
||||
await page.getByText("Memory Chatbot", { exact: true }).isVisible();
|
||||
await expect(page.getByText("Memory Chatbot", { exact: true })).toBeVisible();
|
||||
await page.getByText("Document Q&A", { exact: true }).isHidden();
|
||||
await page.getByText("Basic Prompting", { exact: true }).isHidden();
|
||||
await page
|
||||
.getByText(TEXTS.templateBasicPrompting, { exact: true })
|
||||
.isHidden();
|
||||
});
|
||||
|
||||
test(
|
||||
@ -83,11 +92,13 @@ test(
|
||||
|
||||
if (await page.getByTestId("components-btn").isVisible()) {
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await adjustScreenView(page, { numberOfZoomOut: 2 });
|
||||
|
||||
await page.getByText("Chat Input").first().click();
|
||||
await page.getByText(TEXTS.componentChatInput).first().click();
|
||||
await page.waitForSelector('[data-testid="more-options-modal"]', {
|
||||
timeout: 1000,
|
||||
});
|
||||
@ -123,15 +134,19 @@ test(
|
||||
|
||||
await page.getByTestId("icon-ChevronLeft").first().click();
|
||||
|
||||
const exitButton = await page.getByText("Exit", { exact: true }).count();
|
||||
const exitButton = await page
|
||||
.getByText(TEXTS.exit, { exact: true })
|
||||
.count();
|
||||
|
||||
if (exitButton > 0) {
|
||||
await page.getByText("Exit", { exact: true }).click();
|
||||
await page.getByText(TEXTS.exit, { exact: true }).click();
|
||||
}
|
||||
|
||||
await page.getByTestId("components-btn").click();
|
||||
await page.getByPlaceholder("Search components").fill("Chat Input");
|
||||
await page.getByText("Chat Input", { exact: true }).isVisible();
|
||||
await expect(
|
||||
page.getByText(TEXTS.componentChatInput, { exact: true }),
|
||||
).toBeVisible();
|
||||
await page.getByText("Prompt", { exact: true }).isHidden();
|
||||
await page.getByText("OpenAI", { exact: true }).isHidden();
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { renameFlow } from "../../utils/rename-flow";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"when auto_login is false, admin can CRUD user's and should see just your own flows",
|
||||
{ tag: ["@release", "@api", "@database", "@mainpage"] },
|
||||
@ -41,16 +42,22 @@ test(
|
||||
|
||||
await page.goto("/");
|
||||
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByPlaceholder("Username").fill("langflow");
|
||||
await page.getByPlaceholder("Password").fill("langflow");
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderPassword)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.removeItem("testMockAutoLogin");
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Sign In" }).click();
|
||||
await page.getByRole("button", { name: TEXTS.signIn }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="mainpage_title"]', {
|
||||
timeout: 30000,
|
||||
@ -67,7 +74,10 @@ test(
|
||||
//CRUD an user
|
||||
await page.getByText("New User", { exact: true }).click();
|
||||
|
||||
await page.getByPlaceholder("Username").last().fill(randomName);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.last()
|
||||
.fill(randomName);
|
||||
await page.locator('input[name="password"]').fill(randomPassword);
|
||||
await page.locator('input[name="confirmpassword"]').fill(randomPassword);
|
||||
|
||||
@ -77,7 +87,7 @@ test(
|
||||
|
||||
await page.locator("#is_active").click();
|
||||
|
||||
await page.getByText("Save", { exact: true }).click();
|
||||
await page.getByText(TEXTS.save, { exact: true }).click();
|
||||
|
||||
await page.waitForSelector("text=new user added", { timeout: 30000 });
|
||||
|
||||
@ -86,7 +96,7 @@ test(
|
||||
});
|
||||
|
||||
await page.getByTestId("icon-Trash2").last().click();
|
||||
await page.getByText("Delete", { exact: true }).last().click();
|
||||
await page.getByText(TEXTS.delete, { exact: true }).last().click();
|
||||
|
||||
await page.waitForSelector("text=user deleted", { timeout: 30000 });
|
||||
|
||||
@ -97,7 +107,10 @@ test(
|
||||
|
||||
await page.getByText("New User", { exact: true }).click();
|
||||
|
||||
await page.getByPlaceholder("Username").last().fill(randomName);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.last()
|
||||
.fill(randomName);
|
||||
await page.locator('input[name="password"]').fill(randomPassword);
|
||||
await page.locator('input[name="confirmpassword"]').fill(randomPassword);
|
||||
|
||||
@ -107,7 +120,7 @@ test(
|
||||
|
||||
await page.locator("#is_active").click();
|
||||
|
||||
await page.getByText("Save", { exact: true }).click();
|
||||
await page.getByText(TEXTS.save, { exact: true }).click();
|
||||
|
||||
await page.waitForSelector("text=new user added", { timeout: 30000 });
|
||||
|
||||
@ -115,14 +128,20 @@ test(
|
||||
(response) =>
|
||||
response.url().includes("/api/v1/users") && response.status() === 200,
|
||||
);
|
||||
await page.getByPlaceholder("Username").last().fill(randomName);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.last()
|
||||
.fill(randomName);
|
||||
await searchResponse;
|
||||
|
||||
await page.getByTestId("icon-Pencil").last().click();
|
||||
|
||||
await page.getByPlaceholder("Username").last().fill(secondRandomName);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.last()
|
||||
.fill(secondRandomName);
|
||||
|
||||
await page.getByText("Save", { exact: true }).click();
|
||||
await page.getByText(TEXTS.save, { exact: true }).click();
|
||||
|
||||
await page.waitForSelector("text=user edited", { timeout: 30000 });
|
||||
|
||||
@ -146,7 +165,9 @@ test(
|
||||
await awaitBootstrapTest(page, { skipGoto: true });
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await adjustScreenView(page, { numberOfZoomOut: 1 });
|
||||
|
||||
@ -182,18 +203,22 @@ test(
|
||||
sessionStorage.setItem("testMockAutoLogin", "true");
|
||||
});
|
||||
|
||||
await page.getByText("Logout", { exact: true }).click();
|
||||
await page.getByText(TEXTS.logout, { exact: true }).click();
|
||||
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByPlaceholder("Username").fill(secondRandomName);
|
||||
await page.getByPlaceholder("Password").fill(randomPassword);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.fill(secondRandomName);
|
||||
await page.getByPlaceholder(TEXTS.placeholderPassword).fill(randomPassword);
|
||||
|
||||
await page.waitForSelector("text=Sign in", {
|
||||
timeout: 1500,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Sign In" }).click();
|
||||
await page.getByRole("button", { name: TEXTS.signIn }).click();
|
||||
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.removeItem("testMockAutoLogin");
|
||||
@ -216,7 +241,9 @@ test(
|
||||
await awaitBootstrapTest(page, { skipGoto: true });
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await adjustScreenView(page, { numberOfZoomOut: 2 });
|
||||
|
||||
@ -249,18 +276,24 @@ test(
|
||||
sessionStorage.setItem("testMockAutoLogin", "true");
|
||||
});
|
||||
|
||||
await page.getByText("Logout", { exact: true }).click();
|
||||
await page.getByText(TEXTS.logout, { exact: true }).click();
|
||||
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByPlaceholder("Username").fill("langflow");
|
||||
await page.getByPlaceholder("Password").fill("langflow");
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderPassword)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.removeItem("testMockAutoLogin");
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Sign In" }).click();
|
||||
await page.getByRole("button", { name: TEXTS.signIn }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="mainpage_title"]', {
|
||||
timeout: 30000,
|
||||
|
||||
@ -3,6 +3,7 @@ import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test.describe("Bulk Delete Sessions", () => {
|
||||
// Helper to send a message in the playground
|
||||
async function sendMessage(page: Page, message: string) {
|
||||
@ -73,12 +74,14 @@ test.describe("Bulk Delete Sessions", () => {
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@ -107,12 +110,14 @@ test.describe("Bulk Delete Sessions", () => {
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@ -156,12 +161,14 @@ test.describe("Bulk Delete Sessions", () => {
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@ -206,12 +213,14 @@ test.describe("Bulk Delete Sessions", () => {
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@ -266,12 +275,14 @@ test.describe("Bulk Delete Sessions", () => {
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@ -322,12 +333,14 @@ test.describe("Bulk Delete Sessions", () => {
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@ -383,12 +396,14 @@ test.describe("Bulk Delete Sessions", () => {
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@ -420,12 +435,14 @@ test.describe("Bulk Delete Sessions", () => {
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user must be able to send an image on chat",
|
||||
{ tag: ["@release", "@workspace", "@components"] },
|
||||
@ -24,7 +25,9 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
@ -33,10 +36,12 @@ test(
|
||||
|
||||
await page.waitForSelector("text=Chat Input", { timeout: 30000 });
|
||||
|
||||
await page.getByText("Chat Input", { exact: true }).click();
|
||||
await page.getByText(TEXTS.componentChatInput, { exact: true }).click();
|
||||
await openAdvancedOptions(page);
|
||||
await closeAdvancedOptions(page);
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
timeout: 100000,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user can add components by hovering and clicking the plus icon",
|
||||
{ tag: ["@release", "@components", "@workspace"] },
|
||||
@ -17,7 +18,7 @@ test(
|
||||
|
||||
// Search for a component
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat input");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatInput);
|
||||
|
||||
await page.waitForSelector('[data-testid="input_outputChat Input"]', {
|
||||
timeout: 2000,
|
||||
|
||||
@ -3,6 +3,7 @@ import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { removeOldApiKeys } from "../../utils/remove-old-api-keys";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user should be able to interact with composio component",
|
||||
{ tag: ["@release", "@workspace", "@api", "@components"] },
|
||||
@ -59,7 +60,7 @@ test(
|
||||
|
||||
await page.getByTestId("button_run_gmail").click();
|
||||
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"custom component code button should be pink when adding custom component",
|
||||
{ tag: ["@release", "@components"] },
|
||||
@ -63,7 +64,7 @@ class CustomComponent(Component):
|
||||
await page.keyboard.press(`ControlOrMeta+A`);
|
||||
await page.locator("textarea").last().fill(waitTimeoutCode);
|
||||
|
||||
await page.getByText("Check & Save").last().click();
|
||||
await page.getByText(TEXTS.checkAndSave).last().click();
|
||||
|
||||
await expect(page.getByTestId("code-button-modal").last()).not.toHaveClass(
|
||||
/animate-pulse-pink/,
|
||||
|
||||
@ -18,6 +18,7 @@ import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
// Every section header the new default template must contain, in order.
|
||||
const SECTION_HEADERS = [
|
||||
"# Identity",
|
||||
@ -158,7 +159,10 @@ test(
|
||||
|
||||
// Load Simple Agent — gives us a ready-to-run Agent wired to ChatInput/Output.
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateSimpleAgent })
|
||||
.first()
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Simple Agent's template may carry its own system_prompt — force the fresh
|
||||
@ -181,7 +185,7 @@ test(
|
||||
await page.getByTestId("input-chat-playground").last().fill("Run now.");
|
||||
await page.getByTestId("button-send").last().click();
|
||||
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
const stopButton = page.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
await stopButton.waitFor({ state: "hidden", timeout: 120000 });
|
||||
|
||||
@ -220,7 +224,10 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateSimpleAgent })
|
||||
.first()
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
const customPrompt =
|
||||
@ -238,7 +245,7 @@ test(
|
||||
.fill("Introduce yourself in one short sentence.");
|
||||
await page.getByTestId("button-send").last().click();
|
||||
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
const stopButton = page.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
await stopButton.waitFor({ state: "hidden", timeout: 120000 });
|
||||
|
||||
@ -280,7 +287,10 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateSimpleAgent })
|
||||
.first()
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Force the model to echo the date from its context — any obedience-style
|
||||
@ -301,7 +311,7 @@ test(
|
||||
.fill("What is today's date?");
|
||||
await page.getByTestId("button-send").last().click();
|
||||
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
const stopButton = page.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
await stopButton.waitFor({ state: "hidden", timeout: 120000 });
|
||||
|
||||
|
||||
@ -12,6 +12,11 @@ import {
|
||||
SNAPSHOTS_EMPTY_MOCK,
|
||||
} from "../../utils/deployment-mocks";
|
||||
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper: set up all required API route mocks
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -225,11 +230,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await awaitBootstrapTest(page, { skipModal: true });
|
||||
await setupDeploymentMocks(page, "");
|
||||
await page.getByTestId("deployments-btn").click();
|
||||
@ -250,11 +250,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page);
|
||||
|
||||
// Next should be disabled before selection
|
||||
@ -277,11 +272,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page);
|
||||
await selectProvider(page);
|
||||
await page.getByTestId("deployment-stepper-next").click();
|
||||
@ -318,11 +308,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page);
|
||||
await goToStepType(page);
|
||||
|
||||
@ -367,11 +352,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page);
|
||||
await goToStepReview(page);
|
||||
|
||||
@ -399,11 +379,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page);
|
||||
|
||||
// Set up POST deployments mock (after bootstrap, before deploy click)
|
||||
@ -454,11 +429,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page);
|
||||
await goToStepReview(page);
|
||||
|
||||
@ -493,11 +463,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page, SNAPSHOTS_DUPLICATE_MOCK);
|
||||
await goToStepReview(page);
|
||||
|
||||
@ -520,11 +485,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page, SNAPSHOTS_EMPTY_MOCK);
|
||||
await goToStepReview(page);
|
||||
|
||||
@ -547,11 +507,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page, SNAPSHOTS_DUPLICATE_MOCK);
|
||||
await goToStepReview(page);
|
||||
|
||||
@ -590,11 +545,6 @@ test(
|
||||
tag: ["@deployment", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await openDeploymentStepper(page, SNAPSHOTS_EMPTY_MOCK, [
|
||||
{ ...FLOWS_MOCK[0], name: "12925" },
|
||||
]);
|
||||
|
||||
@ -12,6 +12,11 @@ import {
|
||||
PROVIDERS_MOCK,
|
||||
} from "../../utils/deployment-mocks";
|
||||
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
async function setupRoutes(page: Parameters<typeof test>[2]["page"]) {
|
||||
// Register broad catch-all FIRST so specific routes (registered after) take priority via LIFO
|
||||
await page.route("**/api/v1/deployments*", (route) => {
|
||||
@ -101,11 +106,6 @@ test(
|
||||
tag: ["@release", "@workspace", "@api"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await setupRoutes(page);
|
||||
await navigateToDeployments(page);
|
||||
|
||||
@ -128,11 +128,6 @@ test(
|
||||
tag: ["@release", "@workspace", "@api"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await setupRoutes(page);
|
||||
await navigateToDeployments(page);
|
||||
|
||||
@ -161,11 +156,6 @@ test(
|
||||
tag: ["@release", "@workspace", "@api"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await setupRoutes(page);
|
||||
await navigateToDeployments(page);
|
||||
|
||||
@ -188,11 +178,6 @@ test(
|
||||
tag: ["@release", "@workspace", "@api"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await setupRoutes(page);
|
||||
await navigateToDeployments(page);
|
||||
|
||||
@ -233,11 +218,6 @@ test(
|
||||
tag: ["@release", "@workspace", "@api"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await setupRoutes(page);
|
||||
await navigateToDeployments(page);
|
||||
|
||||
@ -382,11 +362,6 @@ test(
|
||||
tag: ["@release", "@workspace", "@api"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
// Capture folder ID from the projects API before bootstrap
|
||||
const projectsResponsePromise = page.waitForResponse(
|
||||
(resp) =>
|
||||
@ -483,11 +458,6 @@ test(
|
||||
tag: ["@release", "@workspace", "@api"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
const projectsResponsePromise = page.waitForResponse(
|
||||
(resp) =>
|
||||
resp.url().includes("/api/v1/projects") && resp.status() === 200,
|
||||
|
||||
@ -6,6 +6,11 @@ import {
|
||||
PROVIDERS_MOCK,
|
||||
} from "../../utils/deployment-mocks";
|
||||
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
async function navigateToProvidersTab(
|
||||
page: Parameters<typeof test>[2]["page"],
|
||||
) {
|
||||
@ -19,11 +24,6 @@ test(
|
||||
"Empty state shows Add Environment button",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -50,11 +50,6 @@ test(
|
||||
"New Environment button opens modal with save disabled on empty form",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -84,11 +79,6 @@ test(
|
||||
"Save button becomes enabled after filling all required fields",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -127,11 +117,6 @@ test(
|
||||
"Save calls POST and modal closes",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let postCalled = false;
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
@ -196,11 +181,6 @@ test(
|
||||
"Delete triggers confirmation dialog then calls DELETE",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -256,11 +236,6 @@ test(
|
||||
"Cancel delete dismisses confirmation without calling DELETE",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let deleteRequestCount = 0;
|
||||
|
||||
await page.route("**/api/v1/deployments*", (route) => {
|
||||
|
||||
@ -9,6 +9,12 @@ import {
|
||||
RUNNING_RUN_RESPONSE,
|
||||
} from "../../utils/deployment-mocks";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
async function setupBaseRoutes(page: Page) {
|
||||
// Register broad catch-all FIRST so specific routes (registered after) take priority via LIFO
|
||||
await page.route("**/api/v1/deployments*", (route) => {
|
||||
@ -44,18 +50,13 @@ test(
|
||||
"Test button opens modal with chat interface",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await setupBaseRoutes(page);
|
||||
await navigateToDeploymentsPage(page);
|
||||
|
||||
await page.getByTestId("test-deployment-dep-1").click();
|
||||
|
||||
await expect(page.getByTestId("test-deployment-modal-title")).toBeVisible();
|
||||
await expect(page.getByPlaceholder("Message")).toBeVisible();
|
||||
await expect(page.getByPlaceholder(TEXTS.placeholderMessage)).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
@ -63,11 +64,6 @@ test(
|
||||
"Send message calls POST run with correct body",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let capturedRequestBody: Record<string, unknown> | null = null;
|
||||
let runCallCount = 0;
|
||||
|
||||
@ -102,9 +98,9 @@ test(
|
||||
await navigateToDeploymentsPage(page);
|
||||
|
||||
await page.getByTestId("test-deployment-dep-1").click();
|
||||
await expect(page.getByPlaceholder("Message")).toBeVisible();
|
||||
await expect(page.getByPlaceholder(TEXTS.placeholderMessage)).toBeVisible();
|
||||
|
||||
await page.getByPlaceholder("Message").fill("Hello AI");
|
||||
await page.getByPlaceholder(TEXTS.placeholderMessage).fill("Hello AI");
|
||||
await page.getByRole("button", { name: /send message/i }).click();
|
||||
|
||||
await expect
|
||||
@ -119,11 +115,6 @@ test(
|
||||
"Response appears in chat after polling completes",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let runCallCount = 0;
|
||||
|
||||
await setupBaseRoutes(page);
|
||||
@ -155,12 +146,12 @@ test(
|
||||
await navigateToDeploymentsPage(page);
|
||||
|
||||
await page.getByTestId("test-deployment-dep-1").click();
|
||||
await expect(page.getByPlaceholder("Message")).toBeVisible();
|
||||
await expect(page.getByPlaceholder(TEXTS.placeholderMessage)).toBeVisible();
|
||||
|
||||
await page.getByPlaceholder("Message").fill("Hello AI");
|
||||
await page.getByPlaceholder(TEXTS.placeholderMessage).fill("Hello AI");
|
||||
await page.getByRole("button", { name: /send message/i }).click();
|
||||
|
||||
await expect(page.getByText("Hello from AI")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.labelHelloFromAi)).toBeVisible({
|
||||
timeout: 30_000,
|
||||
});
|
||||
expect(runCallCount).toBeGreaterThanOrEqual(2);
|
||||
@ -171,11 +162,6 @@ test(
|
||||
"Input is disabled during polling and re-enabled after response",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let runCallCount = 0;
|
||||
|
||||
await setupBaseRoutes(page);
|
||||
@ -207,19 +193,21 @@ test(
|
||||
await navigateToDeploymentsPage(page);
|
||||
|
||||
await page.getByTestId("test-deployment-dep-1").click();
|
||||
await expect(page.getByPlaceholder("Message")).toBeVisible();
|
||||
await expect(page.getByPlaceholder(TEXTS.placeholderMessage)).toBeVisible();
|
||||
|
||||
await page.getByPlaceholder("Message").fill("Hello AI");
|
||||
await page.getByPlaceholder(TEXTS.placeholderMessage).fill("Hello AI");
|
||||
await page.getByRole("button", { name: /send message/i }).click();
|
||||
|
||||
// Textarea should be disabled while waiting for response
|
||||
await expect(page.getByPlaceholder("Message")).toBeDisabled();
|
||||
await expect(
|
||||
page.getByPlaceholder(TEXTS.placeholderMessage),
|
||||
).toBeDisabled();
|
||||
|
||||
// After response arrives, textarea should be re-enabled
|
||||
await expect(page.getByText("Hello from AI")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.labelHelloFromAi)).toBeVisible({
|
||||
timeout: 30_000,
|
||||
});
|
||||
await expect(page.getByPlaceholder("Message")).toBeEnabled();
|
||||
await expect(page.getByPlaceholder(TEXTS.placeholderMessage)).toBeEnabled();
|
||||
},
|
||||
);
|
||||
|
||||
@ -227,11 +215,6 @@ test(
|
||||
"Multi-turn: second message includes thread_id from first response",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let runCallCount = 0;
|
||||
const capturedBodies: Array<Record<string, unknown>> = [];
|
||||
|
||||
@ -268,23 +251,25 @@ test(
|
||||
await navigateToDeploymentsPage(page);
|
||||
|
||||
await page.getByTestId("test-deployment-dep-1").click();
|
||||
await expect(page.getByPlaceholder("Message")).toBeVisible();
|
||||
await expect(page.getByPlaceholder(TEXTS.placeholderMessage)).toBeVisible();
|
||||
|
||||
// First message
|
||||
await page.getByPlaceholder("Message").fill("First message");
|
||||
await page.getByPlaceholder(TEXTS.placeholderMessage).fill("First message");
|
||||
await page.getByRole("button", { name: /send message/i }).click();
|
||||
|
||||
// Wait for first response
|
||||
await expect(page.getByText("Hello from AI")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.labelHelloFromAi)).toBeVisible({
|
||||
timeout: 30_000,
|
||||
});
|
||||
|
||||
// Second message
|
||||
await page.getByPlaceholder("Message").fill("Second message");
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderMessage)
|
||||
.fill("Second message");
|
||||
await page.getByRole("button", { name: /send message/i }).click();
|
||||
|
||||
// Wait for second response
|
||||
await expect(page.getByText("Hello from AI")).toHaveCount(2, {
|
||||
await expect(page.getByText(TEXTS.labelHelloFromAi)).toHaveCount(2, {
|
||||
timeout: 30_000,
|
||||
});
|
||||
|
||||
@ -303,11 +288,6 @@ test(
|
||||
"Close and reopen modal resets chat history",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let runCallCount = 0;
|
||||
|
||||
await setupBaseRoutes(page);
|
||||
@ -340,13 +320,13 @@ test(
|
||||
|
||||
// Open modal and send a message
|
||||
await page.getByTestId("test-deployment-dep-1").click();
|
||||
await expect(page.getByPlaceholder("Message")).toBeVisible();
|
||||
await expect(page.getByPlaceholder(TEXTS.placeholderMessage)).toBeVisible();
|
||||
|
||||
await page.getByPlaceholder("Message").fill("Hello AI");
|
||||
await page.getByPlaceholder(TEXTS.placeholderMessage).fill("Hello AI");
|
||||
await page.getByRole("button", { name: /send message/i }).click();
|
||||
|
||||
// Wait for response to appear
|
||||
await expect(page.getByText("Hello from AI")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.labelHelloFromAi)).toBeVisible({
|
||||
timeout: 30_000,
|
||||
});
|
||||
|
||||
@ -354,16 +334,18 @@ test(
|
||||
await page.keyboard.press("Escape");
|
||||
|
||||
// Verify the modal is closed
|
||||
await expect(page.getByPlaceholder("Message")).not.toBeVisible();
|
||||
await expect(
|
||||
page.getByPlaceholder(TEXTS.placeholderMessage),
|
||||
).not.toBeVisible();
|
||||
|
||||
// Reopen the modal
|
||||
runCallCount = 0;
|
||||
await page.getByTestId("test-deployment-dep-1").click();
|
||||
await expect(page.getByPlaceholder("Message")).toBeVisible();
|
||||
await expect(page.getByPlaceholder(TEXTS.placeholderMessage)).toBeVisible();
|
||||
|
||||
// Chat should be empty — no previous messages visible
|
||||
await expect(page.getByText("Hello AI")).not.toBeVisible();
|
||||
await expect(page.getByText("Hello from AI")).not.toBeVisible();
|
||||
await expect(page.getByText(TEXTS.labelHelloFromAi)).not.toBeVisible();
|
||||
|
||||
// Empty state ("Agent Chat") should be shown
|
||||
await expect(page.getByText("Agent Chat")).toBeVisible();
|
||||
|
||||
@ -6,6 +6,11 @@ import {
|
||||
PROVIDERS_MOCK,
|
||||
} from "../../utils/deployment-mocks";
|
||||
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
async function navigateToDeploymentsTab(
|
||||
page: Parameters<typeof test>[2]["page"],
|
||||
) {
|
||||
@ -18,11 +23,6 @@ test(
|
||||
"Renders Deployments tab with sub-tab toggles",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -52,11 +52,6 @@ test(
|
||||
"Deployments empty state shows create button when no providers exist",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -85,11 +80,6 @@ test(
|
||||
"Providers empty state shows add provider button when switching to providers tab",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -120,11 +110,6 @@ test(
|
||||
"Deployment list renders a row for each deployment",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -153,11 +138,6 @@ test(
|
||||
"Provider list renders a row for each provider",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -188,11 +168,6 @@ test(
|
||||
"Delete deployment opens type-to-confirm dialog",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -225,11 +200,6 @@ test(
|
||||
"Delete deployment button is disabled until deployment name is typed",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -267,11 +237,6 @@ test(
|
||||
"Delete deployment — typing correct name and confirming calls DELETE",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
@ -320,11 +285,6 @@ test(
|
||||
"Cancel delete deployment dismisses dialog without calling DELETE",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let deleteRequestCount = 0;
|
||||
|
||||
await page.route("**/api/v1/deployments/providers*", (route) => {
|
||||
@ -379,11 +339,6 @@ test(
|
||||
"Names filter is passed to API when fetching deployments",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
process.env.LANGFLOW_FEATURE_WXO_DEPLOYMENTS !== "true",
|
||||
"Requires LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true",
|
||||
);
|
||||
|
||||
let resolveNamesRequest: ((url: string) => void) | undefined;
|
||||
const namesRequest = new Promise<string>((resolve) => {
|
||||
resolveNamesRequest = resolve;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test.describe("Flow Lock Feature", () => {
|
||||
test(
|
||||
"should lock and unlock a flow and verify UI changes",
|
||||
@ -10,7 +11,9 @@ test.describe("Flow Lock Feature", () => {
|
||||
|
||||
// Navigate to templates and select a flow to work with
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 5000,
|
||||
@ -120,7 +123,9 @@ test.describe("Flow Lock Feature", () => {
|
||||
|
||||
// Navigate to templates and select a flow
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 5000,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
/**
|
||||
* Tests for folder deletion integrity
|
||||
*
|
||||
@ -18,7 +19,9 @@ test(
|
||||
|
||||
// Navigate to templates and create a flow first
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 30000,
|
||||
@ -36,14 +39,14 @@ test(
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.waitFor({ state: "visible", timeout: 10000 });
|
||||
|
||||
// Rename the folder for easier identification
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.dblclick();
|
||||
|
||||
@ -71,10 +74,10 @@ test(
|
||||
.waitFor({ state: "visible", timeout: 5000 });
|
||||
await page.getByTestId("more-options-button_test-folder-to-delete").click();
|
||||
await page.getByTestId("btn-delete-project").click();
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
|
||||
// Verify success message
|
||||
await expect(page.getByText("Project deleted successfully")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.toastProjectDeleted)).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
@ -98,7 +101,9 @@ test(
|
||||
|
||||
// Navigate to templates
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 30000,
|
||||
@ -116,13 +121,13 @@ test(
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.waitFor({ state: "visible", timeout: 10000 });
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.dblclick();
|
||||
|
||||
@ -141,13 +146,13 @@ test(
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.waitFor({ state: "visible", timeout: 10000 });
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.dblclick();
|
||||
|
||||
@ -177,10 +182,10 @@ test(
|
||||
.waitFor({ state: "visible", timeout: 5000 });
|
||||
await page.getByTestId("more-options-button_folder-alpha").click();
|
||||
await page.getByTestId("btn-delete-project").click();
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
|
||||
// Verify success message
|
||||
await expect(page.getByText("Project deleted successfully")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.toastProjectDeleted)).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
@ -208,9 +213,9 @@ test(
|
||||
.waitFor({ state: "visible", timeout: 5000 });
|
||||
await page.getByTestId("more-options-button_folder-beta").click();
|
||||
await page.getByTestId("btn-delete-project").click();
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
|
||||
await expect(page.getByText("Project deleted successfully")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.toastProjectDeleted)).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
},
|
||||
@ -224,7 +229,9 @@ test(
|
||||
|
||||
// Navigate to templates
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 30000,
|
||||
@ -242,13 +249,13 @@ test(
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.waitFor({ state: "visible", timeout: 10000 });
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.dblclick();
|
||||
|
||||
@ -270,9 +277,9 @@ test(
|
||||
.waitFor({ state: "visible", timeout: 5000 });
|
||||
await page.getByTestId("more-options-button_folder-one").click();
|
||||
await page.getByTestId("btn-delete-project").click();
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
|
||||
await expect(page.getByText("Project deleted successfully")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.toastProjectDeleted)).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
@ -286,13 +293,13 @@ test(
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.waitFor({ state: "visible", timeout: 10000 });
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.dblclick();
|
||||
|
||||
@ -317,9 +324,9 @@ test(
|
||||
.waitFor({ state: "visible", timeout: 5000 });
|
||||
await page.getByTestId("more-options-button_folder-two").click();
|
||||
await page.getByTestId("btn-delete-project").click();
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
|
||||
await expect(page.getByText("Project deleted successfully")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.toastProjectDeleted)).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
},
|
||||
@ -378,10 +385,10 @@ test(
|
||||
}
|
||||
|
||||
await page.getByTestId("btn-delete-project").click();
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
|
||||
// Wait for deletion to complete
|
||||
await expect(page.getByText("Project deleted successfully")).toBeVisible({
|
||||
await expect(page.getByText(TEXTS.toastProjectDeleted)).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
@ -403,9 +410,32 @@ test(
|
||||
|
||||
await page.getByTestId("new_project_btn_empty_page").click();
|
||||
|
||||
// The empty-state CTA can either open the templates modal directly
|
||||
// (EmptyPageCommunity) or surface the FlowBuilderWelcome overlay
|
||||
// (EmptyFolder → useStartNewFlow). Race both and click "Browse more"
|
||||
// when the overlay shows up so we always end up on the templates modal.
|
||||
await Promise.race([
|
||||
page.waitForSelector('[data-testid="modal-title"]', { timeout: 30000 }),
|
||||
page.waitForSelector('[data-testid="flow-builder-welcome-panel"]', {
|
||||
timeout: 30000,
|
||||
}),
|
||||
]);
|
||||
if (
|
||||
(await page
|
||||
.locator('[data-testid="flow-builder-welcome-panel"]')
|
||||
.count()) > 0
|
||||
) {
|
||||
await page.getByTestId("flow-builder-welcome-browse-more").click();
|
||||
await page.waitForSelector('[data-testid="modal-title"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
}
|
||||
|
||||
// Navigate to templates
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 30000,
|
||||
@ -422,8 +452,10 @@ test(
|
||||
// Verify we can click on the folder and see the flow
|
||||
await page.getByTestId("sidebar-nav-Starter Project").click();
|
||||
|
||||
// The folder should contain our newly created flow
|
||||
await expect(page.getByTestId("list-card")).toBeVisible({
|
||||
// The folder should contain our newly created flow. Templates render an
|
||||
// extra example list-card alongside the user's flow when the folder is
|
||||
// freshly created, so scope to the first match to satisfy strict mode.
|
||||
await expect(page.getByTestId("list-card").first()).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
},
|
||||
|
||||
@ -3,6 +3,7 @@ import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { renameFlow } from "../../utils/rename-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"CRUD folders",
|
||||
{ tag: ["@release", "@api"] },
|
||||
@ -11,33 +12,32 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await page.getByTestId("icon-ChevronLeft").first().click();
|
||||
await page.getByPlaceholder("Search flows").first().isVisible();
|
||||
await page.getByText("Flows").first().isVisible();
|
||||
if (await page.getByText("Components").first().isVisible()) {
|
||||
await page.getByText("Components").first().isVisible();
|
||||
await expect(page.getByPlaceholder("Search flows").first()).toBeVisible();
|
||||
await expect(page.getByText("Flows").first()).toBeVisible();
|
||||
if (await page.getByText(TEXTS.labelComponents).first().isVisible()) {
|
||||
await expect(page.getByText(TEXTS.labelComponents).first()).toBeVisible();
|
||||
} else {
|
||||
await page.getByText("MCP Server").first().isVisible();
|
||||
await expect(page.getByText("MCP Server").first()).toBeVisible();
|
||||
}
|
||||
await page.getByText("All").first().isVisible();
|
||||
await page.getByText("Select All").first().isVisible();
|
||||
|
||||
await page.getByTestId("add-project-button").click();
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.dblclick();
|
||||
|
||||
@ -62,8 +62,8 @@ test(
|
||||
await page.getByTestId("more-options-button_new-project-test-name").click();
|
||||
|
||||
await page.getByTestId("btn-delete-project").click();
|
||||
await page.getByText("Delete").last().click();
|
||||
await expect(page.getByText("Project deleted successfully")).toBeVisible({
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
await expect(page.getByText(TEXTS.toastProjectDeleted)).toBeVisible({
|
||||
timeout: 3000,
|
||||
});
|
||||
},
|
||||
@ -138,7 +138,9 @@ test("change flow folder", async ({ page }) => {
|
||||
// unique so our assertions can't collide with any template that
|
||||
// Starter ships with by default.
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 100000,
|
||||
@ -155,12 +157,12 @@ test("change flow folder", async ({ page }) => {
|
||||
await page.getByTestId("add-project-button").click();
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.waitFor({ state: "visible", timeout: 10000 });
|
||||
await page
|
||||
.locator("[data-testid='project-sidebar']")
|
||||
.getByText("New Project")
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last()
|
||||
.dblclick();
|
||||
await page.getByTestId("input-project").fill(destinationProjectName);
|
||||
|
||||
@ -6,6 +6,7 @@ import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user must be able to freeze a path",
|
||||
{ tag: ["@release", "@workspace", "@components"] },
|
||||
@ -31,7 +32,9 @@ test(
|
||||
}
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
@ -40,7 +43,7 @@ test(
|
||||
const randomSeed1 = Math.random().toString(36).substring(2, 10);
|
||||
const randomSeed2 = Math.random().toString(36).substring(2, 10);
|
||||
|
||||
await page.getByText("Chat Input", { exact: true }).click();
|
||||
await page.getByText(TEXTS.componentChatInput, { exact: true }).click();
|
||||
|
||||
await page
|
||||
.getByTestId("textarea_str_input_value")
|
||||
@ -57,7 +60,7 @@ test(
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
@ -67,13 +70,13 @@ test(
|
||||
.click();
|
||||
|
||||
const randomTextGeneratedByAI = await page
|
||||
.getByPlaceholder("Empty")
|
||||
.getByPlaceholder(TEXTS.placeholderEmpty)
|
||||
.first()
|
||||
.inputValue();
|
||||
|
||||
await page.getByText("Close").last().click();
|
||||
await page.getByText(TEXTS.close).last().click();
|
||||
|
||||
await page.getByText("Chat Input", { exact: true }).click();
|
||||
await page.getByText(TEXTS.componentChatInput, { exact: true }).click();
|
||||
|
||||
// Use a completely different prompt to ensure different output
|
||||
await page
|
||||
@ -88,7 +91,7 @@ test(
|
||||
});
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
@ -98,15 +101,15 @@ test(
|
||||
.click();
|
||||
|
||||
const secondRandomTextGeneratedByAI = await page
|
||||
.getByPlaceholder("Empty")
|
||||
.getByPlaceholder(TEXTS.placeholderEmpty)
|
||||
.first()
|
||||
.inputValue();
|
||||
|
||||
await page.getByText("Close").last().click();
|
||||
await page.getByText(TEXTS.close).last().click();
|
||||
|
||||
const languageModelNode = page
|
||||
.locator(".react-flow__node", {
|
||||
has: page.getByText("Language Model", { exact: true }),
|
||||
has: page.getByText(TEXTS.componentLanguageModel, { exact: true }),
|
||||
})
|
||||
.last();
|
||||
|
||||
@ -133,7 +136,7 @@ test(
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
@ -143,11 +146,11 @@ test(
|
||||
.click();
|
||||
|
||||
const thirdRandomTextGeneratedByAI = await page
|
||||
.getByPlaceholder("Empty")
|
||||
.getByPlaceholder(TEXTS.placeholderEmpty)
|
||||
.first()
|
||||
.inputValue();
|
||||
|
||||
await page.getByText("Close").last().click();
|
||||
await page.getByText(TEXTS.close).last().click();
|
||||
|
||||
// The frozen path should return the cached (second) result, not generate new output
|
||||
expect(secondRandomTextGeneratedByAI).toEqual(thirdRandomTextGeneratedByAI);
|
||||
|
||||
@ -4,6 +4,7 @@ import { addLegacyComponents } from "../../utils/add-legacy-components";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user must be able to freeze a component",
|
||||
{ tag: ["@release", "@workspace", "@components"] },
|
||||
@ -24,7 +25,7 @@ test(
|
||||
await addLegacyComponents(page);
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("text input");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchTextInput);
|
||||
await page.waitForSelector('[data-testid="input_outputText Input"]', {
|
||||
timeout: 1000,
|
||||
});
|
||||
@ -45,11 +46,13 @@ test(
|
||||
|
||||
await page.getByTestId("output-inspection-output text-textinput").click();
|
||||
|
||||
const firstOutputText = await page.getByPlaceholder("Empty").textContent();
|
||||
const firstOutputText = await page
|
||||
.getByPlaceholder(TEXTS.placeholderEmpty)
|
||||
.textContent();
|
||||
|
||||
expect(firstOutputText).toBe("hello world");
|
||||
|
||||
await page.getByText("Close").last().click();
|
||||
await page.getByText(TEXTS.close).last().click();
|
||||
|
||||
await page.getByTestId("textarea_str_input_value").fill("goodbye world");
|
||||
|
||||
@ -76,7 +79,9 @@ test(
|
||||
|
||||
await page.getByTestId("output-inspection-output text-textinput").click();
|
||||
|
||||
const secondOutputText = await page.getByPlaceholder("Empty").textContent();
|
||||
const secondOutputText = await page
|
||||
.getByPlaceholder(TEXTS.placeholderEmpty)
|
||||
.textContent();
|
||||
|
||||
expect(secondOutputText).toBe("goodbye world");
|
||||
},
|
||||
|
||||
@ -5,6 +5,7 @@ import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user must be able to save or delete a global variable",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
@ -17,7 +18,9 @@ test(
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("openai");
|
||||
await page
|
||||
.getByTestId("sidebar-search-input")
|
||||
.fill(TEXTS.providerOpenAiSearch);
|
||||
|
||||
await page.waitForSelector('[data-testid="openaiOpenAI"]', {
|
||||
timeout: 1000,
|
||||
@ -46,7 +49,7 @@ test(
|
||||
await page.getByTestId("icon-Globe").nth(0).click();
|
||||
await page.getByText("Add New Variable", { exact: true }).click();
|
||||
await page
|
||||
.getByPlaceholder("Enter a name for the variable...")
|
||||
.getByPlaceholder(TEXTS.placeholderVariableName)
|
||||
.fill(genericName);
|
||||
await page.getByText("Generic", { exact: true }).first().isVisible();
|
||||
await page
|
||||
@ -58,7 +61,7 @@ test(
|
||||
|
||||
await page.getByText("Add New Variable", { exact: true }).click();
|
||||
await page
|
||||
.getByPlaceholder("Enter a name for the variable...")
|
||||
.getByPlaceholder(TEXTS.placeholderVariableName)
|
||||
.fill(credentialName);
|
||||
await page.getByTestId("credential-tab").click();
|
||||
await page
|
||||
@ -73,7 +76,7 @@ test(
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await page.getByTestId("icon-Trash2").last().click();
|
||||
await page.getByText("Delete", { exact: true }).nth(1).click();
|
||||
await page.getByText(TEXTS.delete, { exact: true }).nth(1).click();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
import { test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
test.describe("group node test", () => {
|
||||
/// <reference lib="dom"/>
|
||||
// TODO: fix this test
|
||||
test.skip(
|
||||
"group and ungroup updating values",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page
|
||||
.getByRole("heading", { name: "Basic Prompting" })
|
||||
.first()
|
||||
.click();
|
||||
await page.getByTestId("fit_view").first().click();
|
||||
|
||||
await page.getByTestId("title-OpenAI").click();
|
||||
await page
|
||||
.getByTestId("title-OpenAI")
|
||||
.click({ modifiers: ["ControlOrMeta"] });
|
||||
await page
|
||||
.getByTestId("title-Prompt Template")
|
||||
.click({ modifiers: ["ControlOrMeta"] });
|
||||
await page
|
||||
.getByTestId("title-OpenAI")
|
||||
.click({ modifiers: ["ControlOrMeta"] });
|
||||
|
||||
await page.getByRole("button", { name: "Group" }).click();
|
||||
await page.getByTestId("title-Group").click();
|
||||
await page.getByTestId("edit-name-description-button").click();
|
||||
await page.getByTestId("input-title-Group").first().fill("test");
|
||||
await page.getByTestId("save-name-description-button").first().click();
|
||||
await page.keyboard.press("ControlOrMeta+g");
|
||||
await page.getByTestId("title-OpenAI").isVisible();
|
||||
await page.getByTestId("title-Prompt Template").isVisible();
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test.describe("ModelInputComponent", () => {
|
||||
test(
|
||||
"should display model selector in a node with model input",
|
||||
@ -16,7 +17,7 @@ test.describe("ModelInputComponent", () => {
|
||||
|
||||
// Search for OpenAI component which has model input
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("OpenAI");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.providerOpenAi);
|
||||
|
||||
// Wait for search results
|
||||
await page.waitForTimeout(500);
|
||||
@ -54,7 +55,7 @@ test.describe("ModelInputComponent", () => {
|
||||
});
|
||||
|
||||
// Add an OpenAI model node
|
||||
await page.getByTestId("sidebar-search-input").fill("OpenAI");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.providerOpenAi);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const openaiComponent = page.getByTestId("modelsOpenAI").first();
|
||||
@ -93,7 +94,7 @@ test.describe("ModelInputComponent", () => {
|
||||
});
|
||||
|
||||
// Add a model component
|
||||
await page.getByTestId("sidebar-search-input").fill("OpenAI");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.providerOpenAi);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const openaiComponent = page.getByTestId("modelsOpenAI").first();
|
||||
@ -133,7 +134,7 @@ test.describe("ModelInputComponent", () => {
|
||||
});
|
||||
|
||||
// Add a model component
|
||||
await page.getByTestId("sidebar-search-input").fill("OpenAI");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.providerOpenAi);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const openaiComponent = page.getByTestId("modelsOpenAI").first();
|
||||
@ -175,7 +176,7 @@ test.describe("ModelInputComponent", () => {
|
||||
});
|
||||
|
||||
// Add a model component
|
||||
await page.getByTestId("sidebar-search-input").fill("OpenAI");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.providerOpenAi);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const openaiComponent = page.getByTestId("modelsOpenAI").first();
|
||||
@ -212,7 +213,7 @@ test.describe("ModelInputComponent", () => {
|
||||
});
|
||||
|
||||
// Add a model component
|
||||
await page.getByTestId("sidebar-search-input").fill("OpenAI");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.providerOpenAi);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const openaiComponent = page.getByTestId("modelsOpenAI").first();
|
||||
|
||||
@ -1,184 +0,0 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
test.describe("ModelProviderCount Component", () => {
|
||||
test(
|
||||
"should open model provider page when navigating via settings",
|
||||
{ tag: ["@release", "@components", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
// Close the new project modal
|
||||
const closeButton = page
|
||||
.locator("button")
|
||||
.filter({ hasText: "Close" })
|
||||
.or(page.locator('button[aria-label="Close"]'))
|
||||
.or(page.locator('button[data-testid="close-button"]'))
|
||||
.first();
|
||||
await closeButton.click();
|
||||
|
||||
// Navigate to settings > Model Providers
|
||||
await page.getByTestId("user-profile-settings").click();
|
||||
await page.getByText("Settings").first().click();
|
||||
await page.getByText("Model Providers").first().click();
|
||||
|
||||
// Wait for the settings page header
|
||||
await page.waitForSelector('[data-testid="settings_menu_header"]', {
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
// Page should appear with "Model Providers" header
|
||||
await expect(
|
||||
page.getByTestId("settings_menu_header").last(),
|
||||
).toContainText("Model Providers", { timeout: 5000 });
|
||||
|
||||
// Page should contain provider configuration content
|
||||
await expect(
|
||||
page.getByText(
|
||||
"Configure AI model providers and manage their API keys.",
|
||||
),
|
||||
).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
"should navigate back from model provider page",
|
||||
{ tag: ["@release", "@components", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
const closeButton = page
|
||||
.locator("button")
|
||||
.filter({ hasText: "Close" })
|
||||
.or(page.locator('button[aria-label="Close"]'))
|
||||
.or(page.locator('button[data-testid="close-button"]'))
|
||||
.first();
|
||||
await closeButton.click();
|
||||
|
||||
// Navigate to settings > Model Providers
|
||||
await page.getByTestId("user-profile-settings").click();
|
||||
await page.getByText("Settings").first().click();
|
||||
await page.getByText("Model Providers").first().click();
|
||||
|
||||
// Verify page is open
|
||||
await expect(
|
||||
page.getByTestId("settings_menu_header").last(),
|
||||
).toContainText("Model Providers", { timeout: 5000 });
|
||||
|
||||
// Navigate back by clicking the back button
|
||||
await page.getByTestId("icon-ChevronLeft").first().click();
|
||||
|
||||
// Should be back at main view - the settings page header should change
|
||||
await expect(
|
||||
page.getByText(
|
||||
"Configure AI model providers and manage their API keys.",
|
||||
),
|
||||
).not.toBeVisible({ timeout: 3000 });
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
"should navigate to model provider page multiple times",
|
||||
{ tag: ["@release", "@components", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
const closeButton = page
|
||||
.locator("button")
|
||||
.filter({ hasText: "Close" })
|
||||
.or(page.locator('button[aria-label="Close"]'))
|
||||
.or(page.locator('button[data-testid="close-button"]'))
|
||||
.first();
|
||||
await closeButton.click();
|
||||
|
||||
// First navigation - open page
|
||||
await page.getByTestId("user-profile-settings").click();
|
||||
await page.getByText("Settings").first().click();
|
||||
await page.getByText("Model Providers").first().click();
|
||||
|
||||
await expect(
|
||||
page.getByTestId("settings_menu_header").last(),
|
||||
).toContainText("Model Providers", { timeout: 5000 });
|
||||
|
||||
// Navigate back
|
||||
await page.getByTestId("icon-ChevronLeft").first().click();
|
||||
await expect(
|
||||
page.getByText(
|
||||
"Configure AI model providers and manage their API keys.",
|
||||
),
|
||||
).not.toBeVisible({ timeout: 3000 });
|
||||
|
||||
// Second navigation - open page again
|
||||
await page.getByTestId("user-profile-settings").click();
|
||||
await page.getByText("Settings").first().click();
|
||||
await page.getByText("Model Providers").first().click();
|
||||
await expect(
|
||||
page.getByTestId("settings_menu_header").last(),
|
||||
).toContainText("Model Providers", { timeout: 5000 });
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
"should display provider list in the page",
|
||||
{ tag: ["@release", "@components", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
const closeButton = page
|
||||
.locator("button")
|
||||
.filter({ hasText: "Close" })
|
||||
.or(page.locator('button[aria-label="Close"]'))
|
||||
.or(page.locator('button[data-testid="close-button"]'))
|
||||
.first();
|
||||
await closeButton.click();
|
||||
|
||||
// Navigate to settings > Model Providers
|
||||
await page.getByTestId("user-profile-settings").click();
|
||||
await page.getByText("Settings").first().click();
|
||||
await page.getByText("Model Providers").first().click();
|
||||
|
||||
// Wait for page to be fully visible
|
||||
await expect(
|
||||
page.getByTestId("settings_menu_header").last(),
|
||||
).toContainText("Model Providers", { timeout: 5000 });
|
||||
|
||||
// The page should contain provider selection area with content
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Page should be properly structured with content
|
||||
await expect(page.locator("div").first()).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
"model provider page should display provider count information",
|
||||
{ tag: ["@release", "@components", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
const closeButton = page
|
||||
.locator("button")
|
||||
.filter({ hasText: "Close" })
|
||||
.or(page.locator('button[aria-label="Close"]'))
|
||||
.or(page.locator('button[data-testid="close-button"]'))
|
||||
.first();
|
||||
await closeButton.click();
|
||||
|
||||
// Navigate to settings > Model Providers
|
||||
await page.getByTestId("user-profile-settings").click();
|
||||
await page.getByText("Settings").first().click();
|
||||
await page.getByText("Model Providers").first().click();
|
||||
|
||||
// Page should display the header
|
||||
await expect(
|
||||
page.getByTestId("settings_menu_header").last(),
|
||||
).toContainText("Model Providers", { timeout: 5000 });
|
||||
|
||||
// Provider list content should be visible
|
||||
const providerList = page.getByTestId("provider-list");
|
||||
if (await providerList.isVisible({ timeout: 3000 })) {
|
||||
await expect(providerList).toBeVisible();
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -178,4 +178,35 @@ test.describe("ModelProviderModal", () => {
|
||||
).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
"should navigate to model provider page multiple times",
|
||||
{ tag: ["@release", "@components", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page, { skipModal: true });
|
||||
|
||||
// Wait for page to be ready
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// First navigation - open page
|
||||
await navigateSettingsPages(page, "Settings", "Model Providers");
|
||||
await expect(
|
||||
page.getByTestId("settings_menu_header").last(),
|
||||
).toContainText("Model Providers", { timeout: 5000 });
|
||||
|
||||
// Navigate back
|
||||
await page.getByTestId("icon-ChevronLeft").first().click();
|
||||
await expect(
|
||||
page.getByText(
|
||||
"Configure AI model providers and manage their API keys.",
|
||||
),
|
||||
).not.toBeVisible({ timeout: 3000 });
|
||||
|
||||
// Second navigation - open page again
|
||||
await navigateSettingsPages(page, "Settings", "Model Providers");
|
||||
await expect(
|
||||
page.getByTestId("settings_menu_header").last(),
|
||||
).toContainText("Model Providers", { timeout: 5000 });
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -1,68 +1,45 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
import { TID } from "../../utils/constants/testIds";
|
||||
import { TIMEOUTS } from "../../utils/constants/timeouts";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { addComponentFromSidebar } from "../../utils/flow/add-component-from-sidebar";
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
import { disableInspectPanel } from "../../utils/open-advanced-options";
|
||||
import { sessionMoreMenu } from "../../utils/playground/sessions";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"fresh start playground",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page }) => {
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
|
||||
await disableInspectPanel(page);
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat output");
|
||||
await page.waitForSelector('[data-testid="input_outputChat Output"]', {
|
||||
timeout: 100000,
|
||||
await addComponentFromSidebar(page, {
|
||||
search: "chat output",
|
||||
testId: "input_outputChat Output",
|
||||
hoverAdd: true,
|
||||
});
|
||||
|
||||
await page
|
||||
.getByTestId("input_outputChat Output")
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await page.getByTestId("add-component-button-chat-output").click();
|
||||
});
|
||||
|
||||
await zoomOut(page, 2);
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat input");
|
||||
await page.waitForSelector('[data-testid="input_outputChat Input"]', {
|
||||
timeout: 100000,
|
||||
await addComponentFromSidebar(page, {
|
||||
search: "chat input",
|
||||
testId: "input_outputChat Input",
|
||||
position: { x: 100, y: 100 },
|
||||
});
|
||||
|
||||
await page
|
||||
.getByTestId("input_outputChat Input")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'), {
|
||||
targetPosition: { x: 100, y: 100 },
|
||||
});
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("text output");
|
||||
await page.waitForSelector('[data-testid="input_outputText Output"]', {
|
||||
timeout: 100000,
|
||||
await addComponentFromSidebar(page, {
|
||||
search: "text output",
|
||||
testId: "input_outputText Output",
|
||||
position: { x: 300, y: 300 },
|
||||
});
|
||||
|
||||
await page
|
||||
.getByTestId("input_outputText Output")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'), {
|
||||
targetPosition: { x: 300, y: 300 },
|
||||
});
|
||||
|
||||
await adjustScreenView(page);
|
||||
|
||||
await page
|
||||
@ -78,14 +55,16 @@ test(
|
||||
.getByTestId("handle-chatoutput-noshownode-inputs-target")
|
||||
.click();
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
timeout: 100000,
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForSelector(`[data-testid="${TID.inputChatPlayground}"]`, {
|
||||
timeout: TIMEOUTS.componentMount,
|
||||
});
|
||||
|
||||
//send message
|
||||
await page.getByTestId("input-chat-playground").click();
|
||||
await page.getByTestId("input-chat-playground").fill("message 1");
|
||||
await page.getByTestId(TID.inputChatPlayground).click();
|
||||
await page.getByTestId(TID.inputChatPlayground).fill("message 1");
|
||||
await page.keyboard.press("Enter");
|
||||
await expect(page.getByTestId("chat-message-User-message 1")).toBeVisible();
|
||||
await expect(page.getByTestId("chat-message-AI-message 1")).toBeVisible();
|
||||
@ -119,63 +98,57 @@ test(
|
||||
await expect(page.getByTestId("chat-message-AI-edit_bot_1")).toBeVisible();
|
||||
|
||||
// check table messages view (use sidebar session more menu — header menu hidden in fullscreen)
|
||||
await page
|
||||
.locator('[data-testid^="session-"][data-testid$="-more-menu"]')
|
||||
.first()
|
||||
.click();
|
||||
await sessionMoreMenu(page, "first").click();
|
||||
await page.getByTestId("message-logs-option").click();
|
||||
await expect(page.getByText("Page 1 of 1", { exact: true })).toBeVisible();
|
||||
await page.getByRole("button", { name: "Close" }).click();
|
||||
await page.getByRole("button", { name: TEXTS.close }).click();
|
||||
|
||||
// create new session (use sidebar new-chat button)
|
||||
await page.getByTestId("new-chat").click();
|
||||
await page.getByTestId(TID.newChat).click();
|
||||
await expect(page.getByTitle("New Session 0")).toBeVisible();
|
||||
|
||||
// check rename session
|
||||
await page
|
||||
.getByTestId("input-chat-playground")
|
||||
.getByTestId(TID.inputChatPlayground)
|
||||
.fill("session_after_delete");
|
||||
await page.keyboard.press("Enter");
|
||||
await page
|
||||
.getByTestId("chat-message-User-session_after_delete")
|
||||
.isVisible();
|
||||
// Use sidebar session more menu for rename
|
||||
await page
|
||||
.locator('[data-testid^="session-"][data-testid$="-more-menu"]')
|
||||
.last()
|
||||
.click();
|
||||
await sessionMoreMenu(page, "last").click();
|
||||
await page.getByTestId("rename-session-option").click();
|
||||
await page.getByTestId("session-rename-input").fill("my first session");
|
||||
await page.keyboard.press("Enter");
|
||||
await expect(
|
||||
page.getByTestId("session-selector").getByText("my first session"),
|
||||
).toBeVisible();
|
||||
page
|
||||
.getByTestId(TID.sessionSelector)
|
||||
.filter({ hasText: "my first session" })
|
||||
.first(),
|
||||
).toBeVisible({ timeout: 10000 });
|
||||
|
||||
// check cancel rename (using Escape key)
|
||||
await page
|
||||
.locator('[data-testid^="session-"][data-testid$="-more-menu"]')
|
||||
.last()
|
||||
.click();
|
||||
await sessionMoreMenu(page, "last").click();
|
||||
await page.getByTestId("rename-session-option").click();
|
||||
await page.getByTestId("session-rename-input").fill("cancel name");
|
||||
await page.keyboard.press("Escape");
|
||||
await expect(
|
||||
page.getByTestId("session-selector").getByText("my first session"),
|
||||
).toBeVisible();
|
||||
page
|
||||
.getByTestId(TID.sessionSelector)
|
||||
.filter({ hasText: "my first session" })
|
||||
.first(),
|
||||
).toBeVisible({ timeout: 10000 });
|
||||
|
||||
// check delete session
|
||||
await page
|
||||
.locator('[data-testid^="session-"][data-testid$="-more-menu"]')
|
||||
.last()
|
||||
.click();
|
||||
await sessionMoreMenu(page, "last").click();
|
||||
await page.getByTestId("delete-session-option").click();
|
||||
await expect(page.getByTitle("Default Session")).toBeVisible();
|
||||
|
||||
//create new session
|
||||
await page.getByTestId("new-chat").click();
|
||||
await page.getByTestId("input-chat-playground").click();
|
||||
await page.getByTestId(TID.newChat).click();
|
||||
await page.getByTestId(TID.inputChatPlayground).click();
|
||||
await page
|
||||
.getByTestId("input-chat-playground")
|
||||
.getByTestId(TID.inputChatPlayground)
|
||||
.fill("session_after_delete");
|
||||
await page.keyboard.press("Enter");
|
||||
await expect(
|
||||
|
||||
@ -1,107 +1,85 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { ANIMATIONS, TIMEOUTS } from "../../utils/constants/timeouts";
|
||||
import { TID } from "../../utils/constants/testIds";
|
||||
import { addComponentFromSidebar } from "../../utils/flow/add-component-from-sidebar";
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user should be able to publish a flow",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page, context }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 5000,
|
||||
await openBlankFlow(page);
|
||||
await page.waitForSelector(`[data-testid="${TID.sidebarSearchInput}"]`, {
|
||||
timeout: TIMEOUTS.short,
|
||||
});
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 5000,
|
||||
await addComponentFromSidebar(page, {
|
||||
search: "chat input",
|
||||
testId: "input_outputChat Input",
|
||||
hoverAdd: true,
|
||||
});
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat input");
|
||||
|
||||
await page.waitForSelector('[data-testid="input_outputChat Input"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page
|
||||
.getByTestId("input_outputChat Input")
|
||||
.hover({ timeout: 3000 })
|
||||
.then(async () => {
|
||||
await page
|
||||
.getByTestId("add-component-button-chat-input")
|
||||
.last()
|
||||
.click();
|
||||
});
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await adjustScreenView(page, { numberOfZoomOut: 3 });
|
||||
await page.getByTestId("publish-button").click();
|
||||
await page.getByTestId(TID.publishButton).click();
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
await page.waitForSelector('[data-testid="shareable-playground"]', {
|
||||
timeout: 10000,
|
||||
await page.waitForSelector(`[data-testid="${TID.shareablePlayground}"]`, {
|
||||
timeout: TIMEOUTS.medium,
|
||||
});
|
||||
|
||||
try {
|
||||
await page.waitForTimeout(2000);
|
||||
await expect(page.getByTestId(TID.publishSwitch)).toBeVisible({
|
||||
timeout: TIMEOUTS.medium,
|
||||
});
|
||||
|
||||
await expect(page.getByTestId("publish-switch")).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error waiting for publish operation:", error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.getByTestId("publish-switch").click();
|
||||
await page.getByTestId(TID.publishSwitch).click();
|
||||
const pagePromise = context.waitForEvent("page");
|
||||
await page.waitForTimeout(ANIMATIONS.publishTogglePropagation);
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.getByTestId("shareable-playground").click();
|
||||
await page.getByTestId(TID.shareablePlayground).click();
|
||||
const newPage = await pagePromise;
|
||||
await newPage.waitForLoadState("domcontentloaded");
|
||||
|
||||
// Wait for the chat input to actually be present before filling. The
|
||||
// default actionTimeout (20s) was not enough on Windows CI for the
|
||||
// shareable-playground page to mount the message input.
|
||||
await newPage
|
||||
.getByPlaceholder("Send a message...")
|
||||
.waitFor({ state: "visible", timeout: 60000 });
|
||||
.getByPlaceholder(TEXTS.placeholderSendMessage)
|
||||
.waitFor({ state: "visible", timeout: TIMEOUTS.long });
|
||||
const newUrl = newPage.url();
|
||||
await newPage.getByPlaceholder("Send a message...").fill("Hello");
|
||||
await newPage.getByTestId("button-send").last().click();
|
||||
await newPage.getByPlaceholder(TEXTS.placeholderSendMessage).fill("Hello");
|
||||
await newPage.getByTestId(TID.buttonSend).last().click();
|
||||
|
||||
const stopButton = newPage.getByRole("button", { name: "Stop" });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
const stopButton = newPage.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "visible", timeout: TIMEOUTS.standard });
|
||||
|
||||
await newPage.close();
|
||||
await page.bringToFront();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId("publish-button").click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId("publish-switch").click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId(TID.publishButton).click();
|
||||
await page.getByTestId(TID.publishSwitch).click();
|
||||
await expect(page.getByTestId("rf__wrapper")).toBeVisible();
|
||||
await expect(page.getByTestId("publish-switch")).toBeChecked({
|
||||
await expect(page.getByTestId(TID.publishSwitch)).toBeChecked({
|
||||
checked: false,
|
||||
});
|
||||
await expect(page.getByTestId("rf__wrapper")).toBeVisible();
|
||||
|
||||
// The publish-switch toggle is confirmed in the UI above, but the
|
||||
// un-publish has to reach the backend before the shareable URL stops
|
||||
// resolving — give it time to propagate.
|
||||
await page.waitForTimeout(ANIMATIONS.publishTogglePropagation);
|
||||
|
||||
await page.goto(newUrl);
|
||||
await page.waitForTimeout(2000);
|
||||
try {
|
||||
await expect(page.getByTestId("mainpage_title")).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
} catch (_error) {
|
||||
await page.reload();
|
||||
await expect(page.getByTestId("mainpage_title")).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
}
|
||||
|
||||
// An un-published playground URL redirects to the projects page:
|
||||
// PlaygroundPage detects access_type !== "PUBLIC" and navigates to
|
||||
// "/". The redirect is client-side and the subsequent app bootstrap
|
||||
// can be slow on CI, so wait for the URL to leave /playground/
|
||||
// before asserting the projects page rendered.
|
||||
await page.waitForURL((url) => !url.pathname.startsWith("/playground/"), {
|
||||
timeout: TIMEOUTS.long,
|
||||
});
|
||||
await expect(page.getByTestId(TID.mainpageTitle)).toBeVisible({
|
||||
timeout: TIMEOUTS.long,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user can open component dropdown menu by right-clicking on nodes",
|
||||
{ tag: ["@release", "@components", "@dropdown", "@right-click"] },
|
||||
@ -10,7 +11,9 @@ test(
|
||||
// Start with a basic template that has multiple components
|
||||
if (await page.getByTestId("components-btn").isVisible()) {
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
}
|
||||
|
||||
await page.getByTestId("template-get-started-card-basic-prompting").click();
|
||||
@ -29,7 +32,7 @@ test(
|
||||
});
|
||||
|
||||
// Test 1: Right-click on Chat Input component should open dropdown immediately (single click)
|
||||
const chatInputComponent = page.getByText("Chat Input").first();
|
||||
const chatInputComponent = page.getByText(TEXTS.componentChatInput).first();
|
||||
|
||||
// First, click somewhere else to ensure no component is selected
|
||||
await page.click("body", { position: { x: 100, y: 100 } });
|
||||
|
||||
@ -5,6 +5,7 @@ import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user should be able to use Run Flow without any issues",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
@ -22,7 +23,7 @@ test(
|
||||
await page.getByTestId("blank-flow").click();
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat output");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatOutput);
|
||||
await page.waitForSelector('[data-testid="input_outputChat Output"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
@ -37,7 +38,7 @@ test(
|
||||
await zoomOut(page, 2);
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat input");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatInput);
|
||||
await page.waitForSelector('[data-testid="input_outputChat Input"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
@ -49,7 +50,7 @@ test(
|
||||
});
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("text output");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchTextOutput);
|
||||
await page.waitForSelector('[data-testid="input_outputText Output"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
@ -77,7 +78,7 @@ test(
|
||||
|
||||
await page.getByTestId("icon-ChevronLeft").click();
|
||||
|
||||
await page.getByText("New Flow").isVisible();
|
||||
await expect(page.getByText("New Flow")).toBeVisible();
|
||||
await page.getByTestId("new-project-btn").click();
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
@ -116,7 +117,7 @@ test(
|
||||
.fill("THIS IS A TEST FOR RUN FLOW COMPONENT");
|
||||
|
||||
await page.getByTestId("button_run_run flow").click();
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
@ -127,7 +128,9 @@ test(
|
||||
|
||||
await page.locator('[data-testid^="output-inspection-"]').first().click();
|
||||
|
||||
const value = await page.getByPlaceholder("Empty").inputValue();
|
||||
const value = await page
|
||||
.getByPlaceholder(TEXTS.placeholderEmpty)
|
||||
.inputValue();
|
||||
|
||||
expect(value).toBe("THIS IS A TEST FOR RUN FLOW COMPONENT");
|
||||
},
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
import { readFileSync } from "fs";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
test.describe("save component tests", () => {
|
||||
/// <reference lib="dom"/>
|
||||
test.skip(
|
||||
"save group component tests",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"tests/assets/flow_group_test.json",
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
// Create the DataTransfer and File
|
||||
const dataTransfer = await page.evaluateHandle((data) => {
|
||||
const dt = new DataTransfer();
|
||||
// Convert the buffer to a hex array
|
||||
const file = new File([data], "flow_group_test.json", {
|
||||
type: "application/json",
|
||||
});
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
}, jsonContent);
|
||||
|
||||
// Now dispatch
|
||||
await page.dispatchEvent(
|
||||
"//*[@data-testid='rf__wrapper']/div[1]/div",
|
||||
"drop",
|
||||
{
|
||||
dataTransfer,
|
||||
},
|
||||
);
|
||||
|
||||
const genericNoda = page.getByTestId("div-generic-node");
|
||||
const elementCount = await genericNoda?.count();
|
||||
if (elementCount > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
||||
await adjustScreenView(page, { numberOfZoomOut: 2 });
|
||||
|
||||
await page.getByTestId("title-Agent Initializer").click({
|
||||
modifiers: ["Control"],
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Group" }).click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]')
|
||||
.first()
|
||||
.click({ button: "left" });
|
||||
|
||||
let textArea = page.getByTestId("div-textarea-description");
|
||||
let elementCountText = await textArea?.count();
|
||||
if (elementCountText > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
||||
let groupNode = page.getByTestId("title-Group");
|
||||
let elementGroup = await groupNode?.count();
|
||||
if (elementGroup > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.getByTestId("title-Group").click();
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
|
||||
await page.getByTestId("icon-SaveAll").click();
|
||||
// timeout to handle case where there is already a saved component with the same name
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const replaceButton = await page
|
||||
.getByTestId("replace-button")
|
||||
.isVisible();
|
||||
|
||||
if (replaceButton) {
|
||||
await page.getByTestId("replace-button").click();
|
||||
}
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("group");
|
||||
|
||||
await page
|
||||
.getByText("Group")
|
||||
.first()
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page.getByTestId("fit_view").click();
|
||||
textArea = page.getByTestId("div-textarea-description");
|
||||
elementCountText = await textArea?.count();
|
||||
if (elementCountText > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
||||
groupNode = page.getByTestId("title-Group");
|
||||
elementGroup = await groupNode?.count();
|
||||
if (elementGroup > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -1,84 +1,29 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
|
||||
/**
|
||||
* Helper: create Basic Prompting flow, configure GPT, publish,
|
||||
* and open the shareable playground in a new tab.
|
||||
*/
|
||||
async function setupShareablePlayground(page: any, context: any): Promise<any> {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByTestId("publish-button").click();
|
||||
await page.waitForSelector('[data-testid="shareable-playground"]', {
|
||||
timeout: 10000,
|
||||
});
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("publish-switch").click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
const pagePromise = context.waitForEvent("page");
|
||||
await page.getByTestId("shareable-playground").click();
|
||||
const newPage = await pagePromise;
|
||||
await newPage.waitForTimeout(3000);
|
||||
|
||||
return newPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: send message and wait for build to complete.
|
||||
* Uses the same pattern as publish-flow.spec.ts (Stop button lifecycle).
|
||||
*/
|
||||
async function sendAndWaitForResponse(playgroundPage: any, message: string) {
|
||||
// Wait for the chat input to be present. The default actionTimeout (20s)
|
||||
// was not enough on Windows CI for the shareable-playground page to mount
|
||||
// the message input.
|
||||
await playgroundPage
|
||||
.getByPlaceholder("Send a message...")
|
||||
.waitFor({ state: "visible", timeout: 60000 });
|
||||
await playgroundPage.getByPlaceholder("Send a message...").fill(message);
|
||||
await playgroundPage.getByTestId("button-send").last().click();
|
||||
|
||||
// Wait for Stop button to appear (build started)
|
||||
const stopButton = playgroundPage.getByRole("button", { name: "Stop" });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
|
||||
// Wait for Stop button to disappear (build complete)
|
||||
await stopButton.waitFor({ state: "hidden", timeout: 120000 });
|
||||
}
|
||||
import { TID } from "../../utils/constants/testIds";
|
||||
import { TIMEOUTS } from "../../utils/constants/timeouts";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { publishBasicPromptingAndOpenShareablePlayground } from "../../utils/playground/publish-and-open-shareable";
|
||||
import { sendPlaygroundMessage } from "../../utils/playground/send-playground-message";
|
||||
|
||||
test(
|
||||
"shareable playground: auto-login user can send message and get response",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page, context }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
const { playgroundPage } =
|
||||
await publishBasicPromptingAndOpenShareablePlayground(page, context);
|
||||
|
||||
const playgroundPage = await setupShareablePlayground(page, context);
|
||||
|
||||
await sendAndWaitForResponse(playgroundPage, "Say hello");
|
||||
await sendPlaygroundMessage(playgroundPage, "Say hello", {
|
||||
surface: "shareable",
|
||||
});
|
||||
|
||||
// After build complete, at least one chat message should be visible
|
||||
await expect(
|
||||
playgroundPage.locator('[data-testid="div-chat-message"]').first(),
|
||||
).toBeVisible({ timeout: 10000 });
|
||||
playgroundPage.locator(`[data-testid="${TID.chatMessage}"]`).first(),
|
||||
).toBeVisible({ timeout: TIMEOUTS.medium });
|
||||
|
||||
await playgroundPage.close();
|
||||
},
|
||||
@ -88,40 +33,19 @@ test(
|
||||
"shareable playground: streaming works",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page, context }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
const { playgroundPage } =
|
||||
await publishBasicPromptingAndOpenShareablePlayground(page, context);
|
||||
|
||||
const playgroundPage = await setupShareablePlayground(page, context);
|
||||
|
||||
// Wait for the chat input to be present (Windows CI is slow to mount it).
|
||||
await playgroundPage
|
||||
.getByPlaceholder("Send a message...")
|
||||
.waitFor({ state: "visible", timeout: 60000 });
|
||||
await playgroundPage
|
||||
.getByPlaceholder("Send a message...")
|
||||
.fill("Tell me a short joke");
|
||||
await playgroundPage.getByTestId("button-send").last().click();
|
||||
|
||||
// Stop button should appear during build (streaming active)
|
||||
await playgroundPage.waitForSelector('[data-testid="button-stop"]', {
|
||||
timeout: 30000,
|
||||
await sendPlaygroundMessage(playgroundPage, "Tell me a short joke", {
|
||||
surface: "shareable",
|
||||
});
|
||||
|
||||
// Wait for stop button to disappear (streaming finished)
|
||||
await playgroundPage.waitForSelector('[data-testid="button-stop"]', {
|
||||
state: "detached",
|
||||
timeout: 120000,
|
||||
});
|
||||
|
||||
// Send button should be back
|
||||
// After stop button disappears the send button should be back
|
||||
await expect(
|
||||
playgroundPage.getByTestId("button-send").last(),
|
||||
playgroundPage.getByTestId(TID.buttonSend).last(),
|
||||
).toBeVisible();
|
||||
|
||||
await playgroundPage.close();
|
||||
@ -132,31 +56,26 @@ test(
|
||||
"shareable playground: session management works",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page, context }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
const { playgroundPage } =
|
||||
await publishBasicPromptingAndOpenShareablePlayground(page, context);
|
||||
|
||||
const playgroundPage = await setupShareablePlayground(page, context);
|
||||
|
||||
await sendAndWaitForResponse(playgroundPage, "Session test");
|
||||
await sendPlaygroundMessage(playgroundPage, "Session test", {
|
||||
surface: "shareable",
|
||||
});
|
||||
|
||||
// Create new session
|
||||
await playgroundPage.getByTestId("new-chat").click();
|
||||
await playgroundPage.waitForTimeout(2000);
|
||||
await playgroundPage.getByTestId(TID.newChat).click();
|
||||
|
||||
// New session should be created — at least "Default Session" + new one
|
||||
// Check that the new-chat button is still clickable (UI didn't crash)
|
||||
await expect(playgroundPage.getByTestId("new-chat")).toBeVisible();
|
||||
// New session should be created and the UI should not crash
|
||||
await expect(playgroundPage.getByTestId(TID.newChat)).toBeVisible();
|
||||
|
||||
// Verify at least one session-selector exists
|
||||
await expect(
|
||||
playgroundPage.getByTestId("session-selector").first(),
|
||||
).toBeVisible({ timeout: 5000 });
|
||||
playgroundPage.getByTestId(TID.sessionSelector).first(),
|
||||
).toBeVisible({ timeout: TIMEOUTS.medium });
|
||||
|
||||
await playgroundPage.close();
|
||||
},
|
||||
|
||||
@ -1,161 +1,86 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
|
||||
// These tests require the server to run with AUTO_LOGIN=FALSE.
|
||||
// When the server runs with AUTO_LOGIN=TRUE (default for local dev),
|
||||
// the backend uses client_id instead of user_id for session isolation,
|
||||
// and persistence features are not active.
|
||||
// Set LANGFLOW_AUTO_LOGIN=false in your .env to run these tests.
|
||||
|
||||
/**
|
||||
* Helper: mock auto-login as disabled and log in manually.
|
||||
*/
|
||||
async function setupAutoLoginOff(page: any) {
|
||||
await page.route("**/api/v1/auto_login", (route: any) => {
|
||||
route.fulfill({
|
||||
status: 500,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ detail: { auto_login: false } }),
|
||||
});
|
||||
});
|
||||
import type { Page } from "@playwright/test";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { mockAutoLoginDisabled } from "../../utils/auth/mock-auto-login-disabled";
|
||||
import { TID } from "../../utils/constants/testIds";
|
||||
import { TIMEOUTS } from "../../utils/constants/timeouts";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { publishBasicPromptingAndOpenShareablePlayground } from "../../utils/playground/publish-and-open-shareable";
|
||||
import { sendPlaygroundMessage } from "../../utils/playground/send-playground-message";
|
||||
import { sessionMoreMenu } from "../../utils/playground/sessions";
|
||||
|
||||
await page.addInitScript(() => {
|
||||
window.process = window.process || ({} as any);
|
||||
const newEnv = {
|
||||
...(window.process as any).env,
|
||||
LANGFLOW_AUTO_LOGIN: "false",
|
||||
};
|
||||
Object.defineProperty(window.process, "env", {
|
||||
value: newEnv,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
});
|
||||
sessionStorage.setItem("testMockAutoLogin", "true");
|
||||
});
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
/**
|
||||
* Stub auto-login, navigate to the sign-in page, log in manually.
|
||||
*/
|
||||
async function setupAutoLoginOff(page: Page): Promise<void> {
|
||||
await mockAutoLoginDisabled(page);
|
||||
|
||||
await page.goto("/");
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
|
||||
await page.getByPlaceholder("Username").fill("langflow");
|
||||
await page.getByPlaceholder("Password").fill("langflow");
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderPassword)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.removeItem("testMockAutoLogin");
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Sign In" }).click();
|
||||
await page.getByRole("button", { name: TEXTS.signIn }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="mainpage_title"]', {
|
||||
timeout: 30000,
|
||||
await page.waitForSelector(`[data-testid="${TID.mainpageTitle}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: create Basic Prompting flow, configure GPT, publish,
|
||||
* and return the shareable playground URL.
|
||||
*/
|
||||
async function createPublishAndGetUrl(
|
||||
page: any,
|
||||
context: any,
|
||||
): Promise<string> {
|
||||
await page.waitForSelector('[id="new-project-btn"]', { timeout: 30000 });
|
||||
|
||||
await awaitBootstrapTest(page, { skipGoto: true });
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Build first
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
// Publish
|
||||
await page.getByTestId("publish-button").click();
|
||||
await page.waitForSelector('[data-testid="shareable-playground"]', {
|
||||
timeout: 10000,
|
||||
});
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("publish-switch").click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// Get URL
|
||||
const pagePromise = context.waitForEvent("page");
|
||||
await page.getByTestId("shareable-playground").click();
|
||||
const newPage = await pagePromise;
|
||||
await newPage.waitForTimeout(2000);
|
||||
const url = newPage.url();
|
||||
await newPage.close();
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: send a message and wait for the build to complete.
|
||||
*/
|
||||
async function sendMessageAndWait(page: any, message: string) {
|
||||
await page.getByPlaceholder("Send a message...").fill(message);
|
||||
await page.getByTestId("button-send").last().click();
|
||||
|
||||
// Wait for Stop button lifecycle (build started → completed)
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
await stopButton.waitFor({ state: "hidden", timeout: 120000 });
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
}
|
||||
|
||||
test(
|
||||
"shareable playground: logged-in user messages persist after page refresh",
|
||||
{ tag: ["@release", "@api", "@database"] },
|
||||
async ({ page, context }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
test.skip(
|
||||
process?.env?.LANGFLOW_AUTO_LOGIN !== "false",
|
||||
"Server must run with AUTO_LOGIN=FALSE for persistence tests",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
skipIfMissing.openAiKey();
|
||||
skipIfMissing.autoLoginDisabled();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
await setupAutoLoginOff(page);
|
||||
const playgroundUrl = await createPublishAndGetUrl(page, context);
|
||||
const { url: playgroundUrl, playgroundPage } =
|
||||
await publishBasicPromptingAndOpenShareablePlayground(page, context, {
|
||||
skipBootstrap: true,
|
||||
});
|
||||
await playgroundPage.close();
|
||||
|
||||
// Navigate to shareable playground
|
||||
await page.goto(playgroundUrl);
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 30000,
|
||||
await page.waitForSelector(`[data-testid="${TID.buttonSend}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
|
||||
// Send message
|
||||
await sendMessageAndWait(page, "persist test");
|
||||
await sendPlaygroundMessage(page, "persist test", {
|
||||
surface: "shareable",
|
||||
});
|
||||
|
||||
// Should have messages
|
||||
const messagesBefore = await page
|
||||
.locator('[data-testid="div-chat-message"]')
|
||||
.locator(`[data-testid="${TID.chatMessage}"]`)
|
||||
.count();
|
||||
expect(messagesBefore).toBeGreaterThanOrEqual(2);
|
||||
|
||||
// Refresh
|
||||
await page.reload();
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 30000,
|
||||
await page.waitForSelector(`[data-testid="${TID.buttonSend}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Messages should still be visible
|
||||
const messagesAfter = await page
|
||||
.locator('[data-testid="div-chat-message"]')
|
||||
.locator(`[data-testid="${TID.chatMessage}"]`)
|
||||
.count();
|
||||
expect(messagesAfter).toBeGreaterThanOrEqual(2);
|
||||
},
|
||||
@ -165,37 +90,31 @@ test(
|
||||
"shareable playground: default session appears first",
|
||||
{ tag: ["@release", "@api", "@database"] },
|
||||
async ({ page, context }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
test.skip(
|
||||
process?.env?.LANGFLOW_AUTO_LOGIN !== "false",
|
||||
"Server must run with AUTO_LOGIN=FALSE for persistence tests",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
skipIfMissing.openAiKey();
|
||||
skipIfMissing.autoLoginDisabled();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
await setupAutoLoginOff(page);
|
||||
const playgroundUrl = await createPublishAndGetUrl(page, context);
|
||||
const { url: playgroundUrl, playgroundPage } =
|
||||
await publishBasicPromptingAndOpenShareablePlayground(page, context, {
|
||||
skipBootstrap: true,
|
||||
});
|
||||
await playgroundPage.close();
|
||||
|
||||
await page.goto(playgroundUrl);
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 30000,
|
||||
await page.waitForSelector(`[data-testid="${TID.buttonSend}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
|
||||
// Send message in default session
|
||||
await sendMessageAndWait(page, "default session msg");
|
||||
await sendPlaygroundMessage(page, "default session msg", {
|
||||
surface: "shareable",
|
||||
});
|
||||
|
||||
// Create new session
|
||||
await page.getByTestId("new-chat").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId(TID.newChat).click();
|
||||
|
||||
// First session should be Default Session
|
||||
const firstSession = page.getByTestId("session-selector").first();
|
||||
const firstSession = page.getByTestId(TID.sessionSelector).first();
|
||||
await expect(firstSession).toContainText("Default Session");
|
||||
},
|
||||
);
|
||||
@ -204,60 +123,47 @@ test(
|
||||
"shareable playground: delete session persists after refresh",
|
||||
{ tag: ["@release", "@api", "@database"] },
|
||||
async ({ page, context }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
test.skip(
|
||||
process?.env?.LANGFLOW_AUTO_LOGIN !== "false",
|
||||
"Server must run with AUTO_LOGIN=FALSE for persistence tests",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
skipIfMissing.openAiKey();
|
||||
skipIfMissing.autoLoginDisabled();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
await setupAutoLoginOff(page);
|
||||
const playgroundUrl = await createPublishAndGetUrl(page, context);
|
||||
const { url: playgroundUrl, playgroundPage } =
|
||||
await publishBasicPromptingAndOpenShareablePlayground(page, context, {
|
||||
skipBootstrap: true,
|
||||
});
|
||||
await playgroundPage.close();
|
||||
|
||||
await page.goto(playgroundUrl);
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 30000,
|
||||
await page.waitForSelector(`[data-testid="${TID.buttonSend}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
|
||||
// Send message
|
||||
await sendMessageAndWait(page, "keep this");
|
||||
await sendPlaygroundMessage(page, "keep this", { surface: "shareable" });
|
||||
|
||||
// Create new session and send message
|
||||
await page.getByTestId("new-chat").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await sendMessageAndWait(page, "delete this");
|
||||
// Create new session and send a message in it
|
||||
await page.getByTestId(TID.newChat).click();
|
||||
await sendPlaygroundMessage(page, "delete this", { surface: "shareable" });
|
||||
|
||||
const sessionsBefore = await page.getByTestId("session-selector").count();
|
||||
const sessionsBefore = await page.getByTestId(TID.sessionSelector).count();
|
||||
|
||||
// Delete last session
|
||||
await page
|
||||
.locator('[data-testid^="session-"][data-testid$="-more-menu"]')
|
||||
.last()
|
||||
.click();
|
||||
await sessionMoreMenu(page, "last").click();
|
||||
await page.getByTestId("delete-session-option").click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
const sessionsAfterDelete = await page
|
||||
.getByTestId("session-selector")
|
||||
.getByTestId(TID.sessionSelector)
|
||||
.count();
|
||||
expect(sessionsAfterDelete).toBeLessThan(sessionsBefore);
|
||||
|
||||
// Refresh
|
||||
await page.reload();
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 30000,
|
||||
await page.waitForSelector(`[data-testid="${TID.buttonSend}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
const sessionsAfterRefresh = await page
|
||||
.getByTestId("session-selector")
|
||||
.getByTestId(TID.sessionSelector)
|
||||
.count();
|
||||
expect(sessionsAfterRefresh).toBeLessThanOrEqual(sessionsAfterDelete);
|
||||
},
|
||||
@ -267,57 +173,45 @@ test(
|
||||
"shareable playground: rename session persists after refresh",
|
||||
{ tag: ["@release", "@api", "@database"] },
|
||||
async ({ page, context }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
test.skip(
|
||||
process?.env?.LANGFLOW_AUTO_LOGIN !== "false",
|
||||
"Server must run with AUTO_LOGIN=FALSE for persistence tests",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
skipIfMissing.openAiKey();
|
||||
skipIfMissing.autoLoginDisabled();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
await setupAutoLoginOff(page);
|
||||
const playgroundUrl = await createPublishAndGetUrl(page, context);
|
||||
const { url: playgroundUrl, playgroundPage } =
|
||||
await publishBasicPromptingAndOpenShareablePlayground(page, context, {
|
||||
skipBootstrap: true,
|
||||
});
|
||||
await playgroundPage.close();
|
||||
|
||||
await page.goto(playgroundUrl);
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 30000,
|
||||
await page.waitForSelector(`[data-testid="${TID.buttonSend}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
|
||||
// Create new session and send message
|
||||
await page.getByTestId("new-chat").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await sendMessageAndWait(page, "rename test");
|
||||
await page.getByTestId(TID.newChat).click();
|
||||
await sendPlaygroundMessage(page, "rename test", { surface: "shareable" });
|
||||
|
||||
// Rename session
|
||||
await page
|
||||
.locator('[data-testid^="session-"][data-testid$="-more-menu"]')
|
||||
.last()
|
||||
.click();
|
||||
await sessionMoreMenu(page, "last").click();
|
||||
await page.getByTestId("rename-session-option").click();
|
||||
await page.getByTestId("session-rename-input").fill("Custom Name");
|
||||
await page.keyboard.press("Enter");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await expect(
|
||||
page.getByTestId("session-selector").getByText("Custom Name"),
|
||||
).toBeVisible({ timeout: 5000 });
|
||||
page.getByTestId(TID.sessionSelector).getByText("Custom Name"),
|
||||
).toBeVisible({ timeout: TIMEOUTS.medium });
|
||||
|
||||
// Refresh
|
||||
await page.reload();
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 30000,
|
||||
await page.waitForSelector(`[data-testid="${TID.buttonSend}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Renamed session should persist
|
||||
await expect(
|
||||
page.getByTestId("session-selector").getByText("Custom Name"),
|
||||
).toBeVisible({ timeout: 10000 });
|
||||
page.getByTestId(TID.sessionSelector).getByText("Custom Name"),
|
||||
).toBeVisible({ timeout: TIMEOUTS.medium });
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,70 +1,39 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { TID } from "../../utils/constants/testIds";
|
||||
import { TIMEOUTS } from "../../utils/constants/timeouts";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { buildFlowAndWait } from "../../utils/flow/build-flow-and-wait";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { publishBasicPromptingAndOpenShareablePlayground } from "../../utils/playground/publish-and-open-shareable";
|
||||
import { sendPlaygroundMessage } from "../../utils/playground/send-playground-message";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"shareable playground: bot messages display token usage",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
async ({ page, context }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
const { playgroundPage } =
|
||||
await publishBasicPromptingAndOpenShareablePlayground(page, context);
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Build first
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
// Publish
|
||||
await page.getByTestId("publish-button").click();
|
||||
await page.waitForSelector('[data-testid="shareable-playground"]', {
|
||||
timeout: 10000,
|
||||
await sendPlaygroundMessage(playgroundPage, "Say hi", {
|
||||
surface: "shareable",
|
||||
});
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("publish-switch").click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
const pagePromise = context.waitForEvent("page");
|
||||
await page.getByTestId("shareable-playground").click();
|
||||
const newPage = await pagePromise;
|
||||
await newPage.waitForTimeout(3000);
|
||||
|
||||
// Send message
|
||||
await newPage.getByPlaceholder("Send a message...").fill("Say hi");
|
||||
await newPage.getByTestId("button-send").last().click();
|
||||
|
||||
// Wait for build to complete (Stop button lifecycle)
|
||||
const stopButton = newPage.getByRole("button", { name: "Stop" });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
await stopButton.waitFor({ state: "hidden", timeout: 120000 });
|
||||
|
||||
// Wait for UI to settle
|
||||
await newPage.waitForTimeout(3000);
|
||||
|
||||
// Token count should be visible (Coins icon indicates token display)
|
||||
await newPage.waitForSelector('[data-testid="icon-Coins"]', {
|
||||
timeout: 30000,
|
||||
await playgroundPage.waitForSelector(`[data-testid="${TID.iconCoins}"]`, {
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
const coinsIcons = await newPage
|
||||
.locator('[data-testid="icon-Coins"]')
|
||||
const coinsIcons = await playgroundPage
|
||||
.locator(`[data-testid="${TID.iconCoins}"]`)
|
||||
.count();
|
||||
expect(coinsIcons).toBeGreaterThan(0);
|
||||
|
||||
await newPage.close();
|
||||
await playgroundPage.close();
|
||||
},
|
||||
);
|
||||
|
||||
@ -72,48 +41,34 @@ test(
|
||||
"regular playground: Finished In with token display still works (regression)",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
|
||||
await openStarterProject(page, "Basic Prompting");
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Build
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
await buildFlowAndWait(page);
|
||||
|
||||
// Open regular playground
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
timeout: 10000,
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForSelector(`[data-testid="${TID.inputChatPlayground}"]`, {
|
||||
timeout: TIMEOUTS.medium,
|
||||
});
|
||||
|
||||
// Send message
|
||||
await page.getByTestId("input-chat-playground").click();
|
||||
await page.getByTestId("input-chat-playground").fill("Say hello briefly");
|
||||
await page.getByTestId(TID.inputChatPlayground).click();
|
||||
await page.getByTestId(TID.inputChatPlayground).fill("Say hello briefly");
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
// Wait for AI response
|
||||
await page.waitForFunction(
|
||||
() =>
|
||||
document.querySelectorAll('[data-testid="div-chat-message"]').length >=
|
||||
2,
|
||||
{ timeout: 120000 },
|
||||
{ timeout: TIMEOUTS.buildComplete },
|
||||
);
|
||||
|
||||
// "Finished in" should appear (regular playground specific)
|
||||
await expect(page.getByText("Finished in")).toBeVisible({
|
||||
timeout: 30000,
|
||||
timeout: TIMEOUTS.standard,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@ -7,6 +7,7 @@ import { removeOldApiKeys } from "../../utils/remove-old-api-keys";
|
||||
import { updateOldComponents } from "../../utils/update-old-components";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
// TODO: fix this test
|
||||
test(
|
||||
"user must be able to stop a building",
|
||||
@ -20,7 +21,7 @@ test(
|
||||
//first component
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("text input");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchTextInput);
|
||||
|
||||
await page
|
||||
.getByTestId("input_outputText Input")
|
||||
@ -32,7 +33,7 @@ test(
|
||||
//second component
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("url");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchUrl);
|
||||
|
||||
await page
|
||||
.getByTestId("data_sourceURL")
|
||||
@ -65,7 +66,7 @@ test(
|
||||
//fifth component
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat output");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatOutput);
|
||||
|
||||
await page
|
||||
.getByTestId("input_outputChat Output")
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { test } from "../../fixtures";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { renameFlow } from "../../utils/rename-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"should filter by tag",
|
||||
{ tag: ["@release", "@api"] },
|
||||
@ -28,14 +29,13 @@ test(
|
||||
});
|
||||
|
||||
await page
|
||||
.getByPlaceholder("Insert your API Key")
|
||||
.getByPlaceholder(TEXTS.placeholderApiKey)
|
||||
.fill(process.env.STORE_API_KEY ?? "");
|
||||
|
||||
await page.getByTestId("api-key-save-button-store").click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByText("Success! Your API Key has been saved.").isVisible();
|
||||
|
||||
await expect(page.getByText(TEXTS.toastApiKeySaved)).toBeVisible();
|
||||
await page.getByTestId("button-store").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
@ -66,7 +66,7 @@ test(
|
||||
await safeClick("tag-selector-Vector Store");
|
||||
await safeClick("tag-selector-Memory");
|
||||
|
||||
await page.getByText("Basic RAG").isVisible();
|
||||
await expect(page.getByText(TEXTS.templateBasicRag)).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
@ -91,14 +91,13 @@ test("should share component with share button", async ({ page }) => {
|
||||
});
|
||||
|
||||
await page
|
||||
.getByPlaceholder("Insert your API Key")
|
||||
.getByPlaceholder(TEXTS.placeholderApiKey)
|
||||
.fill(process.env.STORE_API_KEY ?? "");
|
||||
|
||||
await page.getByTestId("api-key-save-button-store").click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByText("Success! Your API Key has been saved.").isVisible();
|
||||
|
||||
await expect(page.getByText(TEXTS.toastApiKeySaved)).toBeVisible();
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
@ -114,7 +113,9 @@ test("should share component with share button", async ({ page }) => {
|
||||
const randomName = Math.random().toString(36).substring(2);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await renameFlow(page, { flowName: randomName });
|
||||
|
||||
@ -123,33 +124,32 @@ test("should share component with share button", async ({ page }) => {
|
||||
});
|
||||
|
||||
await page.getByTestId("shared-button-flow").first().click();
|
||||
await page.getByText("Name:").isVisible();
|
||||
await page.getByText("Description:").isVisible();
|
||||
await page.getByText("Set workflow status to public").isVisible();
|
||||
await expect(page.getByText("Name:")).toBeVisible();
|
||||
await expect(page.getByText("Description:")).toBeVisible();
|
||||
await expect(page.getByText("Set workflow status to public")).toBeVisible();
|
||||
await page
|
||||
.getByText(
|
||||
"Attention: API keys in specified fields are automatically removed upon sharing.",
|
||||
)
|
||||
.isVisible();
|
||||
await page.getByText("Export").first().isVisible();
|
||||
await page.getByText("Share Flow").first().isVisible();
|
||||
|
||||
await expect(page.getByText("Export").first()).toBeVisible();
|
||||
await expect(page.getByText("Share Flow").first()).toBeVisible();
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
await page.getByText("Agent").first().isVisible();
|
||||
await page.getByText("Memory").first().isVisible();
|
||||
await page.getByText("Chain").first().isVisible();
|
||||
await page.getByText("Vector Store").first().isVisible();
|
||||
await page.getByText("Prompt").last().isVisible();
|
||||
await expect(page.getByText("Agent").first()).toBeVisible();
|
||||
await expect(page.getByText("Memory").first()).toBeVisible();
|
||||
await expect(page.getByText("Chain").first()).toBeVisible();
|
||||
await expect(page.getByText("Vector Store").first()).toBeVisible();
|
||||
await expect(page.getByText("Prompt").last()).toBeVisible();
|
||||
await page.getByTestId("public-checkbox").isChecked();
|
||||
|
||||
const flowName = await page.getByTestId("input-flow-name").inputValue();
|
||||
const flowDescription = await page
|
||||
.getByPlaceholder("Flow description")
|
||||
.inputValue();
|
||||
await page.getByText(flowName).last().isVisible();
|
||||
await page.getByText(flowDescription).last().isVisible();
|
||||
await expect(page.getByText(flowName).last()).toBeVisible();
|
||||
await expect(page.getByText(flowDescription).last()).toBeVisible();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByText("Flow shared successfully").last().isVisible();
|
||||
await expect(page.getByText("Flow shared successfully").last()).toBeVisible();
|
||||
});
|
||||
|
||||
@ -6,6 +6,7 @@ import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { openAdvancedOptions } from "../../utils/open-advanced-options";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
/**
|
||||
* E2E coverage for the Native Structured Output feature on the Agent
|
||||
* component (CZL/MANUAL_TEST_NATIVE_STRUCTURED_OUTPUT.md). The tests
|
||||
@ -40,7 +41,10 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateSimpleAgent })
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
@ -84,7 +88,10 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateSimpleAgent })
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
@ -126,7 +133,10 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateSimpleAgent })
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test.describe("Token Usage Tracking", () => {
|
||||
test(
|
||||
"node badge should show token count after running an LLM flow",
|
||||
@ -21,7 +22,9 @@ test.describe("Token Usage Tracking", () => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
@ -29,7 +32,7 @@ test.describe("Token Usage Tracking", () => {
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
@ -73,7 +76,9 @@ test.describe("Token Usage Tracking", () => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
@ -81,7 +86,7 @@ test.describe("Token Usage Tracking", () => {
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
test.describe("group node test", () => {
|
||||
/// <reference lib="dom"/>
|
||||
// TODO: fix this test
|
||||
test.skip(
|
||||
"group and ungroup updating values",
|
||||
{ tag: ["@release", "@workspace", "@components"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page
|
||||
.getByRole("heading", { name: "Basic Prompting" })
|
||||
.first()
|
||||
.click();
|
||||
await page.getByTestId("fit_view").first().click();
|
||||
|
||||
await page
|
||||
.getByTestId("title-OpenAI")
|
||||
.click({ modifiers: ["ControlOrMeta"] });
|
||||
await page
|
||||
.getByTestId("title-Prompt Template")
|
||||
.click({ modifiers: ["ControlOrMeta"] });
|
||||
|
||||
await page.getByRole("button", { name: "Group" }).click();
|
||||
await page.getByTestId("title-Group").click();
|
||||
await expect(page.getByTestId("tool-mode-button")).toBeHidden();
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -3,6 +3,7 @@ import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"should able to see and interact with Traces",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
@ -31,7 +32,9 @@ test(
|
||||
response.status() === 201,
|
||||
{ timeout: 120000 },
|
||||
);
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await flowCreatePromise;
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
@ -99,7 +102,9 @@ test.skip(
|
||||
response.status() === 201,
|
||||
{ timeout: 120000 },
|
||||
);
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await flowCreatePromise;
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
|
||||
@ -2,6 +2,7 @@ import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"curl_api_generation",
|
||||
{ tag: ["@release", "@workspace", "@api"] },
|
||||
@ -10,7 +11,9 @@ test(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
// Wait for the new-flow Loading state to clear before checking the
|
||||
// publish button — the canvas mounts only after the flow finishes
|
||||
// loading, which can outlast a 20s action timeout on Windows CI.
|
||||
@ -33,7 +36,7 @@ test(
|
||||
expect(clipboardContent.length).toBeGreaterThan(0);
|
||||
await page.getByTestId("tweaks-button").click();
|
||||
await page
|
||||
.getByRole("heading", { name: "Language Model" })
|
||||
.getByRole("heading", { name: TEXTS.componentLanguageModel })
|
||||
.locator("div")
|
||||
.first()
|
||||
.click();
|
||||
@ -44,7 +47,7 @@ test(
|
||||
|
||||
await page.getByTestId("showstream").first().click();
|
||||
|
||||
await page.getByText("Close").last().click();
|
||||
await page.getByText(TEXTS.close).last().click();
|
||||
|
||||
await page.getByTestId("api_tab_curl").click();
|
||||
await page.getByTestId("icon-Copy").click();
|
||||
@ -56,7 +59,7 @@ test(
|
||||
expect(oldValue).not.toBe(newValue);
|
||||
expect(clipboardContent2.length).toBeGreaterThan(clipboardContent.length);
|
||||
await awaitBootstrapTest(page, { skipModal: true });
|
||||
await page.getByText("Basic Prompting").first().click();
|
||||
await page.getByText(TEXTS.templateBasicPrompting).first().click();
|
||||
await page.getByTestId("publish-button").click();
|
||||
await page.getByTestId("api-access-item").click();
|
||||
expect(
|
||||
@ -119,7 +122,7 @@ test("check if tweaks are updating when someothing on the flow changes", async (
|
||||
await page.getByText("collection_name_test_123123123!@#$&*(&%$@").isVisible();
|
||||
await page.getByText("persist_directory_123123123!@#$&*(&%$@").isVisible();
|
||||
|
||||
await page.getByText("Close").last().click();
|
||||
await page.getByText(TEXTS.close).last().click();
|
||||
|
||||
await page.getByText("Python", { exact: true }).click();
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { renameFlow } from "../../utils/rename-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"flow state should be properly cleaned up between user sessions",
|
||||
{ tag: ["@release", "@api", "@database"] },
|
||||
@ -43,9 +44,15 @@ test(
|
||||
|
||||
// Log in as admin and create test user
|
||||
await page.goto("/");
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.getByPlaceholder("Username").fill("langflow");
|
||||
await page.getByPlaceholder("Password").fill("langflow");
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderPassword)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.removeItem("testMockAutoLogin");
|
||||
});
|
||||
@ -55,7 +62,7 @@ test(
|
||||
response.url().includes("/api/v1/login") && response.status() === 200,
|
||||
{ timeout: 60000 },
|
||||
),
|
||||
page.getByRole("button", { name: "Sign In" }).click(),
|
||||
page.getByRole("button", { name: TEXTS.signIn }).click(),
|
||||
]);
|
||||
|
||||
// mainpage_title only renders after the homepage data finishes loading,
|
||||
@ -66,13 +73,16 @@ test(
|
||||
await page.getByTestId("user-profile-settings").click();
|
||||
await page.getByText("Admin Page", { exact: true }).click();
|
||||
await page.getByText("New User", { exact: true }).click();
|
||||
await page.getByPlaceholder("Username").last().fill(userAName);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.last()
|
||||
.fill(userAName);
|
||||
await page.locator('input[name="password"]').fill(userAPassword);
|
||||
await page.locator('input[name="confirmpassword"]').fill(userAPassword);
|
||||
await page.waitForSelector("#is_active", { timeout: 1500 });
|
||||
await page.locator("#is_active").click();
|
||||
await expect(page.locator("#is_active")).toBeChecked();
|
||||
await page.getByText("Save", { exact: true }).click();
|
||||
await page.getByText(TEXTS.save, { exact: true }).click();
|
||||
await page.waitForSelector("text=new user added", { timeout: 30000 });
|
||||
|
||||
// Log out from admin
|
||||
@ -84,14 +94,16 @@ test(
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.setItem("testMockAutoLogin", "true");
|
||||
});
|
||||
await page.getByText("Logout", { exact: true }).click();
|
||||
await page.getByText(TEXTS.logout, { exact: true }).click();
|
||||
|
||||
// ---- USER A SESSION ----
|
||||
|
||||
// Log in as User A
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.getByPlaceholder("Username").fill(userAName);
|
||||
await page.getByPlaceholder("Password").fill(userAPassword);
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByPlaceholder(TEXTS.placeholderUsername).fill(userAName);
|
||||
await page.getByPlaceholder(TEXTS.placeholderPassword).fill(userAPassword);
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.removeItem("testMockAutoLogin");
|
||||
});
|
||||
@ -101,7 +113,7 @@ test(
|
||||
response.url().includes("/api/v1/login") && response.status() === 200,
|
||||
{ timeout: 60000 },
|
||||
),
|
||||
page.getByRole("button", { name: "Sign In" }).click(),
|
||||
page.getByRole("button", { name: TEXTS.signIn }).click(),
|
||||
]);
|
||||
|
||||
// Create a flow for User A
|
||||
@ -159,14 +171,20 @@ test(
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.setItem("testMockAutoLogin", "true");
|
||||
});
|
||||
await page.getByText("Logout", { exact: true }).click();
|
||||
await page.getByText(TEXTS.logout, { exact: true }).click();
|
||||
|
||||
// ---- ADMIN SESSION AGAIN ----
|
||||
|
||||
// Log in as admin again
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.getByPlaceholder("Username").fill("langflow");
|
||||
await page.getByPlaceholder("Password").fill("langflow");
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderPassword)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.removeItem("testMockAutoLogin");
|
||||
});
|
||||
@ -176,7 +194,7 @@ test(
|
||||
response.url().includes("/api/v1/login") && response.status() === 200,
|
||||
{ timeout: 60000 },
|
||||
),
|
||||
page.getByRole("button", { name: "Sign In" }).click(),
|
||||
page.getByRole("button", { name: TEXTS.signIn }).click(),
|
||||
]);
|
||||
|
||||
// Verify admin can't see User A's flow
|
||||
|
||||
@ -5,6 +5,7 @@ import { addNewUserAndLogin } from "../../utils/add-new-user-and-loggin";
|
||||
import { cleanAllFlows } from "../../utils/clean-all-flows";
|
||||
import { cleanOldFolders } from "../../utils/clean-old-folders";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"admin user must be able to track their progress in getting started",
|
||||
{ tag: ["@release", "@api"] },
|
||||
@ -81,7 +82,9 @@ async function progressTrackTestFn(
|
||||
await page.getByTestId("new_project_btn_empty_page").click();
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
timeout: 100000,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
// TODO: Need to review the voice assistant vs text to voice
|
||||
test.skip(
|
||||
"should able to see and interact with voice assistant",
|
||||
@ -29,7 +30,9 @@ test.skip(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
await expect(page.getByTestId("voice-button")).toBeVisible();
|
||||
@ -95,7 +98,9 @@ test.skip(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
await expect(page.getByTestId("voice-button")).not.toBeVisible();
|
||||
@ -123,7 +128,9 @@ test.skip(
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
await expect(page.getByTestId("voice-button")).toBeVisible();
|
||||
|
||||
@ -1,43 +1,34 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
import { buildFlowAndWait } from "../../utils/flow/build-flow-and-wait";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Basic Prompting (Hello, World)",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Basic Prompting");
|
||||
|
||||
await initialGPTsetup(page);
|
||||
await buildFlowAndWait(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByText("No input message provided.", { exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText(TEXTS.labelNoInputMessage, { exact: true })
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
//create a new session - default session can not be deleted
|
||||
await page.getByTestId("new-chat").click();
|
||||
await page.getByTitle("New Session 0").isVisible();
|
||||
|
||||
await expect(page.getByTitle("New Session 0")).toBeVisible();
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
@ -57,16 +48,35 @@ withEventDeliveryModes(
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await page.getByText("matey").last().isVisible();
|
||||
await expect(page.getByText("matey").last()).toBeVisible();
|
||||
|
||||
await page.getByText("timestamp", { exact: true }).last().isVisible();
|
||||
await page.getByText("text", { exact: true }).last().isVisible();
|
||||
await page.getByText("sender", { exact: true }).last().isVisible();
|
||||
await page.getByText("sender_name", { exact: true }).last().isVisible();
|
||||
await page.getByText("session_id", { exact: true }).last().isVisible();
|
||||
await page.getByText("files", { exact: true }).last().isVisible();
|
||||
// Open the message logs table view to verify metadata columns
|
||||
// (timestamp/text/sender/...). The header chat-menu is hidden in
|
||||
// fullscreen, so click the sidebar session more-menu instead.
|
||||
await page
|
||||
.locator('[data-testid^="session-"][data-testid$="-more-menu"]')
|
||||
.last()
|
||||
.click();
|
||||
await page.getByTestId("message-logs-option").click();
|
||||
|
||||
await page.getByRole("gridcell").last().isVisible();
|
||||
await expect(
|
||||
page.getByText("timestamp", { exact: true }).last(),
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("text", { exact: true }).last()).toBeVisible();
|
||||
await expect(
|
||||
page.getByText("sender", { exact: true }).last(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText("sender_name", { exact: true }).last(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText("session_id", { exact: true }).last(),
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("files", { exact: true }).last()).toBeVisible();
|
||||
await expect(page.getByRole("gridcell").last()).toBeVisible();
|
||||
|
||||
// Close the logs panel so the rest of the playground UI is reachable again.
|
||||
await page.getByRole("button", { name: TEXTS.close }).click();
|
||||
// Use sidebar session more menu (chat-header-more-menu is hidden in fullscreen)
|
||||
await page
|
||||
.locator('[data-testid^="session-"][data-testid$="-more-menu"]')
|
||||
@ -77,6 +87,8 @@ withEventDeliveryModes(
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await page.getByTestId("input-chat-playground").last().isVisible();
|
||||
await expect(
|
||||
page.getByTestId("input-chat-playground").last(),
|
||||
).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,27 +1,18 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Blog Writer",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Blog Writer" }).click();
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Blog Writer");
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
@ -51,11 +42,13 @@ withEventDeliveryModes(
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 30000 * 3,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByPlaceholder(
|
||||
"No chat input variables found. Click to run your flow.",
|
||||
@ -64,8 +57,8 @@ withEventDeliveryModes(
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
await page.getByText("turtles").last().isVisible();
|
||||
await page.getByText("sea").last().isVisible();
|
||||
await page.getByText("survival").last().isVisible();
|
||||
await expect(page.getByText("turtles").last()).toBeVisible();
|
||||
await expect(page.getByText("sea").last()).toBeVisible();
|
||||
await expect(page.getByText("survival").last()).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { getAllResponseMessage } from "../../utils/get-all-response-message";
|
||||
import { selectAnthropicModel } from "../../utils/select-anthropic-model";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Custom Component Generator",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
@ -14,11 +14,7 @@ withEventDeliveryModes(
|
||||
!process?.env?.ANTHROPIC_API_KEY,
|
||||
"ANTHROPIC_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
@ -44,7 +40,7 @@ withEventDeliveryModes(
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
const stopButton = page.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "hidden", timeout: 30000 * 3 });
|
||||
|
||||
const textContents = await getAllResponseMessage(page);
|
||||
|
||||
@ -1,28 +1,20 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { uploadFile } from "../../utils/upload-file";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
import { buildFlowAndWait } from "../../utils/flow/build-flow-and-wait";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Document Q&A",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Document Q&A" }).click();
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Document Q&A");
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await uploadFile(page, "test_file.txt");
|
||||
@ -30,13 +22,13 @@ withEventDeliveryModes(
|
||||
await page.waitForSelector('[data-testid="button_run_chat output"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
await buildFlowAndWait(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByText("No input message provided.", { exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText(TEXTS.labelNoInputMessage, { exact: true })
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
@ -56,7 +48,7 @@ withEventDeliveryModes(
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
await page.getByText("this is a test file").last().isVisible();
|
||||
expect(await page.getByTestId("div-chat-message).last().count()).toBe(1)"));
|
||||
await expect(page.getByText("this is a test file").last()).toBeVisible();
|
||||
expect(await page.getByTestId("div-chat-message").last().count()).toBe(1);
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
|
||||
test.skip(
|
||||
"Dynamic Agent",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
test.skip(
|
||||
!process?.env?.SEARCH_API_KEY,
|
||||
"SEARCH_API_KEY required to run this test",
|
||||
);
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Dynamic Agent" }).last().click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-api_key")
|
||||
.last()
|
||||
.fill(process.env.SEARCH_API_KEY ?? "");
|
||||
|
||||
await page
|
||||
.getByTestId("textarea_str_input_value")
|
||||
.first()
|
||||
.fill("how much is an apple stock today");
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
timeout: 60000 * 3,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page.waitForTimeout(1000);
|
||||
expect(page.getByText("apple").last()).toBeVisible();
|
||||
const textContents = await page
|
||||
.getByTestId("div-chat-message")
|
||||
.allTextContents();
|
||||
const concatAllText = textContents.join(" ");
|
||||
expect(concatAllText.toLocaleLowerCase()).toContain("apple");
|
||||
expect(concatAllText.toLocaleLowerCase()).not.toContain("error");
|
||||
expect(concatAllText.toLocaleLowerCase()).not.toContain("apologize");
|
||||
const allTextLength = concatAllText.length;
|
||||
expect(allTextLength).toBeGreaterThan(100);
|
||||
},
|
||||
);
|
||||
@ -1,74 +0,0 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
|
||||
withEventDeliveryModes(
|
||||
"Financial Report Parser",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page
|
||||
.getByRole("heading", { name: "Financial Report Parser" })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page.getByText("Parser", { exact: true }).last().click();
|
||||
|
||||
await page.getByTestId("tab_1_stringify").click();
|
||||
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page.getByTestId("button-send").click();
|
||||
|
||||
try {
|
||||
// Wait for the flow building indicator to appear and then disappear
|
||||
await page.waitForSelector('[data-testid="stop_building_button"]', {
|
||||
timeout: 30000,
|
||||
state: "visible",
|
||||
});
|
||||
await page.waitForSelector('[data-testid="stop_building_button"]', {
|
||||
timeout: 180000,
|
||||
state: "hidden",
|
||||
});
|
||||
} catch (_error) {
|
||||
console.error("Timeout error");
|
||||
test.skip(true, "Timeout error");
|
||||
}
|
||||
|
||||
// Wait for the chat response to appear
|
||||
await page.waitForSelector('[data-testid="div-chat-message"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
const textContents = await page
|
||||
.getByTestId("div-chat-message")
|
||||
.last()
|
||||
.allTextContents();
|
||||
const concatAllText = textContents.join(" ").toLowerCase();
|
||||
expect(concatAllText.length).toBeGreaterThan(10);
|
||||
expect(concatAllText).toContain("ebitda");
|
||||
},
|
||||
);
|
||||
@ -1,53 +0,0 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
|
||||
test.skip(
|
||||
"Hierarchical Tasks Agent",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
test.skip(
|
||||
!process?.env?.SEARCH_API_KEY,
|
||||
"SEARCH_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page
|
||||
.getByRole("heading", { name: "Hierarchical Tasks Agent" })
|
||||
.first()
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-api_key")
|
||||
.last()
|
||||
.fill(process.env.SEARCH_API_KEY ?? "");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
|
||||
expect(await page.locator(".markdown").count()).toBeGreaterThan(0);
|
||||
|
||||
expect(await page.getByText("Langflow").count()).toBeGreaterThan(2);
|
||||
},
|
||||
);
|
||||
@ -1,91 +0,0 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { getAllResponseMessage } from "../../utils/get-all-response-message";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
|
||||
withEventDeliveryModes(
|
||||
"Image Sentiment Analysis",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page
|
||||
.getByText("Image Sentiment Analysis", { exact: true })
|
||||
.last()
|
||||
.click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
//* TODO: Remove these 3 steps once the template is updated *//
|
||||
await page
|
||||
.getByTestId("handle-structuredoutput-shownode-structured output-right")
|
||||
.click();
|
||||
|
||||
await page.getByTestId("handle-parser-shownode-json or table-left").click();
|
||||
await page.getByTestId("tab_1_stringify").click();
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
// Upload image using the hidden file input
|
||||
const filePath = path.resolve(__dirname, "../../assets/chain.png");
|
||||
const fileInput = page.locator('input[type="file"]');
|
||||
await fileInput.setInputFiles(filePath);
|
||||
|
||||
// Wait for file preview to appear (shows loading then the image)
|
||||
await page.waitForSelector('img[alt="chain.png"]', { timeout: 30000 });
|
||||
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await page.getByTestId("button-send").click();
|
||||
|
||||
// Wait for the flow to complete
|
||||
try {
|
||||
await page.waitForSelector('[data-testid="stop_building_button"]', {
|
||||
timeout: 30000,
|
||||
state: "visible",
|
||||
});
|
||||
await page.waitForSelector('[data-testid="stop_building_button"]', {
|
||||
timeout: 180000,
|
||||
state: "hidden",
|
||||
});
|
||||
} catch (_error) {
|
||||
console.error("Timeout error");
|
||||
test.skip(true, "Timeout error");
|
||||
}
|
||||
|
||||
// Verify the image is visible in the chat messages after sending
|
||||
// Note: Server renames file with timestamp prefix (e.g., "2026-02-03_13-55-02_chain.png")
|
||||
await expect(page.locator('img[alt$="chain.png"]')).toBeVisible();
|
||||
|
||||
await page.waitForSelector('[data-testid="div-chat-message"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
const textContents = await getAllResponseMessage(page);
|
||||
expect(textContents.length).toBeGreaterThan(10);
|
||||
expect(textContents.toLowerCase()).toContain("sentiment");
|
||||
expect(textContents.toLowerCase()).toContain("neutral");
|
||||
expect(textContents.toLowerCase()).toContain("description");
|
||||
},
|
||||
);
|
||||
@ -1,36 +1,26 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { getAllResponseMessage } from "../../utils/get-all-response-message";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { unselectNodes } from "../../utils/unselect-nodes";
|
||||
import { waitForOpenModalWithChatInput } from "../../utils/wait-for-open-modal";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"Instagram Copywriter",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
test.skip(
|
||||
!process?.env?.TAVILY_API_KEY,
|
||||
"TAVILY_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Instagram Copywriter" }).click();
|
||||
await openStarterProject(page, "Instagram Copywriter");
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
@ -57,11 +47,13 @@ test(
|
||||
|
||||
await unselectNodes(page);
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 30000 * 2,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText("Create a Langflow post", { exact: true })
|
||||
.last()
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { unselectNodes } from "../../utils/unselect-nodes";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"Invoice Summarizer",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
@ -15,15 +15,8 @@ test(
|
||||
!process?.env?.NEEDLE_COLLECTION_ID,
|
||||
"OPENAI_API_KEY, NEEDLE_API_KEY, and NEEDLE_COLLECTION_ID required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Invoice Summarizer" }).click();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Invoice Summarizer");
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
@ -53,14 +46,18 @@ test(
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
|
||||
// Wait for the flow to build successfully
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 120000,
|
||||
});
|
||||
|
||||
// Switch to Playground
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
// Wait for the playground to be ready
|
||||
const inputPlaceholder = page
|
||||
.getByPlaceholder("Send a message...", { exact: true })
|
||||
.getByPlaceholder(TEXTS.placeholderSendMessage, { exact: true })
|
||||
.last();
|
||||
|
||||
await expect(inputPlaceholder).toBeVisible({ timeout: 10000 });
|
||||
|
||||
@ -1,36 +1,27 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { getAllResponseMessage } from "../../utils/get-all-response-message";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { disableInspectPanel } from "../../utils/open-advanced-options";
|
||||
import { unselectNodes } from "../../utils/unselect-nodes";
|
||||
import { waitForOpenModalWithChatInput } from "../../utils/wait-for-open-modal";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Market Research",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
skipIfMissing.openAiKey();
|
||||
test.skip(
|
||||
!process?.env?.TAVILY_API_KEY,
|
||||
"TAVILY_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Market Research" }).click();
|
||||
await openStarterProject(page, "Market Research");
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
@ -58,13 +49,15 @@ withEventDeliveryModes(
|
||||
await page.getByTestId("tab_1_stringify").click();
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 60000 * 3,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByText("No input message provided.", { exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText(TEXTS.labelNoInputMessage, { exact: true })
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
|
||||
@ -1,36 +1,28 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
import { buildFlowAndWait } from "../../utils/flow/build-flow-and-wait";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Memory Chatbot",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Memory Chatbot" }).click();
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Memory Chatbot");
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await buildFlowAndWait(page);
|
||||
|
||||
await page
|
||||
.getByText("No input message provided.", { exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByText(TEXTS.labelNoInputMessage, { exact: true })
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
withEventDeliveryModes(
|
||||
"News Aggregator",
|
||||
@ -13,21 +13,10 @@ withEventDeliveryModes(
|
||||
!process?.env?.AGENTQL_API_KEY,
|
||||
"AGENTQL_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
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") });
|
||||
}
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "News Aggregator" }).click();
|
||||
await openStarterProject(page, "News Aggregator");
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
|
||||
@ -1,33 +1,24 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Pokedex Agent",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Pokédex Agent" }).click();
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Pokédex Agent");
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
await page.getByTestId("input-chat-playground").isVisible();
|
||||
await expect(page.getByTestId("input-chat-playground")).toBeVisible();
|
||||
await page.getByTestId("input-chat-playground").click();
|
||||
await page
|
||||
.getByTestId("input-chat-playground")
|
||||
@ -35,7 +26,7 @@ withEventDeliveryModes(
|
||||
|
||||
await page.getByTestId("button-send").last().click();
|
||||
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
const stopButton = page.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 40000 });
|
||||
|
||||
if (await stopButton.isVisible()) {
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { uploadFile } from "../../utils/upload-file";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
|
||||
withEventDeliveryModes(
|
||||
"Portfolio Website Code Generator",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.ANTHROPIC_API_KEY,
|
||||
"ANTHROPIC_API_KEY required to run this test",
|
||||
);
|
||||
// TODO: remove this skip once the test is stabilized
|
||||
test.skip(true, "Skipping flaky test until it can be stabilized");
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page
|
||||
.getByRole("heading", { name: "Portfolio Website Code Generator" })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await initialGPTsetup(page, {
|
||||
skipAdjustScreenView: true,
|
||||
skipSelectGptModel: true,
|
||||
});
|
||||
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-api_key")
|
||||
.last()
|
||||
.fill(process.env.ANTHROPIC_API_KEY ?? "");
|
||||
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-api_key")
|
||||
.first()
|
||||
.fill(process.env.ANTHROPIC_API_KEY ?? "");
|
||||
|
||||
await uploadFile(page, "resume.txt");
|
||||
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page.getByTestId("button-send").click();
|
||||
|
||||
await page.waitForSelector('[data-testid="chat-code-tab"]', {
|
||||
timeout: 30000 * 3,
|
||||
});
|
||||
|
||||
await page.waitForSelector(".markdown", { timeout: 30000 });
|
||||
|
||||
const textContents = await page
|
||||
.locator(".markdown")
|
||||
.last()
|
||||
.allTextContents();
|
||||
|
||||
const concatAllText = textContents.join(" ").toLowerCase();
|
||||
|
||||
expect(concatAllText.length).toBeGreaterThan(200);
|
||||
|
||||
expect(concatAllText).toContain("div");
|
||||
expect(concatAllText).toContain("body");
|
||||
},
|
||||
);
|
||||
@ -1,111 +0,0 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
|
||||
withEventDeliveryModes(
|
||||
"Price Deal Finder",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.AGENTQL_API_KEY,
|
||||
"AGENTQL_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
test.skip(
|
||||
!process?.env?.TAVILY_API_KEY,
|
||||
"TAVILY_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Price Deal Finder" }).click();
|
||||
await adjustScreenView(page);
|
||||
|
||||
await initialGPTsetup(page, {
|
||||
skipAdjustScreenView: true,
|
||||
skipAddNewApiKeys: true,
|
||||
skipSelectGptModel: true,
|
||||
});
|
||||
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-api_key")
|
||||
.nth(0)
|
||||
.fill(process?.env?.TAVILY_API_KEY ?? "");
|
||||
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-api_key")
|
||||
.nth(1)
|
||||
.fill(process?.env?.AGENTQL_API_KEY ?? "");
|
||||
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-api_key")
|
||||
.nth(2)
|
||||
.fill(process?.env?.OPENAI_API_KEY ?? "");
|
||||
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
const product = randomProduct();
|
||||
|
||||
await page.getByTestId("input-chat-playground").fill(product);
|
||||
|
||||
await page.getByTestId("button-send").click();
|
||||
|
||||
try {
|
||||
await page.waitForSelector('[data-testid="button-stop"]', {
|
||||
timeout: 180000,
|
||||
state: "hidden",
|
||||
});
|
||||
} catch (_error) {
|
||||
console.error("Timeout error");
|
||||
test.skip(true, "Timeout error");
|
||||
}
|
||||
|
||||
await page.waitForSelector(".markdown", { timeout: 3000 });
|
||||
|
||||
const textContents = await page
|
||||
.locator(".markdown")
|
||||
.last()
|
||||
.allTextContents();
|
||||
|
||||
const concatAllText = textContents.join(" ").toLowerCase();
|
||||
|
||||
expect(concatAllText.length).toBeGreaterThan(100);
|
||||
|
||||
const zeldaChapter = product.split(" ")[1];
|
||||
expect(concatAllText).toContain(zeldaChapter);
|
||||
},
|
||||
);
|
||||
|
||||
const randomProduct = () => {
|
||||
const products = [
|
||||
"Zelda Tears of the Kingdom",
|
||||
"Zelda Ocarina of Time",
|
||||
"Zelda Majora's Mask",
|
||||
"Zelda The Wind Waker",
|
||||
"Zelda Twilight Princess",
|
||||
"Zelda Skyward Sword",
|
||||
"Zelda Breath of the Wild",
|
||||
"Zelda Link's Awakening",
|
||||
"Zelda Link to the Past",
|
||||
];
|
||||
|
||||
return products[Math.floor(Math.random() * products.length)].toLowerCase();
|
||||
};
|
||||
@ -1,30 +1,21 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { getAllResponseMessage } from "../../utils/get-all-response-message";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { waitForOpenModalWithChatInput } from "../../utils/wait-for-open-modal";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Prompt Chaining",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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") });
|
||||
}
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Prompt Chaining" }).click();
|
||||
await openStarterProject(page, "Prompt Chaining");
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
@ -33,11 +24,15 @@ withEventDeliveryModes(
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 60000 });
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByText("No input message provided.", { exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText(TEXTS.labelNoInputMessage, { exact: true })
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
|
||||
@ -1,24 +1,18 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { selectGptModel } from "../../utils/select-gpt-model";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Research Translation Loop.spec",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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") });
|
||||
}
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
@ -50,7 +44,7 @@ withEventDeliveryModes(
|
||||
|
||||
await page.getByTestId("button-send").click();
|
||||
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
const stopButton = page.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 40000 });
|
||||
|
||||
if (await stopButton.isVisible()) {
|
||||
|
||||
@ -1,43 +1,35 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { getAllResponseMessage } from "../../utils/get-all-response-message";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { waitForOpenModalWithoutChatInput } from "../../utils/wait-for-open-modal";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
import { buildFlowAndWait } from "../../utils/flow/build-flow-and-wait";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"SEO Keyword Generator",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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") });
|
||||
}
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "SEO Keyword Generator" }).click();
|
||||
await openStarterProject(page, "SEO Keyword Generator");
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await initialGPTsetup(page);
|
||||
await buildFlowAndWait(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByText("No input message provided.", { exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText(TEXTS.labelNoInputMessage, { exact: true })
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
|
||||
@ -1,43 +1,35 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { getAllResponseMessage } from "../../utils/get-all-response-message";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { waitForOpenModalWithoutChatInput } from "../../utils/wait-for-open-modal";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
import { buildFlowAndWait } from "../../utils/flow/build-flow-and-wait";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"SaaS Pricing",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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") });
|
||||
}
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "SaaS Pricing" }).click();
|
||||
await openStarterProject(page, "SaaS Pricing");
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await initialGPTsetup(page);
|
||||
await buildFlowAndWait(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByText("No input message provided.", { exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText(TEXTS.labelNoInputMessage, { exact: true })
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
|
||||
test.skip(
|
||||
"Sequential Task Agent",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page
|
||||
.getByRole("heading", { name: "Sequential Tasks Agent" })
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
|
||||
expect(await page.locator(".markdown").count()).toBeGreaterThan(0);
|
||||
|
||||
expect(await page.getByText("Agile").count()).toBeGreaterThan(0);
|
||||
},
|
||||
);
|
||||
@ -1,28 +1,25 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Simple Agent Memory",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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") });
|
||||
}
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
// Open Simple Agent template
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateSimpleAgent })
|
||||
.first()
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open Playground
|
||||
|
||||
@ -1,28 +1,18 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Simple Agent",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Simple Agent");
|
||||
await initialGPTsetup(page);
|
||||
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
@ -34,7 +24,7 @@ withEventDeliveryModes(
|
||||
|
||||
await page.getByTestId("button-send").last().click();
|
||||
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
const stopButton = page.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
|
||||
if (await stopButton.isVisible()) {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
function getRandomSocialMediaQuery(): string {
|
||||
const companies = [
|
||||
"OpenAI",
|
||||
@ -61,15 +61,8 @@ withEventDeliveryModes(
|
||||
!process?.env?.APIFY_API_TOKEN,
|
||||
"APIFY_API_TOKEN required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Social Media Agent" }).click();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Social Media Agent");
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
@ -98,7 +91,7 @@ withEventDeliveryModes(
|
||||
|
||||
await page.getByTestId("button-send").last().click();
|
||||
|
||||
const stopButton = page.getByRole("button", { name: "Stop" });
|
||||
const stopButton = page.getByRole("button", { name: TEXTS.stop });
|
||||
await stopButton.waitFor({ state: "visible", timeout: 30000 });
|
||||
|
||||
if (await stopButton.isVisible()) {
|
||||
|
||||
@ -1,25 +1,19 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { unselectNodes } from "../../utils/unselect-nodes";
|
||||
import { uploadFile } from "../../utils/upload-file";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"user should be able to analyze text sentiment",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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") });
|
||||
}
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
@ -39,9 +33,13 @@ withEventDeliveryModes(
|
||||
await page.getByText("Expand").click();
|
||||
await unselectNodes(page);
|
||||
await page.getByTestId("button_run_chat output").last().click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 120000,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText("Add a Chat Input component to your flow to send messages.", {
|
||||
exact: true,
|
||||
|
||||
@ -1,29 +1,22 @@
|
||||
import { type Page } from "@playwright/test";
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Travel Planning Agent",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
test.skip(
|
||||
!process?.env?.SEARCH_API_KEY,
|
||||
"SEARCH_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
@ -64,11 +57,13 @@ withEventDeliveryModes(
|
||||
test.skip();
|
||||
}
|
||||
|
||||
await page.waitForSelector("text=built successfully", {
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 60000 * 3,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector("text=default session", {
|
||||
timeout: 30000,
|
||||
|
||||
@ -1,25 +1,20 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { getAllResponseMessage } from "../../utils/get-all-response-message";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { waitForOpenModalWithoutChatInput } from "../../utils/wait-for-open-modal";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { buildFlowAndWait } from "../../utils/flow/build-flow-and-wait";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"Twitter Thread Generator",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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") });
|
||||
}
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
@ -37,13 +32,13 @@ withEventDeliveryModes(
|
||||
await page.getByTestId("title-Chat Output").click();
|
||||
await page.getByTestId("icon-MoreHorizontal").click();
|
||||
await page.getByText("Expand").click();
|
||||
await buildFlowAndWait(page);
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByText("No input message provided.", { exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByText(TEXTS.labelNoInputMessage, { exact: true })
|
||||
.last()
|
||||
.isVisible();
|
||||
|
||||
|
||||
@ -1,33 +1,23 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
withEventDeliveryModes(
|
||||
"YouTube Analysis",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
test.skip(
|
||||
!process?.env?.YOUTUBE_API_KEY,
|
||||
"YOUTUBE_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await page.goto("/");
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "YouTube Analysis" }).click();
|
||||
await openStarterProject(page, "YouTube Analysis");
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
@ -42,7 +32,9 @@ withEventDeliveryModes(
|
||||
|
||||
await page.getByTestId("button_run_chat output").last().click();
|
||||
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 120000,
|
||||
});
|
||||
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
|
||||
@ -1,24 +1,14 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { selectAssistantOpenAiModel } from "../../utils/select-assistant-openai-model";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
test.describe("Assistant Panel Integration", { tag: ["@release"] }, () => {
|
||||
test.beforeEach(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 awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await openStarterProject(page, "Basic Prompting");
|
||||
|
||||
// Open assistant panel and wait for model selector
|
||||
await page.getByTestId("assistant-button").click();
|
||||
|
||||
@ -1,17 +1,11 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { openStarterProject } from "../../utils/flow/open-starter-project";
|
||||
|
||||
test.describe("Assistant Panel UI", { tag: ["@release"] }, () => {
|
||||
test("should open and close from canvas controls", async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
skipIfMissing.openAiKey();
|
||||
await openStarterProject(page, "Basic Prompting");
|
||||
|
||||
// Panel should not be visible initially
|
||||
await expect(page.getByTestId("assistant-panel")).not.toBeVisible();
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
import { selectGptModel } from "../../utils/select-gpt-model";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"should create a flow with decision",
|
||||
{ tag: ["@release", "@components", "@workflow"] },
|
||||
@ -34,7 +35,7 @@ test(
|
||||
|
||||
//---------------------------------- CHAT INPUT
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat input");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatInput);
|
||||
await page.waitForSelector('[data-testid="input_outputChat Input"]', {
|
||||
timeout: 2000,
|
||||
});
|
||||
@ -157,7 +158,7 @@ test(
|
||||
});
|
||||
//---------------------------------- PROMPT
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("prompt");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchPrompt);
|
||||
await page.waitForSelector(
|
||||
'[data-testid="models_and_agentsPrompt Template"]',
|
||||
{
|
||||
@ -172,7 +173,9 @@ test(
|
||||
|
||||
//---------------------------------- OPENAI
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("openai");
|
||||
await page
|
||||
.getByTestId("sidebar-search-input")
|
||||
.fill(TEXTS.providerOpenAiSearch);
|
||||
await page.waitForSelector('[data-testid="openai_openai_draggable"]', {
|
||||
timeout: 2000,
|
||||
});
|
||||
@ -195,7 +198,7 @@ test(
|
||||
});
|
||||
//---------------------------------- CHAT OUTPUT
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat output");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatOutput);
|
||||
await page.waitForSelector('[data-testid="input_outputChat Output"]', {
|
||||
timeout: 2000,
|
||||
});
|
||||
@ -209,7 +212,7 @@ test(
|
||||
});
|
||||
//---------------------------------- CHAT OUTPUT
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat output");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatOutput);
|
||||
await page.waitForSelector('[data-testid="input_outputChat Output"]', {
|
||||
timeout: 2000,
|
||||
});
|
||||
@ -244,7 +247,7 @@ test(
|
||||
User: {user_message}
|
||||
AI:
|
||||
`);
|
||||
await page.getByText("Check & Save").last().click();
|
||||
await page.getByText(TEXTS.checkAndSave).last().click();
|
||||
//---------------------------------- MAKE CONNECTIONS
|
||||
await page
|
||||
.getByTestId("handle-createlist-shownode-json list-right")
|
||||
@ -370,7 +373,9 @@ test(
|
||||
|
||||
await adjustScreenView(page);
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
@ -7,6 +7,7 @@ import { unselectNodes } from "../../utils/unselect-nodes";
|
||||
import { updateOldComponents } from "../../utils/update-old-components";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user must be able to check similarity between embedding texts",
|
||||
{ tag: ["@release", "@components"] },
|
||||
@ -89,7 +90,7 @@ test(
|
||||
//seventh component
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("text output");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchTextOutput);
|
||||
await page.waitForSelector("text=Text Output", {
|
||||
timeout: 1000,
|
||||
});
|
||||
@ -128,7 +129,7 @@ test(
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-message")
|
||||
.first()
|
||||
.fill("langflow");
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
|
||||
const firstApiKeyInput = page
|
||||
.getByTestId("popover-anchor-input-openai_api_key")
|
||||
@ -249,7 +250,9 @@ test(
|
||||
|
||||
await page.getByTestId("button_run_text output").click();
|
||||
|
||||
await page.waitForSelector("text=built successfully", { timeout: 120000 });
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 120000,
|
||||
});
|
||||
|
||||
await unselectNodes(page);
|
||||
|
||||
|
||||
@ -1,174 +0,0 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { selectGptModel } from "../../utils/select-gpt-model";
|
||||
|
||||
test.skip(
|
||||
"TextInputOutputComponent",
|
||||
{ tag: ["@release", "@components"] },
|
||||
async ({ page }) => {
|
||||
// commented out because new playground does not support text io yet
|
||||
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 awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("text input");
|
||||
await page.waitForTimeout(1000);
|
||||
await page
|
||||
.getByTestId("input_outputText Input")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("openai");
|
||||
await page.waitForTimeout(1000);
|
||||
await page
|
||||
.getByTestId("openaiOpenAI")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await adjustScreenView(page);
|
||||
let visibleElementHandle;
|
||||
const elementsTextInputOutput = await page
|
||||
.getByTestId("handle-textinput-shownode-output text-right")
|
||||
.all();
|
||||
for (const element of elementsTextInputOutput) {
|
||||
if (await element.isVisible()) {
|
||||
visibleElementHandle = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await visibleElementHandle!.waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000,
|
||||
});
|
||||
await visibleElementHandle!.hover();
|
||||
await page.mouse.down();
|
||||
for (const element of elementsTextInputOutput) {
|
||||
if (await element.isVisible()) {
|
||||
visibleElementHandle = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await visibleElementHandle!.waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000,
|
||||
});
|
||||
// Move to the second element
|
||||
await visibleElementHandle!.hover();
|
||||
// Release the mouse
|
||||
await page.mouse.up();
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("text output");
|
||||
await page
|
||||
.getByTestId("input_outputText Output")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await adjustScreenView(page, { numberOfZoomOut: 6 });
|
||||
|
||||
const elementsOpenAiOutput = await page
|
||||
.getByTestId("handle-openaimodel-shownode-text-right")
|
||||
.all();
|
||||
for (const element of elementsOpenAiOutput) {
|
||||
if (await element.isVisible()) {
|
||||
visibleElementHandle = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await visibleElementHandle!.waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000,
|
||||
});
|
||||
// Click and hold on the first element
|
||||
await visibleElementHandle!.hover();
|
||||
await page.mouse.down();
|
||||
const elementTextOutputInput = await page
|
||||
.getByTestId("handle-textoutput-shownode-inputs-left")
|
||||
.all();
|
||||
for (const element of elementTextOutputInput) {
|
||||
if (await element.isVisible()) {
|
||||
visibleElementHandle = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await visibleElementHandle!.waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000,
|
||||
});
|
||||
// Move to the second element
|
||||
await visibleElementHandle!.hover();
|
||||
// Release the mouse
|
||||
await page.mouse.up();
|
||||
await page
|
||||
.getByTestId(/^rf__node-TextInput-[a-zA-Z0-9]+$/)
|
||||
.getByTestId("textarea_str_input_value")
|
||||
.fill("This is a test!");
|
||||
let outdatedComponents = await page.getByTestId("update-button").count();
|
||||
while (outdatedComponents > 0) {
|
||||
await page.getByTestId("update-button").first().click();
|
||||
await page.waitForTimeout(1000);
|
||||
outdatedComponents = await page.getByTestId("update-button").count();
|
||||
}
|
||||
let filledApiKey = await page.getByTestId("remove-icon-badge").count();
|
||||
while (filledApiKey > 0) {
|
||||
await page.getByTestId("remove-icon-badge").first().click();
|
||||
await page.waitForTimeout(1000);
|
||||
filledApiKey = await page.getByTestId("remove-icon-badge").count();
|
||||
}
|
||||
const apiKeyInput = page.getByTestId("popover-anchor-input-api_key");
|
||||
const isApiKeyInputVisible = await apiKeyInput.isVisible();
|
||||
if (isApiKeyInputVisible) {
|
||||
await apiKeyInput.fill(process.env.OPENAI_API_KEY ?? "");
|
||||
}
|
||||
await selectGptModel(page);
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page.getByTestId("button_run_text_output").click();
|
||||
await page
|
||||
.getByTestId(/^rf__node-TextOutput-[a-zA-Z0-9]+$/)
|
||||
.getByTestId("output-inspection-output message-chatoutput")
|
||||
.click();
|
||||
await page.getByText("Run Flow", { exact: true }).click();
|
||||
await page.waitForTimeout(5000);
|
||||
let textInputContent = await page
|
||||
.getByPlaceholder("Enter text...")
|
||||
.textContent();
|
||||
expect(textInputContent).toBe("This is a test!");
|
||||
await page.getByText("Outputs", { exact: true }).nth(1).click();
|
||||
await page.getByText("Text Output", { exact: true }).nth(2).click();
|
||||
let contentOutput = await page
|
||||
.getByPlaceholder("Enter text...")
|
||||
.inputValue();
|
||||
expect(contentOutput).not.toBe(null);
|
||||
await page.keyboard.press("Escape");
|
||||
await page
|
||||
.getByTestId(/^rf__node-TextInput-[a-zA-Z0-9]+$/)
|
||||
.getByTestId("textarea_str_input_value")
|
||||
.fill("This is a test, again just to be sure!");
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page.getByText("Run Flow", { exact: true }).click();
|
||||
await page.waitForTimeout(5000);
|
||||
textInputContent = await page
|
||||
.getByPlaceholder("Enter text...")
|
||||
.textContent();
|
||||
expect(textInputContent).toBe("This is a test, again just to be sure!");
|
||||
await page.getByText("Outputs", { exact: true }).nth(1).click();
|
||||
await page.getByText("Text Output", { exact: true }).nth(2).click();
|
||||
contentOutput = await page.getByPlaceholder("Enter text...").inputValue();
|
||||
expect(contentOutput).not.toBe(null);
|
||||
},
|
||||
);
|
||||
@ -1,5 +1,6 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user must not be able to login after logout and refresh the page when auto_login is false",
|
||||
{ tag: ["@release", "@api"] },
|
||||
@ -30,16 +31,22 @@ test(
|
||||
|
||||
await page.goto("/");
|
||||
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByPlaceholder("Username").fill("langflow");
|
||||
await page.getByPlaceholder("Password").fill("langflow");
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderUsername)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
await page
|
||||
.getByPlaceholder(TEXTS.placeholderPassword)
|
||||
.fill(TEXTS.authDefaultCredential);
|
||||
|
||||
await page.evaluate(() => {
|
||||
sessionStorage.removeItem("testMockAutoLogin");
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Sign In" }).click();
|
||||
await page.getByRole("button", { name: TEXTS.signIn }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="mainpage_title"]', {
|
||||
timeout: 30000,
|
||||
@ -51,13 +58,15 @@ test(
|
||||
sessionStorage.setItem("testMockAutoLogin", "true");
|
||||
});
|
||||
|
||||
await page.getByText("Logout", { exact: true }).click();
|
||||
await page.getByText(TEXTS.logout, { exact: true }).click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.reload();
|
||||
|
||||
await page.waitForSelector("text=sign in to langflow", { timeout: 30000 });
|
||||
await page.waitForSelector(`text=${TEXTS.authSignInHeader}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
const isLoggedIn = await page
|
||||
.getByTestId("mainpage_title")
|
||||
|
||||
@ -1,25 +1,22 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user must be able to edit an empty prompt",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
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") });
|
||||
}
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 100000,
|
||||
@ -39,7 +36,7 @@ test(
|
||||
await page.keyboard.press(`ControlOrMeta+a`);
|
||||
await page.keyboard.press("Backspace");
|
||||
|
||||
await page.getByText("Edit Prompt", { exact: true }).click();
|
||||
await page.getByText(TEXTS.editPrompt, { exact: true }).click();
|
||||
|
||||
await page.getByTestId("edit-prompt-sanitized").last().click();
|
||||
|
||||
@ -47,7 +44,7 @@ test(
|
||||
.getByTestId("modal-promptarea_prompt_template")
|
||||
.fill("THIS IS A TEST");
|
||||
|
||||
await page.getByText("Edit Prompt", { exact: true }).click();
|
||||
await page.getByText(TEXTS.editPrompt, { exact: true }).click();
|
||||
|
||||
let promptSanitizedText = await page
|
||||
.getByTestId("edit-prompt-sanitized")
|
||||
@ -61,7 +58,7 @@ test(
|
||||
await page.keyboard.press(`ControlOrMeta+a`);
|
||||
await page.keyboard.press("Backspace");
|
||||
|
||||
await page.getByText("Edit Prompt", { exact: true }).click();
|
||||
await page.getByText(TEXTS.editPrompt, { exact: true }).click();
|
||||
|
||||
await page.getByTestId("edit-prompt-sanitized").last().click();
|
||||
|
||||
@ -69,7 +66,7 @@ test(
|
||||
.getByTestId("modal-promptarea_prompt_template")
|
||||
.fill("THIS IS A TEST 2");
|
||||
|
||||
await page.getByText("Edit Prompt", { exact: true }).click();
|
||||
await page.getByText(TEXTS.editPrompt, { exact: true }).click();
|
||||
|
||||
promptSanitizedText = await page
|
||||
.getByTestId("edit-prompt-sanitized")
|
||||
|
||||
@ -3,6 +3,7 @@ import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { renameFlow } from "../../utils/rename-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"should be able to move flow from folder, rename it and be displayed on correct folder",
|
||||
{ tag: ["@release"] },
|
||||
@ -34,21 +35,21 @@ test(
|
||||
|
||||
await page.getByTestId("add-project-button").click();
|
||||
|
||||
let countFolders = await page.getByText("New Project").count();
|
||||
let countFolders = await page.getByText(TEXTS.labelNewProject).count();
|
||||
|
||||
while (countFolders > 1) {
|
||||
await page.getByText("New Project").first().hover();
|
||||
await page.getByText(TEXTS.labelNewProject).first().hover();
|
||||
|
||||
await page.getByTestId("more-options-button").first().click();
|
||||
await page.getByTestId("btn-delete-project").click();
|
||||
await page.getByText("Delete").last().click();
|
||||
await page.getByText(TEXTS.delete).last().click();
|
||||
countFolders--;
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
|
||||
// Get the bounding boxes of the elements
|
||||
const sourceElement = await page.getByTestId(`card-${randomName}`).first();
|
||||
const targetElement = await page.getByText("New Project").last();
|
||||
const targetElement = await page.getByText(TEXTS.labelNewProject).last();
|
||||
|
||||
const sourceBox = await sourceElement.boundingBox();
|
||||
const targetBox = await targetElement.boundingBox();
|
||||
@ -67,7 +68,7 @@ test(
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
await page.getByText("New Project").last().click();
|
||||
await page.getByText(TEXTS.labelNewProject).last().click();
|
||||
|
||||
expect(await page.getByTestId(`card-${randomName}`).first().isVisible());
|
||||
|
||||
@ -79,7 +80,7 @@ test(
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
await page.getByText("New Project").last().click();
|
||||
await page.getByText(TEXTS.labelNewProject).last().click();
|
||||
expect(
|
||||
await page.getByTestId(`card-${secondRandomName}`).first().isVisible(),
|
||||
);
|
||||
@ -88,7 +89,9 @@ test(
|
||||
const secondSourceElement = await page
|
||||
.getByTestId(`card-${secondRandomName}`)
|
||||
.first();
|
||||
const secondTargetElement = await page.getByText("New Project").last();
|
||||
const secondTargetElement = await page
|
||||
.getByText(TEXTS.labelNewProject)
|
||||
.last();
|
||||
|
||||
const secondSourceBox = await secondSourceElement.boundingBox();
|
||||
const secondTargetBox = await secondTargetElement.boundingBox();
|
||||
|
||||
@ -4,6 +4,7 @@ import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"should be able to see output preview from grouped components and connect components with a single click",
|
||||
{ tag: ["@release", "@workspace", "@components"] },
|
||||
@ -19,7 +20,7 @@ test(
|
||||
await addLegacyComponents(page);
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("text input");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchTextInput);
|
||||
await page.waitForSelector('[data-testid="input_outputText Input"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
@ -262,7 +263,9 @@ test(
|
||||
|
||||
await page.getByTestId("button_run_text output").last().click();
|
||||
|
||||
await page.waitForSelector("text=built successfully", { timeout: 30000 });
|
||||
await page.waitForSelector(`text=${TEXTS.toastBuiltSuccessfully}`, {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
expect(
|
||||
await page
|
||||
@ -274,9 +277,10 @@ test(
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await page.getByText("Component Output").isVisible();
|
||||
|
||||
const text = await page.getByPlaceholder("Empty").textContent();
|
||||
await expect(page.getByText(TEXTS.componentOutput)).toBeVisible();
|
||||
const text = await page
|
||||
.getByPlaceholder(TEXTS.placeholderEmpty)
|
||||
.textContent();
|
||||
|
||||
const permutations = [
|
||||
`${randomName}-${secondRandomName}-${thirdRandomName}`,
|
||||
|
||||
@ -1,27 +1,24 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { addLegacyComponents } from "../../utils/add-legacy-components";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user should be able to use chat memory as expected",
|
||||
{ tag: ["@release", "@workspace", "@components"] },
|
||||
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") });
|
||||
}
|
||||
skipIfMissing.openAiKey();
|
||||
loadDotenvIfLocal(__dirname);
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
|
||||
await adjustScreenView(page);
|
||||
|
||||
@ -83,8 +80,8 @@ AI:
|
||||
await page.getByTestId("button_open_prompt_modal").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();
|
||||
await page.getByText(TEXTS.editPrompt, { exact: true }).click();
|
||||
await page.getByText(TEXTS.checkAndSave).last().click();
|
||||
|
||||
await adjustScreenView(page);
|
||||
|
||||
@ -98,14 +95,16 @@ AI:
|
||||
|
||||
await page.locator('//*[@id="react-flow-id"]').hover();
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await page
|
||||
.getByPlaceholder("Send a message...")
|
||||
.getByPlaceholder(TEXTS.placeholderSendMessage)
|
||||
.fill("hi, my car is blue and I like to eat pizza");
|
||||
|
||||
await page.getByTestId("button-send").click();
|
||||
@ -113,7 +112,7 @@ AI:
|
||||
await page.waitForSelector("text=AI", { timeout: 30000 });
|
||||
|
||||
await page
|
||||
.getByPlaceholder("Send a message...")
|
||||
.getByPlaceholder(TEXTS.placeholderSendMessage)
|
||||
.fill("what color is my car and what do I like to eat?");
|
||||
|
||||
await page.getByTestId("button-send").click();
|
||||
|
||||
@ -1,15 +1,10 @@
|
||||
import type { Locator, Page } from "@playwright/test";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
async function addChromaNode(page: Page) {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("Chroma");
|
||||
|
||||
|
||||
@ -2,7 +2,9 @@ import type { Page } from "@playwright/test";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
import { skipIfMissing } from "../../utils/env/skip-if-missing";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test.describe("Session Deletion Data Leakage Fix", () => {
|
||||
// Helper to send a message in the playground
|
||||
async function sendMessage(page: Page, message: string) {
|
||||
@ -78,21 +80,19 @@ test.describe("Session Deletion Data Leakage Fix", () => {
|
||||
"should prevent data leakage when default session is deleted and recreated",
|
||||
{ tag: ["@release", "@regression"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
// Load a starter project
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@ -145,21 +145,19 @@ test.describe("Session Deletion Data Leakage Fix", () => {
|
||||
"should clear LLM context when session is deleted",
|
||||
{ tag: ["@release", "@regression"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY,
|
||||
"OPENAI_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
skipIfMissing.openAiKey();
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
// Load a starter project with memory
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page
|
||||
.getByRole("heading", { name: TEXTS.templateBasicPrompting })
|
||||
.click();
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Open playground
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
|
||||
@ -72,15 +72,15 @@ test(
|
||||
"toggle_bool_add_calculator_tool",
|
||||
);
|
||||
await expect(calculatorToggle).toBeVisible({ timeout: 10000 });
|
||||
expect(await calculatorToggle.isChecked()).toBeTruthy();
|
||||
await expect(calculatorToggle).toBeChecked();
|
||||
|
||||
// S3 — user disables the toggle.
|
||||
await calculatorToggle.click();
|
||||
expect(await calculatorToggle.isChecked()).toBeFalsy();
|
||||
await expect(calculatorToggle).not.toBeChecked();
|
||||
|
||||
// Re-enable to confirm the control is bi-directional.
|
||||
await calculatorToggle.click();
|
||||
expect(await calculatorToggle.isChecked()).toBeTruthy();
|
||||
await expect(calculatorToggle).toBeChecked();
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@ -1,20 +1,15 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test("chat_io_teste", { tag: ["@release", "@workspace"] }, async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.waitForSelector('[data-testid="sidebar-search-input"]', {
|
||||
state: "visible",
|
||||
});
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat output");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatOutput);
|
||||
await page.waitForSelector('[data-testid="input_outputChat Output"]', {
|
||||
timeout: 2000,
|
||||
});
|
||||
@ -27,7 +22,7 @@ test("chat_io_teste", { tag: ["@release", "@workspace"] }, async ({ page }) => {
|
||||
});
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat input");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatInput);
|
||||
await page.waitForSelector('[data-testid="input_outputChat Input"]', {
|
||||
timeout: 2000,
|
||||
});
|
||||
@ -49,7 +44,7 @@ test("chat_io_teste", { tag: ["@release", "@workspace"] }, async ({ page }) => {
|
||||
.click();
|
||||
await page.getByTestId("handle-chatoutput-noshownode-inputs-target").click();
|
||||
|
||||
await page.getByText("Playground", { exact: true }).last().click();
|
||||
await page.getByText(TEXTS.playground, { exact: true }).last().click();
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
@ -1,18 +1,13 @@
|
||||
import { expect } from "@playwright/test";
|
||||
import { test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"CodeAreaModalComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
|
||||
await page.getByTestId("canvas_controls_dropdown").click();
|
||||
|
||||
@ -66,7 +61,7 @@ class CustomComponent(Component):
|
||||
await page.keyboard.press(`ControlOrMeta+A`);
|
||||
await page.locator("textarea").fill(codeInputCode);
|
||||
|
||||
await page.getByText("Check & Save").last().click();
|
||||
await page.getByText(TEXTS.checkAndSave).last().click();
|
||||
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import {
|
||||
closeAdvancedOptions,
|
||||
disableInspectPanel,
|
||||
@ -8,17 +7,14 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"dropDownComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
|
||||
// Allow for legacy components
|
||||
await page.getByTestId("sidebar-options-trigger").click();
|
||||
@ -152,7 +148,6 @@ from langflow.io import BoolInput, DictInput, DropdownInput, StrInput
|
||||
from langflow.io import MessageInput
|
||||
from langflow.io import Output
|
||||
|
||||
|
||||
class AmazonBedrockComponent(LCModelComponent):
|
||||
display_name: str = "Amazon Bedrock"
|
||||
description: str = "Generate text using Amazon Bedrock LLMs."
|
||||
@ -248,7 +243,7 @@ class AmazonBedrockComponent(LCModelComponent):
|
||||
return output
|
||||
`;
|
||||
await page.locator("textarea").fill(emptyOptionsCode);
|
||||
await page.getByRole("button", { name: "Check & Save" }).click();
|
||||
await page.getByRole("button", { name: TEXTS.checkAndSave }).click();
|
||||
await page
|
||||
.getByText("No parameters are available for display.")
|
||||
.isVisible();
|
||||
|
||||
@ -11,6 +11,9 @@ import {
|
||||
enableInspectPanel,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
// Run tests in this file serially to avoid database conflicts with shared file state
|
||||
test.describe.configure({ mode: "serial" });
|
||||
|
||||
@ -30,13 +33,7 @@ test(
|
||||
// Read the test file content
|
||||
const testFilePath = path.join(__dirname, "../../assets/test_file.txt");
|
||||
const fileContent = fs.readFileSync(testFilePath);
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
|
||||
await disableInspectPanel(page);
|
||||
|
||||
@ -88,7 +85,7 @@ test(
|
||||
),
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByText("My Files").first().hover();
|
||||
await page.getByText(TEXTS.labelMyFiles).first().hover();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await expect(page.getByText(`${sourceFileName}.txt`).last()).toBeVisible({
|
||||
@ -273,7 +270,7 @@ test(
|
||||
}
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("chat output");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchChatOutput);
|
||||
|
||||
await page
|
||||
.getByTestId("input_outputChat Output")
|
||||
@ -291,7 +288,9 @@ test(
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
// Create a new session first
|
||||
await page.getByTestId("new-chat").click();
|
||||
@ -387,7 +386,7 @@ test(
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
// Use the chat header more menu to clear chat (stays in fullscreen)
|
||||
await page
|
||||
@ -445,13 +444,7 @@ test(
|
||||
// Read the test file content
|
||||
const testFilePath = path.join(__dirname, "../../assets/test_file.txt");
|
||||
const _fileContent = fs.readFileSync(testFilePath);
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
|
||||
await disableInspectPanel(page);
|
||||
|
||||
@ -696,7 +689,7 @@ test(
|
||||
await awaitBootstrapTest(page, { skipModal: true });
|
||||
|
||||
// Navigate to My Files page
|
||||
await page.getByText("My Files").first().click();
|
||||
await page.getByText(TEXTS.labelMyFiles).first().click();
|
||||
|
||||
// Check if we're on the files page
|
||||
await page.waitForSelector('[data-testid="mainpage_title"]');
|
||||
@ -903,7 +896,7 @@ test(
|
||||
});
|
||||
await page.getByTestId("output-inspection-file path-file").click();
|
||||
const filePaths = await page.getByTestId("textarea").textContent();
|
||||
await page.getByText("Close").last().click();
|
||||
await page.getByText(TEXTS.close).last().click();
|
||||
|
||||
const cleanPath = filePaths
|
||||
?.replace(/"/g, "")
|
||||
@ -998,7 +991,9 @@ test(
|
||||
await textInputs.first().fill(`${folderId}/${file1}.txt`);
|
||||
await textInputs.last().fill(`${folderId}/${file2}.txt`);
|
||||
|
||||
await page.getByRole("button", { name: "Playground", exact: true }).click();
|
||||
await page
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector("text=Run Flow", {
|
||||
timeout: 30000,
|
||||
@ -1011,7 +1006,7 @@ test(
|
||||
await expect(page.getByText(fileContent2)).toBeVisible();
|
||||
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click({ force: true });
|
||||
|
||||
// Test Case 2: Single File (clear second input, use only first)
|
||||
@ -1019,7 +1014,7 @@ test(
|
||||
await textInputs.first().fill(`${folderId}/${file1}.txt`);
|
||||
|
||||
await page
|
||||
.getByRole("button", { name: "Playground", exact: true })
|
||||
.getByRole("button", { name: TEXTS.playground, exact: true })
|
||||
.click({ force: true });
|
||||
|
||||
await page.waitForSelector("text=Run Flow", {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import {
|
||||
closeAdvancedOptions,
|
||||
disableInspectPanel,
|
||||
@ -8,16 +7,12 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
test(
|
||||
"FloatComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("nvidia");
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import {
|
||||
closeAdvancedOptions,
|
||||
disableInspectPanel,
|
||||
@ -8,16 +7,12 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
test(
|
||||
"InputComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("Chroma");
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"InputListComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
@ -16,7 +17,7 @@ test(
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("url");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchUrl);
|
||||
|
||||
await page.waitForSelector('[data-testid="data_sourceURL"]', {
|
||||
timeout: 3000,
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import {
|
||||
closeAdvancedOptions,
|
||||
disableInspectPanel,
|
||||
@ -8,15 +7,15 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
test("IntComponent", { tag: ["@release", "@workspace"] }, async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test("IntComponent", { tag: ["@release", "@workspace"] }, async ({ page }) => {
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("openai");
|
||||
await page
|
||||
.getByTestId("sidebar-search-input")
|
||||
.fill(TEXTS.providerOpenAiSearch);
|
||||
|
||||
await page.waitForSelector('[data-testid="openaiOpenAI"]', {
|
||||
timeout: 3000,
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import {
|
||||
closeAdvancedOptions,
|
||||
disableInspectPanel,
|
||||
@ -8,16 +7,12 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
test(
|
||||
"KeypairListComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
|
||||
await disableInspectPanel(page);
|
||||
|
||||
@ -43,7 +38,7 @@ test(
|
||||
await openAdvancedOptions(page);
|
||||
|
||||
await page.getByTestId("showmodel_kwargs").click();
|
||||
expect(await page.getByTestId("showmodel_kwargs").isChecked()).toBeTruthy();
|
||||
await expect(page.getByTestId("showmodel_kwargs")).toBeChecked();
|
||||
await closeAdvancedOptions(page);
|
||||
|
||||
await adjustScreenView(page, {
|
||||
|
||||
@ -2,6 +2,7 @@ import { type Page } from "@playwright/test";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { extractAndCleanCode } from "../../utils/extract-and-clean-code";
|
||||
|
||||
// TODO: This test might not be needed anymore
|
||||
test(
|
||||
@ -74,27 +75,6 @@ test(
|
||||
},
|
||||
);
|
||||
|
||||
async function extractAndCleanCode(page: Page): Promise<string> {
|
||||
const outerHTML = await page
|
||||
.locator('//*[@id="codeValue"]')
|
||||
.evaluate((el) => el.outerHTML);
|
||||
|
||||
const valueMatch = outerHTML.match(/value="([\s\S]*?)"/);
|
||||
if (!valueMatch) {
|
||||
throw new Error("Could not find value attribute in the HTML");
|
||||
}
|
||||
|
||||
const codeContent = valueMatch[1]
|
||||
.replace(/"/g, '"')
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/'/g, "'")
|
||||
.replace(///g, "/");
|
||||
|
||||
return codeContent;
|
||||
}
|
||||
|
||||
function updateComponentCode(
|
||||
code: string,
|
||||
updates: {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { addLegacyComponents } from "../../utils/add-legacy-components";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import {
|
||||
closeAdvancedOptions,
|
||||
disableInspectPanel,
|
||||
@ -9,16 +8,14 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"user should be able to use nested component",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("alter metadata");
|
||||
|
||||
@ -57,7 +54,7 @@ test(
|
||||
expect(await page.getByText("proptest1", { exact: true }).count()).toBe(1);
|
||||
expect(await page.getByText("proptest2", { exact: true }).count()).toBe(1);
|
||||
|
||||
await page.getByText("Save").last().click();
|
||||
await page.getByText(TEXTS.save).last().click();
|
||||
|
||||
await disableInspectPanel(page);
|
||||
|
||||
@ -87,7 +84,7 @@ test(
|
||||
expect(await page.getByText("keytest", { exact: true }).count()).toBe(0);
|
||||
expect(await page.getByText("proptest", { exact: true }).count()).toBe(0);
|
||||
|
||||
await page.getByText("Save", { exact: true }).last().click();
|
||||
await page.getByText(TEXTS.save, { exact: true }).last().click();
|
||||
|
||||
await closeAdvancedOptions(page);
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import {
|
||||
closeAdvancedOptions,
|
||||
disableInspectPanel,
|
||||
@ -9,7 +8,9 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
import { unselectNodes } from "../../utils/unselect-nodes";
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
// Helper function to verify prompt variables
|
||||
async function verifyPromptVariables(
|
||||
page: Page,
|
||||
@ -62,13 +63,9 @@ test(
|
||||
"PromptTemplateComponent - Variable Extraction",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("prompt");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchPrompt);
|
||||
await page.waitForSelector(
|
||||
'[data-testid="models_and_agentsPrompt Template"]',
|
||||
{
|
||||
@ -150,14 +147,9 @@ test(
|
||||
"PromptTemplateComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("prompt");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchPrompt);
|
||||
|
||||
await page.waitForSelector(
|
||||
'[data-testid="models_and_agentsPrompt Template"]',
|
||||
@ -294,7 +286,7 @@ test(
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showprompt"]').click();
|
||||
expect(await page.locator('//*[@id="showprompt"]').isChecked()).toBeFalsy();
|
||||
await expect(page.locator('//*[@id="showprompt"]')).not.toBeChecked();
|
||||
|
||||
await page.locator('//*[@id="showprompt1"]').click();
|
||||
expect(
|
||||
@ -322,7 +314,7 @@ test(
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showprompt"]').click();
|
||||
expect(await page.locator('//*[@id="showprompt"]').isChecked()).toBeFalsy();
|
||||
await expect(page.locator('//*[@id="showprompt"]')).not.toBeChecked();
|
||||
|
||||
await page.locator('//*[@id="showprompt1"]').click();
|
||||
expect(
|
||||
@ -384,14 +376,9 @@ test(
|
||||
"PromptTemplateComponent - Double Brackets Variable Extraction",
|
||||
{ tag: ["@release", "@workspace"], timeout: 60000 },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("prompt");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchPrompt);
|
||||
|
||||
await page.waitForSelector(
|
||||
'[data-testid="models_and_agentsPrompt Template"]',
|
||||
@ -477,14 +464,9 @@ test(
|
||||
"PromptTemplateComponent - Double Brackets Multiple Variables",
|
||||
{ tag: ["@release", "@workspace"], timeout: 60000 },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("prompt");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchPrompt);
|
||||
|
||||
await page.waitForSelector(
|
||||
'[data-testid="models_and_agentsPrompt Template"]',
|
||||
@ -612,14 +594,9 @@ test(
|
||||
"PromptTemplateComponent - Synchronized State",
|
||||
{ tag: ["@release", "@workspace"], timeout: 60000 },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("prompt");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchPrompt);
|
||||
|
||||
await page.waitForSelector(
|
||||
'[data-testid="models_and_agentsPrompt Template"]',
|
||||
|
||||
@ -9,6 +9,9 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { extractAndCleanCode } from "../../utils/extract-and-clean-code";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
// TODO: This component doesn't have slider needs updating
|
||||
test(
|
||||
"user should be able to use query input",
|
||||
@ -23,7 +26,9 @@ test(
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("openai");
|
||||
await page
|
||||
.getByTestId("sidebar-search-input")
|
||||
.fill(TEXTS.providerOpenAiSearch);
|
||||
|
||||
await page.waitForSelector('[data-testid="openaiOpenAI"]', {
|
||||
timeout: 3000,
|
||||
@ -129,24 +134,3 @@ test(
|
||||
await enableInspectPanel(page);
|
||||
},
|
||||
);
|
||||
|
||||
async function extractAndCleanCode(page: Page): Promise<string> {
|
||||
const outerHTML = await page
|
||||
.locator('//*[@id="codeValue"]')
|
||||
.evaluate((el) => el.outerHTML);
|
||||
|
||||
const valueMatch = outerHTML.match(/value="([\s\S]*?)"/);
|
||||
if (!valueMatch) {
|
||||
throw new Error("Could not find value attribute in the HTML");
|
||||
}
|
||||
|
||||
const codeContent = valueMatch[1]
|
||||
.replace(/"/g, '"')
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/'/g, "'")
|
||||
.replace(///g, "/");
|
||||
|
||||
return codeContent;
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { extractAndCleanCode } from "../../utils/extract-and-clean-code";
|
||||
// TODO: This component doesn't have slider needs updating
|
||||
test(
|
||||
"user should be able to use slider input",
|
||||
@ -111,44 +112,6 @@ test(
|
||||
},
|
||||
);
|
||||
|
||||
async function extractAndCleanCode(page: Page): Promise<string> {
|
||||
// The hidden `#codeValue` mirror is rendered with `<Input value={code} />`,
|
||||
// i.e. a single-line `<input>` rather than a textarea. Browsers strip
|
||||
// newlines from `.value` of single-line inputs by HTML spec, so reading
|
||||
// `(el as HTMLInputElement).value` returns the entire source concatenated
|
||||
// onto one line. The backend then rejects it as
|
||||
// `invalid decimal literal (<unknown>, line 1)`.
|
||||
//
|
||||
// Read the rendered HTML attribute instead — React serializes the prop as
|
||||
// `value="..."` with newlines encoded (` `, ` `, or literal LF
|
||||
// inside attribute text), and the regex below recovers them faithfully.
|
||||
// This is the same strategy queryInputComponent.spec.ts uses.
|
||||
const outerHTML = await page
|
||||
.locator('//*[@id="codeValue"]')
|
||||
.evaluate((el) => el.outerHTML);
|
||||
|
||||
const valueMatch = outerHTML.match(/value="([\s\S]*?)"/);
|
||||
if (!valueMatch) {
|
||||
throw new Error("Could not find value attribute in the #codeValue HTML");
|
||||
}
|
||||
|
||||
const codeContent = valueMatch[1]
|
||||
.replace(/"/g, '"')
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/'/g, "'")
|
||||
.replace(///g, "/")
|
||||
.replace(/ /g, "\n")
|
||||
.replace(/ /g, "\r")
|
||||
.replace(/
/gi, "\n")
|
||||
.replace(/
/gi, "\r");
|
||||
|
||||
// Normalize line endings so downstream string operations are OS-agnostic
|
||||
// (Windows git checkouts of .py files can end up with CRLF).
|
||||
return codeContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
}
|
||||
|
||||
// Set the Ace editor's content using the exact same pattern that
|
||||
// queryInputComponent.spec.ts uses successfully on Windows CI:
|
||||
// `textarea.last().fill(newCode)` against Ace's hidden text-input textarea.
|
||||
|
||||
@ -2,6 +2,7 @@ import { type Page } from "@playwright/test";
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { extractAndCleanCode } from "../../utils/extract-and-clean-code";
|
||||
|
||||
test(
|
||||
"user should interact with tab component",
|
||||
@ -96,27 +97,6 @@ test(
|
||||
},
|
||||
);
|
||||
|
||||
async function extractAndCleanCode(page: Page): Promise<string> {
|
||||
const outerHTML = await page
|
||||
.locator('//*[@id="codeValue"]')
|
||||
.evaluate((el) => el.outerHTML);
|
||||
|
||||
const valueMatch = outerHTML.match(/value="([\s\S]*?)"/);
|
||||
if (!valueMatch) {
|
||||
throw new Error("Could not find value attribute in the HTML");
|
||||
}
|
||||
|
||||
const codeContent = valueMatch[1]
|
||||
.replace(/"/g, '"')
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/'/g, "'")
|
||||
.replace(///g, "/");
|
||||
|
||||
return codeContent;
|
||||
}
|
||||
|
||||
function updateComponentCode(
|
||||
code: string,
|
||||
updates: {
|
||||
|
||||
@ -1,193 +0,0 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { zoomOut } from "../../utils/zoom-out";
|
||||
|
||||
test.skip(
|
||||
"user must be able to interact with table input component",
|
||||
{
|
||||
tag: ["@release", "@workspace"],
|
||||
},
|
||||
async ({ page }) => {
|
||||
// SKIP: This test has UI event conflicts where double-click should expose "Input Editor"
|
||||
// but single-click opens textarea modal that blocks the view. This works in main but
|
||||
// not in this branch despite no UI code changes. Needs investigation of event handling.
|
||||
const randomText = Math.random().toString(36).substring(7);
|
||||
const secondRandomText = Math.random().toString(36).substring(7);
|
||||
const thirdRandomText = Math.random().toString(36).substring(7);
|
||||
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
|
||||
await page.waitForSelector(
|
||||
'[data-testid="sidebar-custom-component-button"]',
|
||||
{
|
||||
timeout: 3000,
|
||||
},
|
||||
);
|
||||
|
||||
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page.getByTestId("sidebar-custom-component-button").click();
|
||||
|
||||
await zoomOut(page, 2);
|
||||
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
await page.getByTestId("code-button-modal").last().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 = "https://docs.langflow.org/components-custom-components"
|
||||
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(`ControlOrMeta+a`);
|
||||
await page.locator("textarea").fill(customCodeWithError);
|
||||
|
||||
await page.getByText("Check & Save").last().click();
|
||||
|
||||
await page.waitForSelector('text="Open table"', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page.getByText("Open table").click();
|
||||
|
||||
await page.waitForSelector(".ag-cell-value", {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
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).last()).toBeVisible();
|
||||
}
|
||||
|
||||
await page.locator(".ag-cell-value").first().dblclick({
|
||||
force: true,
|
||||
});
|
||||
|
||||
await page.getByLabel("Input Editor").fill(randomText);
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
await page.locator(".ag-cell-value").nth(12).dblclick({
|
||||
force: true,
|
||||
});
|
||||
|
||||
await page.getByLabel("Input Editor").fill(secondRandomText);
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
await page.locator(".ag-cell-value").nth(24).dblclick({
|
||||
force: true,
|
||||
});
|
||||
|
||||
await page.getByLabel("Input Editor").fill(thirdRandomText);
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
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").last().click();
|
||||
|
||||
await expect(page.getByTestId("duplicate-row-button")).toBeDisabled({
|
||||
timeout: 1000,
|
||||
});
|
||||
|
||||
let numberOfCopiedRows = await page.getByText(thirdRandomText).count();
|
||||
expect(numberOfCopiedRows).toBe(2);
|
||||
|
||||
await page.locator('input[type="checkbox"]').last().click();
|
||||
await page.getByTestId("icon-Trash2").last().click();
|
||||
|
||||
await expect(page.getByTestId("delete-row-button")).toBeDisabled({
|
||||
timeout: 1000,
|
||||
});
|
||||
|
||||
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("Save").last().click();
|
||||
|
||||
await page.waitForSelector("text=Open table", {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page.getByText("Open table").click();
|
||||
|
||||
await page.waitForSelector(".ag-cell-value", {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
const visibleTexts = ["Alpha", "Bravo", "Charlie", "Delta", "Echo"];
|
||||
const notVisibleTexts = ["X1", "thirdRandomText"];
|
||||
|
||||
for (const text of visibleTexts) {
|
||||
const count = await page.getByText(text).count();
|
||||
expect(count).toBeGreaterThanOrEqual(1);
|
||||
}
|
||||
|
||||
for (const text of notVisibleTexts) {
|
||||
const count = await page.getByText(text).count();
|
||||
expect(count).toBe(0);
|
||||
}
|
||||
},
|
||||
);
|
||||
@ -1,20 +1,16 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
|
||||
import { TEXTS } from "../../utils/constants/texts";
|
||||
test(
|
||||
"TextAreaModalComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
await page.getByTestId("sidebar-search-input").fill("prompt");
|
||||
await page.getByTestId("sidebar-search-input").fill(TEXTS.searchPrompt);
|
||||
|
||||
await page.waitForSelector(
|
||||
'[data-testid="models_and_agentsPrompt Template"]',
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { expect, test } from "../../fixtures";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import {
|
||||
closeAdvancedOptions,
|
||||
disableInspectPanel,
|
||||
@ -8,16 +7,12 @@ import {
|
||||
openAdvancedOptions,
|
||||
} from "../../utils/open-advanced-options";
|
||||
|
||||
import { openBlankFlow } from "../../utils/flow/open-blank-flow";
|
||||
test(
|
||||
"ToggleComponent",
|
||||
{ tag: ["@release", "@workspace"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await openBlankFlow(page);
|
||||
|
||||
// Open the sidebar options dropdown
|
||||
await page.getByTestId("sidebar-options-trigger").click();
|
||||
@ -108,7 +103,7 @@ test(
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showpath"]').click();
|
||||
expect(await page.locator('//*[@id="showpath"]').isChecked()).toBeFalsy();
|
||||
await expect(page.locator('//*[@id="showpath"]')).not.toBeChecked();
|
||||
|
||||
await page.locator('//*[@id="showrecursive"]').click();
|
||||
expect(
|
||||
@ -131,7 +126,7 @@ test(
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showpath"]').click();
|
||||
expect(await page.locator('//*[@id="showpath"]').isChecked()).toBeTruthy();
|
||||
await expect(page.locator('//*[@id="showpath"]')).toBeChecked();
|
||||
|
||||
await page.locator('//*[@id="showrecursive"]').click();
|
||||
expect(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user