Merge branch 'main' into feat/firecrawl-integration
This commit is contained in:
commit
9373749163
44 changed files with 773 additions and 518 deletions
|
|
@ -4,12 +4,12 @@ import sys
|
|||
import time
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
import click
|
||||
import httpx
|
||||
import typer
|
||||
from dotenv import load_dotenv
|
||||
from dotenv import dotenv_values, load_dotenv
|
||||
from multiprocess import Process, cpu_count # type: ignore
|
||||
from packaging import version as pkg_version
|
||||
from rich import box
|
||||
|
|
@ -130,6 +130,29 @@ def run(
|
|||
|
||||
if env_file:
|
||||
load_dotenv(env_file, override=True)
|
||||
env_vars = dotenv_values(env_file)
|
||||
|
||||
# Define a mapping of environment variables to their corresponding variables and types
|
||||
env_var_mapping: dict[str, tuple[str, type | Callable[[Any], bool]]] = {
|
||||
"LANGFLOW_HOST": ("host", str),
|
||||
"LANGFLOW_PORT": ("port", int),
|
||||
"LANGFLOW_WORKERS": ("workers", int),
|
||||
"LANGFLOW_WORKER_TIMEOUT": ("timeout", int),
|
||||
"LANGFLOW_COMPONENTS_PATH": ("components_path", Path),
|
||||
"LANGFLOW_LOG_LEVEL": ("log_level", str),
|
||||
"LANGFLOW_LOG_FILE": ("log_file", Path),
|
||||
"LANGFLOW_LANGCHAIN_CACHE": ("cache", str),
|
||||
"LANGFLOW_FRONTEND_PATH": ("path", str),
|
||||
"LANGFLOW_OPEN_BROWSER": ("open_browser", lambda x: x.lower() == "true"),
|
||||
"LANGFLOW_REMOVE_API_KEYS": ("remove_api_keys", lambda x: x.lower() == "true"),
|
||||
"LANGFLOW_BACKEND_ONLY": ("backend_only", lambda x: x.lower() == "true"),
|
||||
"LANGFLOW_STORE": ("store", lambda x: x.lower() == "true"),
|
||||
}
|
||||
|
||||
# Update variables based on environment variables
|
||||
for env_var, (var_name, var_type) in env_var_mapping.items():
|
||||
if env_var in env_vars:
|
||||
locals()[var_name] = var_type(env_vars[env_var])
|
||||
|
||||
update_settings(
|
||||
dev=dev,
|
||||
|
|
|
|||
|
|
@ -121,9 +121,9 @@ async def retrieve_vertices_order(
|
|||
background_tasks.add_task(
|
||||
telemetry_service.log_package_playground,
|
||||
PlaygroundPayload(
|
||||
seconds=int(time.perf_counter() - start_time),
|
||||
componentCount=components_count,
|
||||
success=True,
|
||||
playgroundSeconds=int(time.perf_counter() - start_time),
|
||||
playgroundComponentCount=components_count,
|
||||
playgroundSuccess=True,
|
||||
),
|
||||
)
|
||||
return VerticesOrderResponse(ids=first_layer, run_id=graph._run_id, vertices_to_run=vertices_to_run)
|
||||
|
|
@ -131,10 +131,10 @@ async def retrieve_vertices_order(
|
|||
background_tasks.add_task(
|
||||
telemetry_service.log_package_playground,
|
||||
PlaygroundPayload(
|
||||
seconds=int(time.perf_counter() - start_time),
|
||||
componentCount=components_count,
|
||||
success=False,
|
||||
errorMessage=str(exc),
|
||||
playgroundSeconds=int(time.perf_counter() - start_time),
|
||||
playgroundComponentCount=components_count,
|
||||
playgroundSuccess=False,
|
||||
playgroundErrorMessage=str(exc),
|
||||
),
|
||||
)
|
||||
if "stream or streaming set to True" in str(exc):
|
||||
|
|
@ -280,10 +280,10 @@ async def build_vertex(
|
|||
background_tasks.add_task(
|
||||
telemetry_service.log_package_component,
|
||||
ComponentPayload(
|
||||
name=vertex_id,
|
||||
seconds=int(time.perf_counter() - start_time),
|
||||
success=valid,
|
||||
errorMessage=params,
|
||||
componentName=vertex_id,
|
||||
componentSeconds=int(time.perf_counter() - start_time),
|
||||
componentSuccess=valid,
|
||||
componentErrorMessage=params,
|
||||
),
|
||||
)
|
||||
return build_response
|
||||
|
|
@ -291,10 +291,10 @@ async def build_vertex(
|
|||
background_tasks.add_task(
|
||||
telemetry_service.log_package_component,
|
||||
ComponentPayload(
|
||||
name=vertex_id,
|
||||
seconds=int(time.perf_counter() - start_time),
|
||||
success=False,
|
||||
errorMessage=str(exc),
|
||||
componentName=vertex_id,
|
||||
componentSeconds=int(time.perf_counter() - start_time),
|
||||
componentSuccess=False,
|
||||
componentErrorMessage=str(exc),
|
||||
),
|
||||
)
|
||||
logger.error(f"Error building Component:\n\n{exc}")
|
||||
|
|
|
|||
|
|
@ -116,11 +116,29 @@ async def simple_run_flow(
|
|||
return RunResponse(outputs=task_result, session_id=session_id)
|
||||
|
||||
except sa.exc.StatementError as exc:
|
||||
# StatementError('(builtins.ValueError) badly formed hexadecimal UUID string')
|
||||
if "badly formed hexadecimal UUID string" in str(exc):
|
||||
logger.error(f"Flow ID {flow_id_str} is not a valid UUID")
|
||||
# This means the Flow ID is not a valid UUID which means it can't find the flow
|
||||
raise ValueError(str(exc)) from exc
|
||||
raise ValueError(str(exc)) from exc
|
||||
|
||||
|
||||
async def simple_run_flow_task(
|
||||
flow: Flow,
|
||||
input_request: SimplifiedAPIRequest,
|
||||
stream: bool = False,
|
||||
api_key_user: Optional[User] = None,
|
||||
):
|
||||
"""
|
||||
Run a flow task as a BackgroundTask, therefore it should not throw exceptions.
|
||||
"""
|
||||
try:
|
||||
result = await simple_run_flow(
|
||||
flow=flow,
|
||||
input_request=input_request,
|
||||
stream=stream,
|
||||
api_key_user=api_key_user,
|
||||
)
|
||||
return result
|
||||
|
||||
except Exception as exc:
|
||||
logger.exception(f"Error running flow {flow.id} task: {exc}")
|
||||
|
||||
|
||||
@router.post("/run/{flow_id_or_name}", response_model=RunResponse, response_model_exclude_none=True)
|
||||
|
|
@ -191,7 +209,7 @@ async def simplified_run_flow(
|
|||
end_time = time.perf_counter()
|
||||
background_tasks.add_task(
|
||||
telemetry_service.log_package_run,
|
||||
RunPayload(IsWebhook=False, seconds=int(end_time - start_time), success=True, errorMessage=""),
|
||||
RunPayload(runIsWebhook=False, runSeconds=int(end_time - start_time), runSuccess=True, runErrorMessage=""),
|
||||
)
|
||||
return result
|
||||
|
||||
|
|
@ -199,7 +217,9 @@ async def simplified_run_flow(
|
|||
end_time = time.perf_counter()
|
||||
background_tasks.add_task(
|
||||
telemetry_service.log_package_run,
|
||||
RunPayload(IsWebhook=False, seconds=int(end_time - start_time), success=False, errorMessage=str(exc)),
|
||||
RunPayload(
|
||||
runIsWebhook=False, runSeconds=int(end_time - start_time), runSuccess=False, runErrorMessage=str(exc)
|
||||
),
|
||||
)
|
||||
if "badly formed hexadecimal UUID string" in str(exc):
|
||||
# This means the Flow ID is not a valid UUID which means it can't find the flow
|
||||
|
|
@ -213,7 +233,9 @@ async def simplified_run_flow(
|
|||
logger.exception(exc)
|
||||
background_tasks.add_task(
|
||||
telemetry_service.log_package_run,
|
||||
RunPayload(IsWebhook=False, seconds=int(end_time - start_time), success=False, errorMessage=str(exc)),
|
||||
RunPayload(
|
||||
runIsWebhook=False, runSeconds=int(end_time - start_time), runSuccess=False, runErrorMessage=str(exc)
|
||||
),
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc
|
||||
|
||||
|
|
@ -266,20 +288,25 @@ async def webhook_run_flow(
|
|||
)
|
||||
logger.debug("Starting background task")
|
||||
background_tasks.add_task( # type: ignore
|
||||
simple_run_flow,
|
||||
simple_run_flow_task,
|
||||
flow=flow,
|
||||
input_request=input_request,
|
||||
)
|
||||
background_tasks.add_task(
|
||||
telemetry_service.log_package_run,
|
||||
RunPayload(IsWebhook=True, seconds=int(time.perf_counter() - start_time), success=True, errorMessage=""),
|
||||
RunPayload(
|
||||
runIsWebhook=True, runSeconds=int(time.perf_counter() - start_time), runSuccess=True, runErrorMessage=""
|
||||
),
|
||||
)
|
||||
return {"message": "Task started in the background", "status": "in progress"}
|
||||
except Exception as exc:
|
||||
background_tasks.add_task(
|
||||
telemetry_service.log_package_run,
|
||||
RunPayload(
|
||||
IsWebhook=True, seconds=int(time.perf_counter() - start_time), success=False, errorMessage=str(exc)
|
||||
runIsWebhook=True,
|
||||
runSeconds=int(time.perf_counter() - start_time),
|
||||
runSuccess=False,
|
||||
runErrorMessage=str(exc),
|
||||
),
|
||||
)
|
||||
if "Flow ID is required" in str(exc) or "Request body is empty" in str(exc):
|
||||
|
|
|
|||
|
|
@ -209,6 +209,23 @@ def update_flow(
|
|||
webhook_component = get_webhook_component_in_flow(db_flow.data)
|
||||
db_flow.webhook = webhook_component is not None
|
||||
db_flow.updated_at = datetime.now(timezone.utc)
|
||||
|
||||
# First check if the flow.name is unique
|
||||
# there might be flows with name like: "MyFlow", "MyFlow (1)", "MyFlow (2)"
|
||||
# so we need to check if the name is unique with `like` operator
|
||||
# if we find a flow with the same name, we add a number to the end of the name
|
||||
# based on the highest number found
|
||||
flow_from_db = session.exec(select(Flow).where(Flow.id == flow_id, Flow.user_id == current_user.id)).first()
|
||||
if flow_from_db:
|
||||
flows = session.exec(
|
||||
select(Flow).where(Flow.name.like(f"{flow.name} (%")).where(Flow.user_id == current_user.id) # type: ignore
|
||||
).all()
|
||||
if flows:
|
||||
numbers = [int(flow.name.split("(")[1].split(")")[0]) for flow in flows]
|
||||
flow.name = f"{flow.name} ({max(numbers) + 1})"
|
||||
else:
|
||||
flow.name = f"{flow.name} (1)"
|
||||
|
||||
if db_flow.folder_id is None:
|
||||
default_folder = session.exec(select(Folder).where(Folder.name == DEFAULT_FOLDER_NAME)).first()
|
||||
if default_folder:
|
||||
|
|
|
|||
|
|
@ -3,44 +3,40 @@ from pydantic.v1 import SecretStr
|
|||
from langflow.base.constants import STREAM_INFO_TEXT
|
||||
from langflow.base.models.model import LCModelComponent
|
||||
from langflow.field_typing import LanguageModel
|
||||
from langflow.io import BoolInput, DropdownInput, FloatInput, IntInput, MessageInput, Output, SecretStrInput, StrInput
|
||||
from langflow.inputs import (
|
||||
BoolInput,
|
||||
DropdownInput,
|
||||
FloatInput,
|
||||
IntInput,
|
||||
MessageInput,
|
||||
SecretStrInput,
|
||||
StrInput,
|
||||
)
|
||||
|
||||
|
||||
class GoogleGenerativeAIComponent(LCModelComponent):
|
||||
display_name: str = "Google Generative AI"
|
||||
description: str = "Generate text using Google Generative AI."
|
||||
display_name = "Google Generative AI"
|
||||
description = "Generate text using Google Generative AI."
|
||||
icon = "GoogleGenerativeAI"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="google_api_key",
|
||||
display_name="Google API Key",
|
||||
info="The Google API Key to use for the Google Generative AI.",
|
||||
MessageInput(name="input_value", display_name="Input"),
|
||||
IntInput(
|
||||
name="max_output_tokens",
|
||||
display_name="Max Output Tokens",
|
||||
info="The maximum number of tokens to generate.",
|
||||
),
|
||||
DropdownInput(
|
||||
name="model",
|
||||
display_name="Model",
|
||||
info="The name of the model to use.",
|
||||
options=["gemini-1.5-pro", "gemini-1.5-flash"],
|
||||
options=["gemini-1.5-pro", "gemini-1.5-flash", "gemini-1.0-pro", "gemini-1.0-pro-vision"],
|
||||
value="gemini-1.5-pro",
|
||||
),
|
||||
IntInput(
|
||||
name="max_output_tokens",
|
||||
display_name="Max Output Tokens",
|
||||
info="The maximum number of tokens to generate.",
|
||||
advanced=True,
|
||||
),
|
||||
FloatInput(
|
||||
name="temperature",
|
||||
display_name="Temperature",
|
||||
info="Run inference with this temperature. Must by in the closed interval [0.0, 1.0].",
|
||||
value=0.1,
|
||||
),
|
||||
IntInput(
|
||||
name="top_k",
|
||||
display_name="Top K",
|
||||
info="Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.",
|
||||
advanced=True,
|
||||
SecretStrInput(
|
||||
name="google_api_key",
|
||||
display_name="Google API Key",
|
||||
info="The Google API Key to use for the Google Generative AI.",
|
||||
),
|
||||
FloatInput(
|
||||
name="top_p",
|
||||
|
|
@ -48,29 +44,26 @@ class GoogleGenerativeAIComponent(LCModelComponent):
|
|||
info="The maximum cumulative probability of tokens to consider when sampling.",
|
||||
advanced=True,
|
||||
),
|
||||
FloatInput(name="temperature", display_name="Temperature", value=0.1),
|
||||
BoolInput(name="stream", display_name="Stream", info=STREAM_INFO_TEXT, advanced=True),
|
||||
IntInput(
|
||||
name="n",
|
||||
display_name="N",
|
||||
info="Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.",
|
||||
advanced=True,
|
||||
),
|
||||
MessageInput(
|
||||
name="input_value",
|
||||
display_name="Input",
|
||||
info="The input to the model.",
|
||||
input_types=["Text", "Data", "Prompt"],
|
||||
),
|
||||
BoolInput(name="stream", display_name="Stream", info=STREAM_INFO_TEXT, advanced=True),
|
||||
StrInput(
|
||||
name="system_message",
|
||||
display_name="System Message",
|
||||
info="System message to pass to the model.",
|
||||
advanced=True,
|
||||
),
|
||||
]
|
||||
outputs = [
|
||||
Output(display_name="Text", name="text_output", method="text_response"),
|
||||
Output(display_name="Language Model", name="model_output", method="build_model"),
|
||||
IntInput(
|
||||
name="top_k",
|
||||
display_name="Top K",
|
||||
info="Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.",
|
||||
advanced=True,
|
||||
),
|
||||
]
|
||||
|
||||
def build_model(self) -> LanguageModel:
|
||||
|
|
|
|||
|
|
@ -164,15 +164,15 @@ async def get_current_user_for_websocket(
|
|||
|
||||
def get_current_active_user(current_user: Annotated[User, Depends(get_current_user)]):
|
||||
if not current_user.is_active:
|
||||
raise HTTPException(status_code=400, detail="Inactive user")
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Inactive user")
|
||||
return current_user
|
||||
|
||||
|
||||
def get_current_active_superuser(current_user: Annotated[User, Depends(get_current_user)]) -> User:
|
||||
if not current_user.is_active:
|
||||
raise HTTPException(status_code=401, detail="Inactive user")
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Inactive user")
|
||||
if not current_user.is_superuser:
|
||||
raise HTTPException(status_code=400, detail="The user doesn't have enough privileges")
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="The user doesn't have enough privileges")
|
||||
return current_user
|
||||
|
||||
|
||||
|
|
@ -324,8 +324,8 @@ def authenticate_user(username: str, password: str, db: Session = Depends(get_se
|
|||
|
||||
if not user.is_active:
|
||||
if not user.last_login_at:
|
||||
raise HTTPException(status_code=400, detail="Waiting for approval")
|
||||
raise HTTPException(status_code=400, detail="Inactive user")
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Waiting for approval")
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Inactive user")
|
||||
|
||||
return user if verify_password(password, user.password) else None
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ from pydantic import BaseModel
|
|||
|
||||
|
||||
class RunPayload(BaseModel):
|
||||
IsWebhook: bool = False
|
||||
seconds: int
|
||||
success: bool
|
||||
errorMessage: str = ""
|
||||
runIsWebhook: bool = False
|
||||
runSeconds: int
|
||||
runSuccess: bool
|
||||
runErrorMessage: str = ""
|
||||
|
||||
|
||||
class ShutdownPayload(BaseModel):
|
||||
|
|
@ -23,14 +23,14 @@ class VersionPayload(BaseModel):
|
|||
|
||||
|
||||
class PlaygroundPayload(BaseModel):
|
||||
seconds: int
|
||||
componentCount: int | None = None
|
||||
success: bool
|
||||
errorMessage: str = ""
|
||||
playgroundSeconds: int
|
||||
playgroundComponentCount: int | None = None
|
||||
playgroundSuccess: bool
|
||||
playgroundErrorMessage: str = ""
|
||||
|
||||
|
||||
class ComponentPayload(BaseModel):
|
||||
name: str
|
||||
seconds: int
|
||||
success: bool
|
||||
errorMessage: str
|
||||
componentName: str
|
||||
componentSeconds: int
|
||||
componentSuccess: bool
|
||||
componentErrorMessage: str
|
||||
|
|
|
|||
11
src/backend/base/poetry.lock
generated
11
src/backend/base/poetry.lock
generated
|
|
@ -1295,18 +1295,21 @@ types-requests = ">=2.31.0.2,<3.0.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "langsmith"
|
||||
version = "0.1.81"
|
||||
version = "0.1.82"
|
||||
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8.1"
|
||||
files = [
|
||||
{file = "langsmith-0.1.81-py3-none-any.whl", hash = "sha256:3251d823225eef23ee541980b9d9e506367eabbb7f985a086b5d09e8f78ba7e9"},
|
||||
{file = "langsmith-0.1.81.tar.gz", hash = "sha256:585ef3a2251380bd2843a664c9a28da4a7d28432e3ee8bcebf291ffb8e1f0af0"},
|
||||
{file = "langsmith-0.1.82-py3-none-any.whl", hash = "sha256:9b3653e7d316036b0c60bf0bc3e280662d660f485a4ebd8e5c9d84f9831ae79c"},
|
||||
{file = "langsmith-0.1.82.tar.gz", hash = "sha256:c02e2bbc488c10c13b52c69d271eb40bd38da078d37b6ae7ae04a18bd48140be"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
orjson = ">=3.9.14,<4.0.0"
|
||||
pydantic = ">=1,<3"
|
||||
pydantic = [
|
||||
{version = ">=1,<3", markers = "python_full_version < \"3.12.4\""},
|
||||
{version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""},
|
||||
]
|
||||
requests = ">=2,<3"
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "langflow-base"
|
||||
version = "0.0.79"
|
||||
version = "0.0.81"
|
||||
description = "A Python package with a built-in web application"
|
||||
authors = ["Langflow <contact@langflow.org>"]
|
||||
maintainers = [
|
||||
|
|
|
|||
2
src/frontend/package-lock.json
generated
2
src/frontend/package-lock.json
generated
|
|
@ -102,7 +102,7 @@
|
|||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"prettier-plugin-tailwindcss": "^0.6.4",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"tailwindcss-dotted-background": "^1.1.0",
|
||||
|
|
|
|||
|
|
@ -113,18 +113,18 @@
|
|||
"@testing-library/react": "^16.0.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/lodash": "4.17.5",
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@types/lodash": "4.17.5",
|
||||
"@vitejs/plugin-react-swc": "^3.7.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^9.5.0",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"prettier-plugin-tailwindcss": "^0.6.4",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"tailwindcss-dotted-background": "^1.1.0",
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ export default function TableNodeCellRender({
|
|||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
templateValue?.length === 0 || !templateValue
|
||||
Object.keys(templateValue)?.length === 0 || !templateValue
|
||||
? [{ "": "" }]
|
||||
: convertObjToArray(templateValue, templateData.type)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { useEffect } from "react";
|
|||
import { EDIT_TEXT_MODAL_TITLE } from "../../constants/constants";
|
||||
import { TypeModal } from "../../constants/enums";
|
||||
import GenericModal from "../../modals/genericModal";
|
||||
import { Case } from "../../shared/components/caseComponent";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { Button } from "../ui/button";
|
||||
|
|
@ -24,29 +25,31 @@ export default function TextAreaComponent({
|
|||
return (
|
||||
<div className={"flex w-full items-center " + (disabled ? "" : "")}>
|
||||
<div className="flex w-full items-center gap-3" data-testid={"div-" + id}>
|
||||
<Input
|
||||
id={id}
|
||||
data-testid={id}
|
||||
value={value}
|
||||
disabled={disabled}
|
||||
className={editNode ? "input-edit-node w-full" : "w-full"}
|
||||
placeholder={"Type something..."}
|
||||
onChange={(event) => {
|
||||
onChange(event.target.value);
|
||||
}}
|
||||
/>
|
||||
<div className="flex items-center">
|
||||
<GenericModal
|
||||
type={TypeModal.TEXT}
|
||||
buttonText="Finish Editing"
|
||||
modalTitle={EDIT_TEXT_MODAL_TITLE}
|
||||
<Case condition={!editNode}>
|
||||
<Input
|
||||
id={id}
|
||||
data-testid={id}
|
||||
value={value}
|
||||
setValue={(value: string) => {
|
||||
onChange(value);
|
||||
}}
|
||||
disabled={disabled}
|
||||
>
|
||||
{!editNode && (
|
||||
className={editNode ? "input-edit-node w-full" : "w-full"}
|
||||
placeholder={"Type something..."}
|
||||
onChange={(event) => {
|
||||
onChange(event.target.value);
|
||||
}}
|
||||
/>
|
||||
</Case>
|
||||
<GenericModal
|
||||
type={TypeModal.TEXT}
|
||||
buttonText="Finish Editing"
|
||||
modalTitle={EDIT_TEXT_MODAL_TITLE}
|
||||
value={value}
|
||||
setValue={(value: string) => {
|
||||
onChange(value);
|
||||
}}
|
||||
disabled={disabled}
|
||||
>
|
||||
{!editNode ? (
|
||||
<div className="flex items-center">
|
||||
<Button unstyled>
|
||||
<IconComponent
|
||||
strokeWidth={1.5}
|
||||
|
|
@ -58,9 +61,26 @@ export default function TextAreaComponent({
|
|||
}
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
</GenericModal>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<Button unstyled className="w-full">
|
||||
<div className="flex w-full items-center gap-3">
|
||||
<span
|
||||
id={id}
|
||||
data-testid={id}
|
||||
className={
|
||||
editNode
|
||||
? "input-edit-node input-dialog"
|
||||
: (disabled ? "input-disable text-ring " : "") +
|
||||
" primary-input text-muted-foreground"
|
||||
}
|
||||
>
|
||||
{value !== "" ? value : "Type something..."}
|
||||
</span>
|
||||
</div>
|
||||
</Button>
|
||||
)}
|
||||
</GenericModal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -65,12 +65,6 @@ const EditNodeModal = forwardRef(
|
|||
}
|
||||
}, [gridApi, open]);
|
||||
|
||||
// useEffect(() => {
|
||||
// return () => {
|
||||
// setOpenWDoubleClick(false);
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<BaseModal key={data.id} open={open} setOpen={setOpen}>
|
||||
<BaseModal.Trigger>
|
||||
|
|
|
|||
|
|
@ -270,12 +270,12 @@ test("Blog Writer", async ({ page }) => {
|
|||
"https://www.natgeokids.com/uk/discover/animals/sea-life/turtle-facts/",
|
||||
);
|
||||
await page
|
||||
.getByTestId("input-list-input_urls-0")
|
||||
.nth(1)
|
||||
.getByTestId("input-list-input_urls-1")
|
||||
.nth(0)
|
||||
.fill("https://www.originaldiving.com/blog/top-ten-turtle-facts");
|
||||
|
||||
await page
|
||||
.getByTestId("textarea-input_value")
|
||||
.getByTestId("popover-anchor-input-input_value")
|
||||
.nth(0)
|
||||
.fill(
|
||||
"Use the references above for style to write a new blog/tutorial about turtles. Suggest non-covered topics.",
|
||||
|
|
@ -284,7 +284,7 @@ test("Blog Writer", async ({ page }) => {
|
|||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.waitForTimeout(5000);
|
||||
await page.getByText("built successfully").last().click({
|
||||
timeout: 15000,
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByText("Playground", { exact: true }).click();
|
||||
|
|
@ -403,17 +403,14 @@ test("Vector Store RAG", async ({ page }) => {
|
|||
await page.getByText("test_file.txt").isVisible();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.getByTestId("button_run_astra db vector store").first().click();
|
||||
await page
|
||||
.getByText("Astra DB Vector Store built successfully")
|
||||
.last()
|
||||
.click({
|
||||
timeout: 15000,
|
||||
});
|
||||
await page.getByTestId("button_run_astra db").first().click();
|
||||
await page.getByText("built successfully").last().click({
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
await page.getByText("built successfully").last().click({
|
||||
timeout: 15000,
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByText("Playground", { exact: true }).click();
|
||||
|
|
@ -427,15 +424,6 @@ test("Vector Store RAG", async ({ page }) => {
|
|||
.last()
|
||||
.isVisible();
|
||||
|
||||
await page.getByText("Extracted Chunks", { exact: true }).last().click();
|
||||
|
||||
const inputChunksValues = await page.getByPlaceholder("Empty").inputValue();
|
||||
expect(inputChunksValues).toBe(
|
||||
"this is a test file---this is a test file---this is a test file---this is a test file",
|
||||
);
|
||||
|
||||
await page.getByTestId("icon-ExternalLink").last().click();
|
||||
await page.getByPlaceholder("Send a message...").last().isHidden();
|
||||
await page.getByText("Memories", { exact: true }).last().click();
|
||||
await page.getByText("Default Session").last().click();
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ test("chat_io_teste", async ({ page }) => {
|
|||
}
|
||||
|
||||
const jsonContent = readFileSync(
|
||||
"src/frontend/tests/end-to-end/assets/ChatTest.json",
|
||||
"tests/end-to-end/assets/ChatTest.json",
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,14 +48,21 @@ test("user must interact with chat with Input/Output", async ({ page }) => {
|
|||
await page.getByPlaceholder("Send a message...").fill("Hello, how are you?");
|
||||
await page.getByTestId("icon-LucideSend").click();
|
||||
let valueUser = await page.getByTestId("sender_name_user").textContent();
|
||||
|
||||
await page.waitForSelector('[data-testid="sender_name_ai"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
let valueAI = await page.getByTestId("sender_name_ai").textContent();
|
||||
|
||||
expect(valueUser).toBe("User");
|
||||
expect(valueAI).toBe("AI");
|
||||
|
||||
await page.keyboard.press("Escape");
|
||||
|
||||
await page
|
||||
.getByTestId("textarea-input_value")
|
||||
.nth(1)
|
||||
.nth(0)
|
||||
.fill(
|
||||
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!",
|
||||
);
|
||||
|
|
@ -73,11 +80,11 @@ test("user must interact with chat with Input/Output", async ({ page }) => {
|
|||
await page.getByText("Save Changes", { exact: true }).click();
|
||||
|
||||
await page
|
||||
.getByTestId("textarea-sender_name")
|
||||
.getByTestId("popover-anchor-input-sender_name")
|
||||
.nth(1)
|
||||
.fill("TestSenderNameUser");
|
||||
await page
|
||||
.getByTestId("textarea-sender_name")
|
||||
.getByTestId("popover-anchor-input-sender_name")
|
||||
.nth(0)
|
||||
.fill("TestSenderNameAI");
|
||||
|
||||
|
|
@ -150,6 +157,10 @@ test("user must be able to see output inspection", async ({ page }) => {
|
|||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await page.waitForSelector('[data-testid="icon-ScanEye"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByTestId("icon-ScanEye").nth(4).click();
|
||||
|
||||
await page.getByText("Sender", { exact: true }).isVisible();
|
||||
|
|
@ -206,32 +217,46 @@ test("user must be able to send an image on chat", async ({ page }) => {
|
|||
|
||||
await page.getByText("Playground", { exact: true }).click();
|
||||
|
||||
const jsonContent = readFileSync(
|
||||
"src/frontend/tests/end-to-end/assets/chain.png",
|
||||
"utf-8",
|
||||
// Read the image file as a binary string
|
||||
const filePath = "tests/end-to-end/assets/chain.png";
|
||||
const fileContent = readFileSync(filePath, "base64");
|
||||
|
||||
// Create the DataTransfer and File objects within the browser context
|
||||
const dataTransfer = await page.evaluateHandle(
|
||||
({ fileContent }) => {
|
||||
const dt = new DataTransfer();
|
||||
const byteCharacters = atob(fileContent);
|
||||
const byteNumbers = new Array(byteCharacters.length);
|
||||
for (let i = 0; i < byteCharacters.length; i++) {
|
||||
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
}
|
||||
const byteArray = new Uint8Array(byteNumbers);
|
||||
const file = new File([byteArray], "chain.png", { type: "image/png" });
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
},
|
||||
{ fileContent },
|
||||
);
|
||||
|
||||
// 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], "chain.png", {
|
||||
type: "application/json",
|
||||
});
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
}, jsonContent);
|
||||
|
||||
// Locate the target element
|
||||
const element = await page.getByPlaceholder("Send a message...");
|
||||
|
||||
// Dispatch the drop event on the target element
|
||||
await element.dispatchEvent("drop", { dataTransfer });
|
||||
|
||||
await page.waitForTimeout(4000);
|
||||
|
||||
await page.getByText("chain.png").isVisible();
|
||||
await page.getByTestId("icon-LucideSend").click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByText("chain.png").isVisible();
|
||||
|
||||
await page.getByText("Close", { exact: true }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="icon-ScanEye"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.getByTestId("icon-ScanEye").nth(4).click();
|
||||
await page.getByText("Restart").isHidden();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ test("CodeAreaModalComponent", async ({ page }) => {
|
|||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("experimentalPython Function")
|
||||
.getByTestId("prototypesPython Function")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
|
@ -65,19 +65,9 @@ class PythonFunctionComponent(CustomComponent):
|
|||
await page.locator("textarea").fill(wCode);
|
||||
await page.locator('//*[@id="checkAndSaveBtn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
// expect(
|
||||
// await page.getByText("invalid syntax (<unknown>, line 1)").isVisible()
|
||||
// ).toBeTruthy();
|
||||
await page.locator("textarea").press("Control+a");
|
||||
await page.locator("textarea").fill(wCode);
|
||||
await page.locator("textarea").fill(customComponentCode);
|
||||
await page.locator('//*[@id="checkAndSaveBtn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// await page.getByTestId("code-button-modal").click();
|
||||
// const inputCodeValue = await page
|
||||
// .locator('//*[@id="codeValue"]')
|
||||
// .inputValue();
|
||||
|
||||
// expect(inputCodeValue).toContain("def python_function(text: str) -> str");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,7 +17,14 @@ test("should delete a flow", async ({ page }) => {
|
|||
await page.waitForTimeout(5000);
|
||||
await page.getByText("My Collection").nth(0).click();
|
||||
await page.getByText("Website Content QA").first().isVisible();
|
||||
|
||||
await page.getByLabel("checkbox-component").last().waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000, // Timeout of 30 seconds
|
||||
});
|
||||
|
||||
await page.getByLabel("checkbox-component").first().click();
|
||||
|
||||
await page.getByTestId("icon-Trash2").click();
|
||||
await page
|
||||
.getByText("Are you sure you want to delete the selected component?")
|
||||
|
|
@ -36,6 +43,12 @@ test("should delete a component", async ({ page }) => {
|
|||
await page.getByText("My Collection").nth(0).click();
|
||||
await page.getByText("Components").first().click();
|
||||
await page.getByText("Basic RAG").first().isVisible();
|
||||
|
||||
await page.getByLabel("checkbox-component").last().waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000, // Timeout of 30 seconds
|
||||
});
|
||||
|
||||
await page.getByLabel("checkbox-component").first().click();
|
||||
await page.getByTestId("icon-Trash2").click();
|
||||
await page
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ test.describe("drag and drop test", () => {
|
|||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"src/frontend/tests/end-to-end/assets/collection.json",
|
||||
"tests/end-to-end/assets/collection.json",
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,24 +44,40 @@ test("LLMChain - Tooltip", async ({ page }) => {
|
|||
)
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await expect(page.getByTestId("tooltip-Chains").first()).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("tooltip-Model Specs").first(),
|
||||
page.getByTestId("available-output-chains").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("tooltip-Vector Search").first(),
|
||||
page.getByTestId("available-output-textsplitters").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("tooltip-Text Splitters").first(),
|
||||
page.getByTestId("available-output-retrievers").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("tooltip-Retrievers").first(),
|
||||
page.getByTestId("available-output-prototypes").first(),
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Tools").first()).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Memories").first()).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Agents").first()).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Helpers").first()).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Utilities").first()).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-output-tools").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-output-memories").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-output-toolkits").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-output-chains").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-output-agents").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-output-helpers").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-output-langchain_utilities").first(),
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByTestId("icon-X").click();
|
||||
await page.waitForTimeout(500);
|
||||
});
|
||||
|
|
@ -77,12 +93,10 @@ test("LLMChain - Tooltip", async ({ page }) => {
|
|||
.hover()
|
||||
.then(async () => {
|
||||
await expect(
|
||||
page.getByTestId("tooltip-Model Specs").first(),
|
||||
page.getByTestId("available-input-models").first(),
|
||||
).toBeVisible();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await expect(page.getByTestId("tooltip-Models").first()).toBeVisible();
|
||||
|
||||
await page.getByTestId("icon-Search").click();
|
||||
|
||||
await page.waitForTimeout(500);
|
||||
|
|
@ -100,12 +114,18 @@ test("LLMChain - Tooltip", async ({ page }) => {
|
|||
.then(async () => {
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await expect(page.getByTestId("tooltip-Chains").first()).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("tooltip-Experimental").first(),
|
||||
page.getByTestId("available-input-chains").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-input-prototypes").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-input-agents").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("available-input-helpers").first(),
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Agents").first()).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Helpers").first()).toBeVisible();
|
||||
|
||||
await page.waitForTimeout(500);
|
||||
});
|
||||
|
|
@ -176,26 +196,30 @@ test("LLMChain - Filter", async ({ page }) => {
|
|||
)
|
||||
.click();
|
||||
|
||||
await expect(page.getByTestId("disclosure-model specs")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAnthropic").first()).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAmazon Bedrock")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAzureChatOpenAI")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsChatLiteLLM")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsChatOllama")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsChatOpenAI")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsChatVertexAI")).toBeVisible();
|
||||
await expect(page.getByTestId("disclosure-models")).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("model_specsGoogle Generative AI"),
|
||||
page.getByTestId("modelsGoogle Generative AI").first(),
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("chainsLLMChain").first()).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("langchain_utilitiesSearchApi").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("model_specsHugging Face Inference API"),
|
||||
page.getByTestId("memoriesAstra DB Message Reader").first(),
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsOllama")).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("model_specsQianfanChatEndpoint"),
|
||||
page.getByTestId("prototypesFlow as Tool").first(),
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsQianfanLLMEndpoint")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsVertexAI")).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("retrieversAmazon Kendra Retriever").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("textsplittersCharacterTextSplitter").first(),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("toolkitsVectorStoreInfo").first(),
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("toolsSearchApi").first()).toBeVisible();
|
||||
|
||||
await page.getByPlaceholder("Search").click();
|
||||
|
||||
|
|
@ -219,7 +243,6 @@ test("LLMChain - Filter", async ({ page }) => {
|
|||
.click();
|
||||
|
||||
await expect(page.getByTestId("disclosure-models")).toBeVisible();
|
||||
await expect(page.getByTestId("disclosure-model specs")).toBeVisible();
|
||||
|
||||
await page
|
||||
.locator(
|
||||
|
|
@ -227,10 +250,8 @@ test("LLMChain - Filter", async ({ page }) => {
|
|||
)
|
||||
.click();
|
||||
|
||||
await expect(page.getByTestId("disclosure-saved")).toBeVisible();
|
||||
|
||||
await expect(page.getByTestId("disclosure-helpers")).toBeVisible();
|
||||
await expect(page.getByTestId("disclosure-agents")).toBeVisible();
|
||||
await expect(page.getByTestId("disclosure-chains")).toBeVisible();
|
||||
await expect(page.getByTestId("disclosure-experimental")).toBeVisible();
|
||||
await expect(page.getByTestId("disclosure-prototypes")).toBeVisible();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ test("add folder by drag and drop", async ({ page }) => {
|
|||
await page.waitForTimeout(2000);
|
||||
|
||||
const jsonContent = readFileSync(
|
||||
"src/frontend/tests/end-to-end/assets/collection.json",
|
||||
"tests/end-to-end/assets/collection.json",
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,11 @@ test("erase button should clear the chat messages", async ({ page }) => {
|
|||
await page.getByPlaceholder("Send a message...").fill("Hello, how are you?");
|
||||
await page.getByTestId("icon-LucideSend").click();
|
||||
let valueUser = await page.getByTestId("sender_name_user").textContent();
|
||||
|
||||
await page.waitForSelector('[data-testid="sender_name_ai"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
let valueAI = await page.getByTestId("sender_name_ai").textContent();
|
||||
|
||||
expect(valueUser).toBe("User");
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ test("InputListComponent", async ({ page }) => {
|
|||
await page.waitForTimeout(3000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("astradb");
|
||||
await page.getByPlaceholder("Search").fill("url");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page
|
||||
.getByTestId("vectorsearchAstra DB Search")
|
||||
.getByTestId("dataURL")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
|
@ -36,95 +36,71 @@ test("InputListComponent", async ({ page }) => {
|
|||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page.getByTestId("input-list-input_urls-0").fill("test test test test");
|
||||
|
||||
await page.getByTestId("input-list-plus-btn_urls-0").click();
|
||||
|
||||
await page.getByTestId("input-list-plus-btn_urls-0").click();
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-input_urls-1")
|
||||
.fill("test1 test1 test1 test1");
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-input_urls-2")
|
||||
.fill("test2 test2 test2 test2");
|
||||
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
expect(
|
||||
await page.getByTestId("showmetadata_indexing_exclude").isChecked(),
|
||||
).toBeFalsy();
|
||||
await page.getByTestId("showmetadata_indexing_exclude").click();
|
||||
expect(
|
||||
await page.getByTestId("showmetadata_indexing_exclude").isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
expect(
|
||||
await page.getByTestId("showmetadata_indexing_include").isChecked(),
|
||||
).toBeFalsy();
|
||||
await page.getByTestId("showmetadata_indexing_include").click();
|
||||
expect(
|
||||
await page.getByTestId("showmetadata_indexing_include").isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-input-edit_metadata_indexing_include-0")
|
||||
.fill("test test test test");
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-plus-btn-edit_metadata_indexing_include-0")
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-input-edit_metadata_indexing_include-1")
|
||||
.fill("test1 test1 test1 test1");
|
||||
|
||||
await page.getByText("Save Changes", { exact: true }).click();
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-input_metadata_indexing_include-0")
|
||||
.fill("test test test test");
|
||||
|
||||
const value0 = await page
|
||||
.getByTestId("input-list-input_metadata_indexing_include-0")
|
||||
.getByTestId("input-list-input-edit_urls-0")
|
||||
.inputValue();
|
||||
const value1 = await page
|
||||
.getByTestId("input-list-input_metadata_indexing_include-1")
|
||||
.getByTestId("input-list-input-edit_urls-1")
|
||||
.inputValue();
|
||||
|
||||
const value2 = await page
|
||||
.getByTestId("input-list-input-edit_urls-2")
|
||||
.inputValue();
|
||||
|
||||
if (
|
||||
value0 !== "test test test test" ||
|
||||
value1 !== "test1 test1 test1 test1"
|
||||
value1 !== "test1 test1 test1 test1" ||
|
||||
value2 !== "test2 test2 test2 test2"
|
||||
) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-minus-btn_metadata_indexing_include-1")
|
||||
.click();
|
||||
await page.getByTestId("input-list-minus-btn-edit_urls-1").click();
|
||||
|
||||
const plusButtonLocator = page.getByTestId(
|
||||
"input-list-plus-btn_metadata_indexing_include-1",
|
||||
"input-list-minus-btn-edit_urls-1",
|
||||
);
|
||||
const elementCount = await plusButtonLocator?.count();
|
||||
|
||||
if (elementCount > 0) {
|
||||
if (elementCount > 1) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-plus-btn_metadata_indexing_include-0")
|
||||
.click();
|
||||
await page
|
||||
.getByTestId("input-list-plus-btn_metadata_indexing_include-0")
|
||||
.click();
|
||||
await page
|
||||
.getByTestId("input-list-plus-btn_metadata_indexing_include-0")
|
||||
.click();
|
||||
await page
|
||||
.getByTestId("input-list-plus-btn_metadata_indexing_include-0")
|
||||
.click();
|
||||
await page.getByText("Save Changes", { exact: true }).click();
|
||||
|
||||
await page.getByTestId("input-list-minus-btn_urls-2").isHidden();
|
||||
|
||||
await page.getByTestId("input-list-plus-btn_urls-0").click();
|
||||
await page.getByTestId("input-list-plus-btn_urls-0").click();
|
||||
|
||||
await page.getByTestId("input-list-input_urls-0").fill("test test test test");
|
||||
await page
|
||||
.getByTestId("input-list-input_metadata_indexing_include-0")
|
||||
.fill("test test test test");
|
||||
await page
|
||||
.getByTestId("input-list-input_metadata_indexing_include-1")
|
||||
.getByTestId("input-list-input_urls-1")
|
||||
.fill("test1 test1 test1 test1");
|
||||
await page
|
||||
.getByTestId("input-list-input_metadata_indexing_include-2")
|
||||
.getByTestId("input-list-input_urls-2")
|
||||
.fill("test2 test2 test2 test2");
|
||||
await page
|
||||
.getByTestId("input-list-input_metadata_indexing_include-3")
|
||||
.getByTestId("input-list-input_urls-3")
|
||||
.fill("test3 test3 test3 test3");
|
||||
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
|
|
@ -132,16 +108,16 @@ test("InputListComponent", async ({ page }) => {
|
|||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
const value0Edit = await page
|
||||
.getByTestId("input-list-input-edit_metadata_indexing_include-0")
|
||||
.getByTestId("input-list-input-edit_urls-0")
|
||||
.inputValue();
|
||||
const value1Edit = await page
|
||||
.getByTestId("input-list-input-edit_metadata_indexing_include-1")
|
||||
.getByTestId("input-list-input-edit_urls-1")
|
||||
.inputValue();
|
||||
const value2Edit = await page
|
||||
.getByTestId("input-list-input-edit_metadata_indexing_include-2")
|
||||
.getByTestId("input-list-input-edit_urls-2")
|
||||
.inputValue();
|
||||
const value3Edit = await page
|
||||
.getByTestId("input-list-input-edit_metadata_indexing_include-3")
|
||||
.getByTestId("input-list-input-edit_urls-3")
|
||||
.inputValue();
|
||||
|
||||
if (
|
||||
|
|
@ -153,23 +129,17 @@ test("InputListComponent", async ({ page }) => {
|
|||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page
|
||||
.getByTestId("input-list-minus-btn-edit_metadata_indexing_include-1")
|
||||
.click();
|
||||
await page
|
||||
.getByTestId("input-list-minus-btn-edit_metadata_indexing_include-1")
|
||||
.click();
|
||||
await page
|
||||
.getByTestId("input-list-minus-btn-edit_metadata_indexing_include-1")
|
||||
.click();
|
||||
await page.getByTestId("input-list-minus-btn-edit_urls-1").click();
|
||||
await page.getByTestId("input-list-minus-btn-edit_urls-1").click();
|
||||
await page.getByTestId("input-list-minus-btn-edit_urls-1").click();
|
||||
|
||||
const plusButtonLocatorEdit0 = await page.getByTestId(
|
||||
"input-list-plus-btn-edit_metadata_indexing_include-0",
|
||||
"input-list-plus-btn-edit_urls-0",
|
||||
);
|
||||
const elementCountEdit0 = await plusButtonLocatorEdit0?.count();
|
||||
|
||||
const plusButtonLocatorEdit2 = await page.getByTestId(
|
||||
"input-list-plus-btn-edit_metadata_indexing_include-2",
|
||||
"input-list-plus-btn-edit_urls-1",
|
||||
);
|
||||
const elementCountEdit2 = await plusButtonLocatorEdit2?.count();
|
||||
|
||||
|
|
@ -178,13 +148,13 @@ test("InputListComponent", async ({ page }) => {
|
|||
}
|
||||
|
||||
const minusButtonLocatorEdit1 = await page.getByTestId(
|
||||
"input-list-minus-btn-edit_metadata_indexing_include-1",
|
||||
"input-list-minus-btn-edit_urls-1",
|
||||
);
|
||||
|
||||
const elementCountMinusEdit1 = await minusButtonLocatorEdit1?.count();
|
||||
|
||||
const minusButtonLocatorEdit2 = await page.getByTestId(
|
||||
"input-list-minus-btn-edit_metadata_indexing_include-2",
|
||||
"input-list-minus-btn-edit_urls-2",
|
||||
);
|
||||
|
||||
const elementCountMinusEdit2 = await minusButtonLocatorEdit2?.count();
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ test("IntComponent", async ({ page }) => {
|
|||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("model_specsChatOpenAI")
|
||||
.getByTestId("modelsOpenAI")
|
||||
.first()
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
|
|
@ -65,7 +65,7 @@ test("IntComponent", async ({ page }) => {
|
|||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.getByTestId("title-ChatOpenAI").click();
|
||||
await page.getByTestId("title-OpenAI").click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ test("KeypairListComponent", async ({ page }) => {
|
|||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("model_specsAmazon Bedrock")
|
||||
.getByTestId("modelsAmazon Bedrock")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
|
@ -38,6 +38,14 @@ test("KeypairListComponent", async ({ page }) => {
|
|||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
await page.getByTestId("showmodel_kwargs").click();
|
||||
expect(await page.getByTestId("showmodel_kwargs").isChecked()).toBeTruthy();
|
||||
await page.getByText("Save Changes", { exact: true }).click();
|
||||
|
||||
await page.locator('//*[@id="keypair0"]').click();
|
||||
await page.locator('//*[@id="keypair0"]').fill("testtesttesttest");
|
||||
await page.locator('//*[@id="keypair100"]').click();
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ test("PromptTemplateComponent", async ({ page }) => {
|
|||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
|
||||
await page.getByTestId("save-button-modal").click();
|
||||
|
|
@ -102,13 +104,16 @@ test("PromptTemplateComponent", async ({ page }) => {
|
|||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
value = await page.locator('//*[@id="textarea-edit-prompt"]').inputValue();
|
||||
value =
|
||||
(await page.locator('//*[@id="textarea-edit-prompt"]').textContent()) ?? "";
|
||||
|
||||
if (value != "prompt_value_!@#!@#") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
value = await page.locator('//*[@id="textarea-edit-prompt1"]').inputValue();
|
||||
value =
|
||||
(await page.locator('//*[@id="textarea-edit-prompt1"]').textContent()) ??
|
||||
"";
|
||||
|
||||
if (value != "prompt_name_test_123123!@#!@#") {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
@ -122,13 +127,20 @@ test("PromptTemplateComponent", async ({ page }) => {
|
|||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.locator('//*[@id="textarea-edit-prompt1"]').click();
|
||||
await page
|
||||
.locator('//*[@id="textarea-edit-prompt1"]')
|
||||
.getByTestId("text-area-modal")
|
||||
.fill("prompt_edit_test_12312312321!@#$");
|
||||
|
||||
await page.getByText("Finish Editing", { exact: true }).click();
|
||||
|
||||
await page.locator('//*[@id="textarea-edit-prompt"]').click();
|
||||
await page
|
||||
.locator('//*[@id="textarea-edit-prompt"]')
|
||||
.getByTestId("text-area-modal")
|
||||
.fill("prompt_edit_test_44444444444!@#$");
|
||||
|
||||
await page.getByText("Finish Editing", { exact: true }).click();
|
||||
|
||||
await page.locator('//*[@id="showtemplate"]').click();
|
||||
expect(await page.locator('//*[@id="showtemplate"]').isChecked()).toBeFalsy();
|
||||
|
||||
|
|
@ -174,13 +186,16 @@ test("PromptTemplateComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showprompt1"]').click();
|
||||
expect(await page.locator('//*[@id="showprompt1"]').isChecked()).toBeTruthy();
|
||||
|
||||
value = await page.locator('//*[@id="textarea-edit-prompt"]').inputValue();
|
||||
value =
|
||||
(await page.locator('//*[@id="textarea-edit-prompt"]').textContent()) ?? "";
|
||||
|
||||
if (value != "prompt_edit_test_44444444444!@#$") {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
value = await page.locator('//*[@id="textarea-edit-prompt1"]').inputValue();
|
||||
value =
|
||||
(await page.locator('//*[@id="textarea-edit-prompt1"]').textContent()) ??
|
||||
"";
|
||||
|
||||
if (value != "prompt_edit_test_12312312321!@#$") {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ test.describe("save component tests", () => {
|
|||
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"src/frontend/tests/end-to-end/assets/flow_group_test.json",
|
||||
"tests/end-to-end/assets/flow_group_test.json",
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -259,6 +259,10 @@ test("should share component with share button", async ({ page }) => {
|
|||
await page.getByText("Save").last().click();
|
||||
await page.getByText("Close").last().click();
|
||||
|
||||
await page.waitForSelector('[data-testid="icon-Share3"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await page.getByTestId("icon-Share3").first().click();
|
||||
await page.getByText("Name:").isVisible();
|
||||
await page.getByText("Description:").isVisible();
|
||||
|
|
|
|||
|
|
@ -21,8 +21,17 @@ test("TextAreaModalComponent", async ({ page }) => {
|
|||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
|
||||
await page.waitForSelector('[data-testid="extended-disclosure"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
const focusElementsOnBoard = async ({ page }) => {
|
||||
const focusElements = await page.getByTestId("extended-disclosure");
|
||||
await focusElements.click();
|
||||
};
|
||||
|
||||
await focusElementsOnBoard({ page });
|
||||
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("prompt");
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,17 @@ test("TextInputOutputComponent", async ({ page }) => {
|
|||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.waitForSelector('[data-testid="extended-disclosure"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
const focusElementsOnBoard = async ({ page }) => {
|
||||
const focusElements = await page.getByTestId("extended-disclosure");
|
||||
focusElements.click();
|
||||
};
|
||||
|
||||
await focusElementsOnBoard({ page });
|
||||
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("text input");
|
||||
await page.waitForTimeout(1000);
|
||||
|
|
@ -56,7 +65,15 @@ test("TextInputOutputComponent", async ({ page }) => {
|
|||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
// Click and hold on the first element
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div/div/div[2]/div[1]/div/div[2]/div[5]/button/div[1]',
|
||||
)
|
||||
.waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div/div/div[2]/div[1]/div/div[2]/div[5]/button/div[1]',
|
||||
|
|
@ -64,6 +81,15 @@ test("TextInputOutputComponent", async ({ page }) => {
|
|||
.hover();
|
||||
await page.mouse.down();
|
||||
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div/div/div[2]/div[2]/div/div[2]/div[3]/div/button/div[1]',
|
||||
)
|
||||
.waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
// Move to the second element
|
||||
await page
|
||||
.locator(
|
||||
|
|
@ -88,6 +114,15 @@ test("TextInputOutputComponent", async ({ page }) => {
|
|||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div/div/div[2]/div[2]/div/div[2]/div[15]/button/div[1]',
|
||||
)
|
||||
.waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
// Click and hold on the first element
|
||||
await page
|
||||
.locator(
|
||||
|
|
@ -96,6 +131,15 @@ test("TextInputOutputComponent", async ({ page }) => {
|
|||
.hover();
|
||||
await page.mouse.down();
|
||||
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div/div/div[2]/div[3]/div/div[2]/div[3]/div/button/div[1]',
|
||||
)
|
||||
.waitFor({
|
||||
state: "visible",
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
// Move to the second element
|
||||
await page
|
||||
.locator(
|
||||
|
|
|
|||
|
|
@ -21,8 +21,16 @@ test("ToggleComponent", async ({ page }) => {
|
|||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
|
||||
await page.waitForSelector('[data-testid="extended-disclosure"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
const focusElementsOnBoard = async ({ page }) => {
|
||||
const focusElements = await page.getByTestId("extended-disclosure");
|
||||
focusElements.click();
|
||||
};
|
||||
|
||||
await focusElementsOnBoard({ page });
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("directory");
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,13 @@ test("check if tweaks are updating when someothing on the flow changes", async (
|
|||
.getByTestId("popover-anchor-input-persist_directory")
|
||||
.fill("persist_directory_123123123!@#$&*(&%$@");
|
||||
|
||||
await page.getByText("API", { exact: true }).first().click();
|
||||
const focusElementsOnBoard = async ({ page }) => {
|
||||
await page.waitForSelector("text=API", { timeout: 30000 });
|
||||
const focusElements = await page.getByText("API", { exact: true }).first();
|
||||
await focusElements.click();
|
||||
};
|
||||
|
||||
await focusElementsOnBoard({ page });
|
||||
|
||||
await page.getByText("Tweaks").nth(1).click();
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,23 @@ test("user should be able to see multiple edges and interact with them", async (
|
|||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByText("Vector Store RAG", { exact: true }).last().click();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.waitForTimeout(5000);
|
||||
await page.getByText("Retriever", { exact: true }).first().isVisible();
|
||||
await page.getByText("Search Results", { exact: true }).first().isVisible();
|
||||
await page.getByTestId("icon-Eye").nth(24).click();
|
||||
|
||||
const focusElementsOnBoard = async ({ page }) => {
|
||||
await page.waitForSelector('[title="fit view"]', { timeout: 30000 });
|
||||
const focusElements = await page.getByTitle("fit view");
|
||||
await focusElements.click();
|
||||
};
|
||||
|
||||
await focusElementsOnBoard({ page });
|
||||
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page.getByTestId("output-inspection-retriever").first().click();
|
||||
await page.getByText("Retriever", { exact: true }).first().isHidden();
|
||||
await page.getByTestId("icon-ChevronDown").last().isVisible();
|
||||
await page.getByTestId("icon-ChevronDown").last().click();
|
||||
|
|
|
|||
|
|
@ -62,10 +62,19 @@ test("should interact with global variables", async ({ page }) => {
|
|||
|
||||
await page.getByText(randomName).isVisible();
|
||||
|
||||
await page
|
||||
.getByLabel("Press Space to toggle all rows selection (unchecked)")
|
||||
.nth(0)
|
||||
.click();
|
||||
const focusElementsOnBoard = async ({ page }) => {
|
||||
await page.waitForSelector(
|
||||
'[aria-label="Press Space to toggle all rows selection (unchecked)"]',
|
||||
{ timeout: 30000 },
|
||||
);
|
||||
const focusElements = await page
|
||||
.getByLabel("Press Space to toggle all rows selection (unchecked)")
|
||||
.first();
|
||||
await focusElements.click();
|
||||
};
|
||||
|
||||
await focusElementsOnBoard({ page });
|
||||
|
||||
await page.getByTestId("icon-Trash2").click();
|
||||
await page.getByText("No data available").isVisible();
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue