feat: add stop button on Playground Chat (#3704)

* 📝 (buttonSendWrapper/index.tsx): refactor button styling logic to use constants for better readability and maintainability
🐛 (buttonSendWrapper/index.tsx): fix logic to disable button when chat is locked and not building
🐛 (buttonSendWrapper/index.tsx): fix conditional rendering of icons based on button state

*  (stop-button-playground.spec.ts): Add end-to-end test for stopping building from inside Playground.

* 🔧 (buttonSendWrapper/index.tsx): refactor conditional logic to correctly prioritize showStopButton condition and improve code readability

*  (stop-button-playground.spec.ts): add assertion to check if "build stopped" text is visible after clicking on the stop button
This commit is contained in:
Cristhian Zanforlin Lousa 2024-09-06 17:19:00 -03:00 committed by GitHub
commit 9b83f44611
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 200 additions and 18 deletions

View file

@ -0,0 +1,159 @@
import { expect, test } from "@playwright/test";
import uaParser from "ua-parser-js";
test("User must be able to stop building from inside Playground", async ({
page,
}) => {
await page.goto("/");
await page.waitForSelector('[data-testid="mainpage_title"]', {
timeout: 30000,
});
await page.waitForSelector('[id="new-project-btn"]', {
timeout: 30000,
});
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.getByText("New Project", { exact: true }).click();
await page.waitForTimeout(3000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.getByTestId("blank-flow").click();
await page.waitForSelector('[data-testid="extended-disclosure"]', {
timeout: 1000,
});
await page.getByTestId("extended-disclosure").click();
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("custom");
await page.waitForTimeout(1000);
await page
.locator('//*[@id="helpersCustom Component"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("chat output");
await page.waitForTimeout(1000);
await page
.getByTestId("outputsChat Output")
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTestId("div-generic-node").nth(0).click();
await page.getByTestId("code-button-modal").nth(0).click();
const waitTimeoutCode = `
# from langflow.field_typing import Data
from langflow.custom import Component
from langflow.io import MessageTextInput, Output
from langflow.schema import Data
from time import sleep
from langflow.schema.message import Message
class CustomComponent(Component):
display_name = "Custom Component"
description = "Use as a template to create your own component."
documentation: str = "http://docs.langflow.org/components/custom"
icon = "custom_components"
name = "CustomComponent"
inputs = [
MessageTextInput(name="input_value", display_name="Input Value", value="Hello, World!"),
]
outputs = [
Output(display_name="Output", name="output", method="build_output"),
]
def build_output(self) -> Message:
data = Data(value=self.input_value)
self.status = data
sleep(60)
return data`;
const getUA = await page.evaluate(() => navigator.userAgent);
const userAgentInfo = uaParser(getUA);
let control = "Control";
if (userAgentInfo.os.name.includes("Mac")) {
control = "Meta";
}
await page.locator(".ace_content").click();
await page.keyboard.press(`${control}+A`);
await page.locator("textarea").fill(waitTimeoutCode);
await page.getByText("Check & Save").last().click();
await page.waitForTimeout(1000);
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
//connection 1
const elementCustomComponentOutput = await page
.getByTestId("handle-customcomponent-shownode-output-right")
.first();
await elementCustomComponentOutput.hover();
await page.mouse.down();
const elementChatOutput = await page
.getByTestId("handle-chatoutput-shownode-text-left")
.first();
await elementChatOutput.hover();
await page.mouse.up();
await page.waitForTimeout(1000);
await page.getByTestId("button_run_chat output").click();
await page.waitForTimeout(1000);
await page.getByText("Playground", { exact: true }).click();
await page.waitForTimeout(1000);
await page.waitForSelector('[data-testid="icon-Square"]', {
timeout: 30000,
});
const elements = await page.$$('[data-testid="icon-Square"]');
if (elements.length > 0) {
const lastElement = elements[elements.length - 1];
await lastElement.waitForElementState("visible");
}
expect(await page.getByTestId("icon-Square").last()).toBeVisible();
await page.getByTestId("icon-Square").last().click();
await page.waitForSelector("text=build stopped", { timeout: 30000 });
expect(await page.getByText("build stopped").isVisible()).toBeTruthy();
});