Merge remote-tracking branch 'origin/dev' into saveComponent

This commit is contained in:
anovazzi1 2023-10-18 18:23:34 -03:00
commit 92a109b65c
34 changed files with 5801 additions and 1172 deletions

4
.gitignore vendored
View file

@ -254,4 +254,6 @@ langflow.db
/tmp/*
src/backend/langflow/frontend/
.docker
.docker
.idea

View file

@ -217,4 +217,40 @@ Vertex AI is a cloud computing platform offered by Google Cloud Platform (GCP).
- **top_k:** How the model selects tokens for output, the next token is selected from – defaults to `40`.
- **top_p:** Tokens are selected from most probable to least until the sum of their – defaults to `0.95`.
- **tuned_model_name:** The name of a tuned model. If provided, model_name is ignored.
- **verbose:** This parameter is used to control the level of detail in the output of the chain. When set to True, it will print out some internal states of the chain while it is being run, which can help debug and understand the chain's behavior. If set to False, it will suppress the verbose output – defaults to `False`.
- **verbose:** This parameter is used to control the level of detail in the output of the chain. When set to True, it will print out some internal states of the chain while it is being run, which can help debug and understand the chain's behavior. If set to False, it will suppress the verbose output – defaults to `False`.
---
### QianfanLLMEndpoint
Wrapper around [Baidu Qianfan](https://cloud.baidu.com/doc/WENXINWORKSHOP/index.html) large language models.
:::info
The Qianfan Big Model Platform is a one-stop platform for enterprise developers to develop and operate large models and services. It provides data management based on ERNIE Bot's underlying model (Ernie Bot), automatic model customization and fine-tuning, and one-stop large-scale model customization services for cloud deployment of prediction services, and provides ERNIE Bot's enterprise level service API that can be quickly called, helping to implement the demand for generative AI applications in various industries.
:::
- **Model Name:** Model name. you could get from https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Nlks5zkzu preset models are mapping to an endpoint. `Model Name` will be ignored if `Endpoint` is set.
- **Qianfan Ak:** which you could get from https://cloud.baidu.com/product/wenxinworkshop.
- **Qianfan Sk:** which you could get from https://cloud.baidu.com/product/wenxinworkshop.
- **Top p:** Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo. The diversity of the output text is affected, and the larger the value, the stronger the diversity of the generated text - defaults to `0.8`.
- **Temperature:** Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo. Higher values make the output more random, while lower values make it more concentrated and deterministic - defaults to `0.95`.
- **Penalty Score:** Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo. By increasing the penalty for generated tokens, the phenomenon of duplicate generation is reduced. A higher value indicates a higher penalty - defaults to `1.0`.
- **Endpoint:** Endpoint of the Qianfan LLM, required if custom model used.
---
### QianfanChatEndpoint
Wrapper around [Baidu Qianfan](https://cloud.baidu.com/doc/WENXINWORKSHOP/index.html) chat large language models. This component supports some of the LLMs (Large Language Models) available by Baidu qianfan and is used for tasks such as chatbots, Generative Question-Answering (GQA), and summarization.
:::info
The Qianfan Big Model Platform is a one-stop platform for enterprise developers to develop and operate large models and services. It provides data management based on ERNIE Bot's underlying model (Ernie Bot), automatic model customization and fine-tuning, and one-stop large-scale model customization services for cloud deployment of prediction services, and provides ERNIE Bot's enterprise level service API that can be quickly called, helping to implement the demand for generative AI applications in various industries.
:::
- **Model Name:** Model name. you could get from https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Nlks5zkzu preset models are mapping to an endpoint. `Model Name` will be ignored if `Endpoint` is set.
- **Qianfan Ak:** which you could get from https://cloud.baidu.com/product/wenxinworkshop.
- **Qianfan Sk:** which you could get from https://cloud.baidu.com/product/wenxinworkshop.
- **Top p:** Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo. The diversity of the output text is affected, and the larger the value, the stronger the diversity of the generated text - defaults to `0.8`.
- **Temperature:** Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo. Higher values make the output more random, while lower values make it more concentrated and deterministic - defaults to `0.95`.
- **Penalty Score:** Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo. By increasing the penalty for generated tokens, the phenomenon of duplicate generation is reduced. A higher value indicates a higher penalty - defaults to `1.0`.
- **Endpoint:** Endpoint of the Qianfan LLM, required if custom model used.

1559
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@ google-search-results = "^2.4.1"
google-api-python-client = "^2.79.0"
typer = "^0.9.0"
gunicorn = "^21.2.0"
langchain = "^0.0.308"
langchain = "^0.0.312"
openai = "^0.27.8"
pandas = "2.0.3"
chromadb = "^0.3.21"
@ -91,6 +91,7 @@ pillow = "^10.0.0"
metal-sdk = "^2.2.0"
markupsafe = "^2.1.3"
numexpr = "^2.8.6"
qianfan = "0.0.5"
[tool.poetry.group.dev.dependencies]

View file

@ -0,0 +1,92 @@
from typing import Optional
from langflow import CustomComponent
from langchain.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint
from langchain.llms.base import BaseLLM
class QianfanChatEndpointComponent(CustomComponent):
display_name: str = "QianfanChatEndpoint"
description: str = (
"Baidu Qianfan chat models. Get more detail from "
"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint."
)
def build_config(self):
return {
"model": {
"display_name": "Model Name",
"options": [
"ERNIE-Bot",
"ERNIE-Bot-turbo",
"BLOOMZ-7B",
"Llama-2-7b-chat",
"Llama-2-13b-chat",
"Llama-2-70b-chat",
"Qianfan-BLOOMZ-7B-compressed",
"Qianfan-Chinese-Llama-2-7B",
"ChatGLM2-6B-32K",
"AquilaChat-7B",
],
"info": "https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint",
"required": True,
},
"qianfan_ak": {
"display_name": "Qianfan Ak",
"required": True,
"password": True,
"info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop",
},
"qianfan_sk": {
"display_name": "Qianfan Sk",
"required": True,
"password": True,
"info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop",
},
"top_p": {
"display_name": "Top p",
"field_type": "float",
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
"value": 0.8,
},
"temperature": {
"display_name": "Temperature",
"field_type": "float",
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
"value": 0.95,
},
"penalty_score": {
"display_name": "Penalty Score",
"field_type": "float",
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
"value": 1.0,
},
"endpoint": {
"display_name": "Endpoint",
"info": "Endpoint of the Qianfan LLM, required if custom model used.",
},
"code": {"show": False},
}
def build(
self,
model: str = "ERNIE-Bot-turbo",
qianfan_ak: Optional[str] = None,
qianfan_sk: Optional[str] = None,
top_p: Optional[float] = None,
temperature: Optional[float] = None,
penalty_score: Optional[float] = None,
endpoint: Optional[str] = None,
) -> BaseLLM:
try:
output = QianfanChatEndpoint( # type: ignore
model=model,
qianfan_ak=qianfan_ak,
qianfan_sk=qianfan_sk,
top_p=top_p,
temperature=temperature,
penalty_score=penalty_score,
endpoint=endpoint,
)
except Exception as e:
raise ValueError("Could not connect to Baidu Qianfan API.") from e
return output # type: ignore

View file

@ -0,0 +1,92 @@
from typing import Optional
from langflow import CustomComponent
from langchain.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint
from langchain.llms.base import BaseLLM
class QianfanLLMEndpointComponent(CustomComponent):
display_name: str = "QianfanLLMEndpoint"
description: str = (
"Baidu Qianfan hosted open source or customized models. "
"Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint"
)
def build_config(self):
return {
"model": {
"display_name": "Model Name",
"options": [
"ERNIE-Bot",
"ERNIE-Bot-turbo",
"BLOOMZ-7B",
"Llama-2-7b-chat",
"Llama-2-13b-chat",
"Llama-2-70b-chat",
"Qianfan-BLOOMZ-7B-compressed",
"Qianfan-Chinese-Llama-2-7B",
"ChatGLM2-6B-32K",
"AquilaChat-7B",
],
"info": "https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint",
"required": True,
},
"qianfan_ak": {
"display_name": "Qianfan Ak",
"required": True,
"password": True,
"info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop",
},
"qianfan_sk": {
"display_name": "Qianfan Sk",
"required": True,
"password": True,
"info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop",
},
"top_p": {
"display_name": "Top p",
"field_type": "float",
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
"value": 0.8,
},
"temperature": {
"display_name": "Temperature",
"field_type": "float",
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
"value": 0.95,
},
"penalty_score": {
"display_name": "Penalty Score",
"field_type": "float",
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
"value": 1.0,
},
"endpoint": {
"display_name": "Endpoint",
"info": "Endpoint of the Qianfan LLM, required if custom model used.",
},
"code": {"show": False},
}
def build(
self,
model: str = "ERNIE-Bot-turbo",
qianfan_ak: Optional[str] = None,
qianfan_sk: Optional[str] = None,
top_p: Optional[float] = None,
temperature: Optional[float] = None,
penalty_score: Optional[float] = None,
endpoint: Optional[str] = None,
) -> BaseLLM:
try:
output = QianfanLLMEndpoint( # type: ignore
model=model,
qianfan_ak=qianfan_ak,
qianfan_sk=qianfan_sk,
top_p=top_p,
temperature=temperature,
penalty_score=penalty_score,
endpoint=endpoint,
)
except Exception as e:
raise ValueError("Could not connect to Baidu Qianfan API.") from e
return output # type: ignore

View file

@ -5,7 +5,6 @@ from langchain.vectorstores import Vectara
from langchain.schema import Document
from langchain.vectorstores.base import VectorStore
from langchain.schema import BaseRetriever
from langchain.embeddings.base import Embeddings
class VectaraComponent(CustomComponent):
@ -22,7 +21,6 @@ class VectaraComponent(CustomComponent):
"vectara_api_key": {"display_name": "Vectara API Key", "password": True},
"code": {"show": False},
"documents": {"display_name": "Documents"},
"embedding": {"display_name": "Embedding"},
}
def build(
@ -30,21 +28,21 @@ class VectaraComponent(CustomComponent):
vectara_customer_id: str,
vectara_corpus_id: str,
vectara_api_key: str,
embedding: Optional[Embeddings] = None,
documents: Optional[Document] = None,
) -> Union[VectorStore, BaseRetriever]:
# If documents, then we need to create a Vectara instance using .from_documents
if documents is not None and embedding is not None:
if documents is not None:
return Vectara.from_documents(
documents=documents, # type: ignore
vectara_customer_id=vectara_customer_id,
vectara_corpus_id=vectara_corpus_id,
vectara_api_key=vectara_api_key,
embedding=embedding,
source="langflow",
)
return Vectara(
vectara_customer_id=vectara_customer_id,
vectara_corpus_id=vectara_corpus_id,
vectara_api_key=vectara_api_key,
source="langflow",
)

View file

@ -44,7 +44,7 @@ class FieldFormatters(BaseModel):
class FrontendNode(BaseModel):
template: Template
description: str
description: Optional[str] = None
base_classes: List[str]
name: str = ""
display_name: str = ""

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,9 @@ terminate_process_by_port() {
# Trap signals to ensure cleanup on script termination
trap 'terminate_process_by_port 7860; terminate_process_by_port 3000' EXIT
# install playwright if there is not installed yet
npx playwright install
# Navigate to the project root directory (where the Makefile is located)
cd ../../
@ -56,7 +59,7 @@ cd ../../
make backend &
# Give some time for the backend to start (adjust sleep duration as needed)
sleep 10
sleep 25
# Navigate back to the test directory
cd src/frontend

View file

@ -56,6 +56,7 @@ export default function ParameterComponent({
info = "",
proxy,
showNode,
index = "",
}: ParameterComponentType): JSX.Element {
const ref = useRef<HTMLDivElement>(null);
const refHtml = useRef<HTMLDivElement & ReactNode>(null);
@ -351,9 +352,11 @@ export default function ParameterComponent({
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
id={"textarea-" + index}
/>
) : (
<InputComponent
id={"input-" + index}
disabled={disabled}
password={data.node?.template[name].password ?? false}
value={data.node?.template[name].value ?? ""}
@ -364,6 +367,7 @@ export default function ParameterComponent({
) : left === true && type === "bool" ? (
<div className="mt-2 w-full">
<ToggleShadComponent
id={"toggle-" + index}
disabled={disabled}
enabled={data.node?.template[name].value ?? false}
setEnabled={(isEnabled) => {
@ -406,6 +410,7 @@ export default function ParameterComponent({
disabled={disabled}
value={data.node?.template[name].value ?? ""}
onChange={handleOnNewValue}
id={"code-input-" + index}
/>
</div>
) : left === true && type === "file" ? (
@ -427,6 +432,7 @@ export default function ParameterComponent({
disabled={disabled}
value={data.node?.template[name].value ?? ""}
onChange={handleOnNewValue}
id={"int-input-" + index}
/>
</div>
) : left === true && type === "prompt" ? (
@ -450,6 +456,7 @@ export default function ParameterComponent({
onChange={(e) => {
handleOnNewValue(e);
}}
id={"prompt-input-" + index}
/>
</div>
) : left === true && type === "NestedDict" ? (

View file

@ -219,6 +219,7 @@ export default function GenericNode({
data.node!.template[templateField].show &&
!data.node!.template[templateField].advanced && (
<ParameterComponent
index={idx.toString()}
key={scapedJSONStringfy({
inputTypes:
data.node!.template[templateField].input_types,
@ -421,11 +422,13 @@ export default function GenericNode({
<>
{Object.keys(data.node!.template)
.filter((templateField) => templateField.charAt(0) !== "_")
.sort()
.map((templateField: string, idx) => (
<div key={idx}>
{data.node!.template[templateField].show &&
!data.node!.template[templateField].advanced ? (
<ParameterComponent
index={idx.toString()}
key={scapedJSONStringfy({
inputTypes:
data.node!.template[templateField].input_types,

View file

@ -12,6 +12,7 @@ export default function CodeAreaComponent({
nodeClass,
dynamic,
setNodeClass,
id = "",
readonly = false,
}: CodeAreaComponentType) {
const [myValue, setMyValue] = useState(
@ -43,6 +44,7 @@ export default function CodeAreaComponent({
>
<div className="flex w-full items-center">
<span
id={id}
className={
editNode
? "input-edit-node input-dialog"

View file

@ -22,7 +22,6 @@ export default function DictComponent({
}, [value]);
const ref = useRef(value);
debugger;
return (
<div
className={classNames(

View file

@ -17,6 +17,7 @@ export default function InputComponent({
editNode = false,
placeholder = "Type something...",
className,
id = "",
blurOnEnter = false,
}: InputComponentType): JSX.Element {
const [pwdVisible, setPwdVisible] = useState(false);
@ -33,6 +34,7 @@ export default function InputComponent({
{isForm ? (
<Form.Control asChild>
<Input
id={"form-" + id}
ref={refInput}
onBlur={onBlur}
autoFocus={autoFocus}
@ -61,6 +63,7 @@ export default function InputComponent({
</Form.Control>
) : (
<Input
id={id}
ref={refInput}
type="text"
onBlur={onBlur}

View file

@ -8,6 +8,7 @@ export default function IntComponent({
onChange,
disabled,
editNode = false,
id = "",
}: FloatComponentType): JSX.Element {
const min = 0;
@ -21,6 +22,7 @@ export default function IntComponent({
return (
<div className="w-full">
<Input
id={id}
onKeyDown={(event) => {
if (
event.key !== "Backspace" &&

View file

@ -14,6 +14,7 @@ export default function PromptAreaComponent({
onChange,
disabled,
editNode = false,
id = "",
readonly = false,
}: PromptAreaComponentType): JSX.Element {
useEffect(() => {
@ -36,6 +37,7 @@ export default function PromptAreaComponent({
return (
<div className={disabled ? "pointer-events-none w-full " : " w-full"}>
<GenericModal
id={id}
readonly={readonly}
type={TypeModal.PROMPT}
value={value}
@ -49,6 +51,7 @@ export default function PromptAreaComponent({
>
<div className="flex w-full items-center">
<span
id={id}
className={
editNode
? "input-edit-node input-dialog"

View file

@ -10,6 +10,7 @@ export default function TextAreaComponent({
onChange,
disabled,
editNode = false,
id = "",
}: TextAreaComponentType): JSX.Element {
// Clear text area
useEffect(() => {
@ -21,6 +22,7 @@ export default function TextAreaComponent({
return (
<div className="flex w-full items-center">
<Input
id={id}
value={value}
disabled={disabled}
className={editNode ? "input-edit-node" : ""}

View file

@ -220,6 +220,7 @@ const EditNodeModal = forwardRef(
templateParam
].multiline ? (
<TextAreaComponent
id={"textarea-edit-" + index}
disabled={disabled}
editNode={true}
value={
@ -233,6 +234,7 @@ const EditNodeModal = forwardRef(
/>
) : (
<InputComponent
id={"input-" + index}
editNode={true}
disabled={disabled}
password={
@ -328,6 +330,7 @@ const EditNodeModal = forwardRef(
<div className="ml-auto">
{" "}
<ToggleShadComponent
id={"toggle-edit-" + index}
disabled={disabled}
enabled={
myData.current.node.template[
@ -386,6 +389,7 @@ const EditNodeModal = forwardRef(
.type === "int" ? (
<div className="mx-auto">
<IntComponent
id={"int-input-" + index}
disabled={disabled}
editNode={true}
value={
@ -456,6 +460,7 @@ const EditNodeModal = forwardRef(
onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam);
}}
id={"prompt-area-edit" + index}
/>
</div>
) : myData.current.node?.template[templateParam]
@ -488,6 +493,7 @@ const EditNodeModal = forwardRef(
onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam);
}}
id={"code-area-edit" + index}
/>
</div>
) : myData.current.node?.template[templateParam]

View file

@ -8,6 +8,7 @@ import { useContext, useEffect, useState } from "react";
import AceEditor from "react-ace";
import IconComponent from "../../components/genericIconComponent";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext";
import { darkContext } from "../../contexts/darkContext";
@ -144,6 +145,11 @@ export default function CodeAreaModal({
/>
</BaseModal.Header>
<BaseModal.Content>
<Input
value={code}
className="absolute left-[500%] top-[500%]"
id="codeValue"
/>
<div className="flex h-full w-full flex-col transition-all">
<div className="h-full w-full">
<AceEditor
@ -183,10 +189,11 @@ export default function CodeAreaModal({
</div>
<div className="flex h-fit w-full justify-end">
<Button
disabled={readonly}
className="mt-3"
onClick={handleClick}
type="submit"
id="checkAndSaveBtn"
disabled={readonly}
>
Check & Save
</Button>

View file

@ -30,6 +30,7 @@ export default function GenericModal({
nodeClass,
setNodeClass,
children,
id = "",
readonly = false,
}: genericModalPropsType): JSX.Element {
const [myButtonText] = useState(buttonText);
@ -211,6 +212,7 @@ export default function GenericModal({
>
{type === TypeModal.PROMPT && isEdit && !readonly ? (
<Textarea
id={"modal-" + id}
ref={divRefPrompt}
className="form-input h-full w-full rounded-lg custom-scroll focus-visible:ring-1"
value={inputValue}
@ -286,7 +288,7 @@ export default function GenericModal({
className="m-1 max-w-[40vw] cursor-default truncate p-2.5 text-sm"
>
<div className="relative bottom-[1px]">
<span>
<span id={"badge" + index.toString()}>
{word.replace(/[{}]/g, "").length > 59
? word.replace(/[{}]/g, "").slice(0, 56) +
"..."
@ -306,6 +308,7 @@ export default function GenericModal({
)}
</div>
<Button
id="genericModalBtnSave"
disabled={readonly}
onClick={() => {
switch (myModalType) {

View file

@ -19,6 +19,7 @@ export type InputComponentType = {
showPass?: boolean;
placeholder?: string;
className?: string;
id?: string;
blurOnEnter?: boolean;
};
export type ToggleComponentType = {
@ -52,6 +53,7 @@ export type ParameterComponentType = {
info?: string;
proxy?: { field: string; id: string };
showNode?: boolean;
index?: string;
};
export type InputListComponentType = {
value: string[];
@ -85,6 +87,7 @@ export type TextAreaComponentType = {
onChange: (value: string[] | string) => void;
value: string;
editNode?: boolean;
id?: string;
readonly?: boolean;
};
@ -97,6 +100,7 @@ export type PromptAreaComponentType = {
value: string;
readonly?: boolean;
editNode?: boolean;
id?: string;
};
export type CodeAreaComponentType = {
@ -107,6 +111,7 @@ export type CodeAreaComponentType = {
nodeClass?: APIClassType;
setNodeClass?: (value: APIClassType) => void;
dynamic?: boolean;
id?: string;
readonly?: boolean;
};
@ -138,6 +143,7 @@ export type FloatComponentType = {
disabled?: boolean;
onChange: (value: string) => void;
editNode?: boolean;
id?: string;
};
export type TooltipComponentType = {
@ -495,6 +501,7 @@ export type genericModalPropsType = {
nodeClass?: APIClassType;
setNodeClass?: (Class: APIClassType) => void;
children: ReactNode;
id?: string;
readonly?: boolean;
};

View file

@ -0,0 +1,140 @@
import { expect, test } from "@playwright/test";
test("CodeAreaModalComponent", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(2000);
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("pythonfunctiontool");
await page.waitForTimeout(2000);
await page
.locator('//*[@id="sidePythonFunctionTool"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.locator('//*[@id="code-input-0"]').click();
let value = await page.locator('//*[@id="codeValue"]').inputValue();
if (
value !=
'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text'
) {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div')
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showdescription"]').click();
expect(
await page.locator('//*[@id="showdescription"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showname"]').click();
expect(await page.locator('//*[@id="showname"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showreturn_direct"]').click();
expect(
await page.locator('//*[@id="showreturn_direct"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showdescription"]').click();
expect(
await page.locator('//*[@id="showdescription"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showname"]').click();
expect(await page.locator('//*[@id="showname"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showreturn_direct"]').click();
expect(
await page.locator('//*[@id="showreturn_direct"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showdescription"]').click();
expect(
await page.locator('//*[@id="showdescription"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showname"]').click();
expect(await page.locator('//*[@id="showname"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showreturn_direct"]').click();
expect(
await page.locator('//*[@id="showreturn_direct"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showdescription"]').click();
expect(
await page.locator('//*[@id="showdescription"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showname"]').click();
expect(await page.locator('//*[@id="showname"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showreturn_direct"]').click();
expect(
await page.locator('//*[@id="showreturn_direct"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="code-input-0"]');
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div')
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="code-area-edit0"]').click();
let value = await page.locator('//*[@id="codeValue"]').inputValue();
if (
value !=
'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text'
) {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.locator('//*[@id="code-input-0"]').click();
}
});

View file

@ -1,153 +1,5 @@
import { expect, test } from "@playwright/test";
test("KeypairListComponent", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(2000);
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("csv");
await page.waitForTimeout(2000);
await page
.locator('//*[@id="sideCSVLoader"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.locator('//*[@id="keypair0"]').click();
await page.locator('//*[@id="keypair0"]').fill("testtesttesttest");
await page.locator('//*[@id="keypair100"]').click();
await page.locator('//*[@id="keypair100"]').fill("testtesttesttesttesttest");
const plusButtonLocatorNode = page.locator('//*[@id="plusbtn0"]');
const elementCountNode = await plusButtonLocatorNode.count();
if (elementCountNode > 0) {
await plusButtonLocatorNode.click();
}
await page.locator('//*[@id="keypair1"]').click();
await page.locator('//*[@id="keypair1"]').fill("testtesttesttest1");
await page.locator('//*[@id="keypair101"]').click();
await page.locator('//*[@id="keypair101"]').fill("testtesttesttesttesttest1");
await page.locator('//*[@id="plusbtn1"]').click();
await page.locator('//*[@id="keypair2"]').click();
await page.locator('//*[@id="keypair2"]').fill("testtesttesttest2");
await page.locator('//*[@id="keypair102"]').click();
await page.locator('//*[@id="keypair102"]').fill("testtesttesttesttesttest2");
await page.locator('//*[@id="minusbtn1"]').click();
const keyPairVerification = page.locator('//*[@id="keypair102"]');
const elementKeyCount = await keyPairVerification.count();
if (elementKeyCount === 0) {
expect(true).toBeTruthy();
} else {
expect(false).toBeTruthy();
}
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div/div/div[1]/div/div[1]/div'
)
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showfile_path"]').click();
expect(
await page.locator('//*[@id="showfile_path"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showmetadata"]').click();
expect(await page.locator('//*[@id="showmetadata"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="plusbtn0"]');
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div/div/div[1]/div/div[1]/div'
)
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showfile_path"]').click();
expect(
await page.locator('//*[@id="showfile_path"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showmetadata"]').click();
expect(
await page.locator('//*[@id="showmetadata"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="keypair0"]').click();
await page.locator('//*[@id="keypair0"]').fill("testtesttesttest");
await page.locator('//*[@id="keypair100"]').click();
await page
.locator('//*[@id="keypair100"]')
.fill("testtesttesttesttesttest");
const plusButtonLocator = page.locator('//*[@id="plusbtn0"]');
const elementCount = await plusButtonLocator.count();
if (elementCount > 0) {
await plusButtonLocator.click();
}
await page.locator('//*[@id="keypair1"]').click();
await page.locator('//*[@id="keypair1"]').fill("testtesttesttest1");
await page.locator('//*[@id="keypair101"]').click();
await page
.locator('//*[@id="keypair101"]')
.fill("testtesttesttesttesttest1");
await page.locator('//*[@id="plusbtn1"]').click();
await page.locator('//*[@id="keypair2"]').click();
await page.locator('//*[@id="keypair2"]').fill("testtesttesttest2");
await page.locator('//*[@id="keypair102"]').click();
await page
.locator('//*[@id="keypair102"]')
.fill("testtesttesttesttesttest2");
await page.locator('//*[@id="minusbtn1"]').click();
const keyPairVerification = page.locator('//*[@id="keypair102"]');
const elementKeyCount = await keyPairVerification.count();
if (elementKeyCount === 0) {
await page.locator('//*[@id="saveChangesBtn"]').click();
const key1 = await page.locator('//*[@id="keypair0"]').inputValue();
const value1 = await page.locator('//*[@id="keypair100"]').inputValue();
const key2 = await page.locator('//*[@id="keypair1"]').inputValue();
const value2 = await page.locator('//*[@id="keypair101"]').inputValue();
if (
key1 === "testtesttesttest" &&
value1 === "testtesttesttesttesttest" &&
key2 === "testtesttesttest2" &&
value2 === "testtesttesttesttesttest2"
) {
expect(true).toBeTruthy();
} else {
expect(false).toBeTruthy();
}
} else {
expect(false).toBeTruthy();
}
} else {
expect(false).toBeTruthy();
}
});
test("FloatComponent", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.waitForTimeout(2000);

View file

@ -0,0 +1,118 @@
import { expect, test } from "@playwright/test";
test("IntComponent", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(2000);
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("getrequest");
await page.waitForTimeout(2000);
await page
.locator('//*[@id="sideGET Request"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.locator('//*[@id="int-input-2"]').click();
await page
.locator('//*[@id="int-input-2"]')
.fill("123456789123456789123456789");
let value = await page.locator('//*[@id="int-input-2"]').inputValue();
if (value != "123456789123456789123456789") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="int-input-2"]').click();
await page.locator('//*[@id="int-input-2"]').fill("-3");
value = await page.locator('//*[@id="int-input-2"]').inputValue();
if (value != "0") {
expect(false).toBeTruthy();
}
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div')
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
value = await page.locator('//*[@id="int-input-1"]').inputValue();
if (value != "0") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="int-input-1"]').click();
await page
.locator('//*[@id="int-input-1"]')
.fill("123456789123456789123456789");
await page.locator('//*[@id="showheaders"]').click();
expect(await page.locator('//*[@id="showheaders"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showtimeout"]').click();
expect(await page.locator('//*[@id="showtimeout"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showurl"]').click();
expect(await page.locator('//*[@id="showurl"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showheaders"]').click();
expect(await page.locator('//*[@id="showheaders"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showurl"]').click();
expect(await page.locator('//*[@id="showurl"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="int-input-2"]');
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div')
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showtimeout"]').click();
expect(
await page.locator('//*[@id="showtimeout"]').isChecked()
).toBeTruthy();
const valueEditNode = await page
.locator('//*[@id="int-input-1"]')
.inputValue();
if (valueEditNode != "123456789123456789123456789") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.locator('//*[@id="int-input-2"]').click();
await page.locator('//*[@id="int-input-2"]').fill("3");
let value = await page.locator('//*[@id="int-input-2"]').inputValue();
if (value != "3") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="int-input-2"]').click();
await page.locator('//*[@id="int-input-2"]').fill("-3");
value = await page.locator('//*[@id="int-input-2"]').inputValue();
if (value != "0") {
expect(false).toBeTruthy();
}
}
});

View file

@ -0,0 +1,149 @@
import { expect, test } from "@playwright/test";
test("KeypairListComponent", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(2000);
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("csv");
await page.waitForTimeout(2000);
await page
.locator('//*[@id="sideCSVLoader"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.locator('//*[@id="keypair0"]').click();
await page.locator('//*[@id="keypair0"]').fill("testtesttesttest");
await page.locator('//*[@id="keypair100"]').click();
await page.locator('//*[@id="keypair100"]').fill("testtesttesttesttesttest");
const plusButtonLocatorNode = page.locator('//*[@id="plusbtn0"]');
const elementCountNode = await plusButtonLocatorNode.count();
if (elementCountNode > 0) {
await plusButtonLocatorNode.click();
}
await page.locator('//*[@id="keypair1"]').click();
await page.locator('//*[@id="keypair1"]').fill("testtesttesttest1");
await page.locator('//*[@id="keypair101"]').click();
await page.locator('//*[@id="keypair101"]').fill("testtesttesttesttesttest1");
await page.locator('//*[@id="plusbtn1"]').click();
await page.locator('//*[@id="keypair2"]').click();
await page.locator('//*[@id="keypair2"]').fill("testtesttesttest2");
await page.locator('//*[@id="keypair102"]').click();
await page.locator('//*[@id="keypair102"]').fill("testtesttesttesttesttest2");
await page.locator('//*[@id="minusbtn1"]').click();
const keyPairVerification = page.locator('//*[@id="keypair102"]');
const elementKeyCount = await keyPairVerification.count();
if (elementKeyCount === 0) {
expect(true).toBeTruthy();
} else {
expect(false).toBeTruthy();
}
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div/div/div[1]/div/div[1]/div'
)
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showfile_path"]').click();
expect(
await page.locator('//*[@id="showfile_path"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showmetadata"]').click();
expect(await page.locator('//*[@id="showmetadata"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="plusbtn0"]');
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div/div/div[1]/div/div[1]/div'
)
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showfile_path"]').click();
expect(
await page.locator('//*[@id="showfile_path"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showmetadata"]').click();
expect(
await page.locator('//*[@id="showmetadata"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="keypair0"]').click();
await page.locator('//*[@id="keypair0"]').fill("testtesttesttest");
await page.locator('//*[@id="keypair100"]').click();
await page
.locator('//*[@id="keypair100"]')
.fill("testtesttesttesttesttest");
const plusButtonLocator = page.locator('//*[@id="plusbtn0"]');
const elementCount = await plusButtonLocator.count();
if (elementCount > 0) {
await plusButtonLocator.click();
}
await page.locator('//*[@id="keypair1"]').click();
await page.locator('//*[@id="keypair1"]').fill("testtesttesttest1");
await page.locator('//*[@id="keypair101"]').click();
await page
.locator('//*[@id="keypair101"]')
.fill("testtesttesttesttesttest1");
await page.locator('//*[@id="plusbtn1"]').click();
await page.locator('//*[@id="keypair2"]').click();
await page.locator('//*[@id="keypair2"]').fill("testtesttesttest2");
await page.locator('//*[@id="keypair102"]').click();
await page
.locator('//*[@id="keypair102"]')
.fill("testtesttesttesttesttest2");
await page.locator('//*[@id="minusbtn1"]').click();
const keyPairVerification = page.locator('//*[@id="keypair102"]');
const elementKeyCount = await keyPairVerification.count();
if (elementKeyCount === 0) {
await page.locator('//*[@id="saveChangesBtn"]').click();
const key1 = await page.locator('//*[@id="keypair0"]').inputValue();
const value1 = await page.locator('//*[@id="keypair100"]').inputValue();
const key2 = await page.locator('//*[@id="keypair1"]').inputValue();
const value2 = await page.locator('//*[@id="keypair101"]').inputValue();
if (
key1 === "testtesttesttest" &&
value1 === "testtesttesttesttesttest" &&
key2 === "testtesttesttest2" &&
value2 === "testtesttesttesttesttest2"
) {
expect(true).toBeTruthy();
} else {
expect(false).toBeTruthy();
}
} else {
expect(false).toBeTruthy();
}
} else {
expect(false).toBeTruthy();
}
});

View file

@ -0,0 +1,174 @@
import { expect, test } from "@playwright/test";
test("PromptTemplateComponent", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(2000);
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("promptTemplate");
await page.waitForTimeout(2000);
await page
.locator('//*[@id="sidePromptTemplate"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.locator('//*[@id="prompt-input-4"]').click();
await page
.locator('//*[@id="modal-prompt-input-4"]')
.fill("{prompt} example {prompt1}");
let value = await page
.locator('//*[@id="modal-prompt-input-4"]')
.inputValue();
if (value != "{prompt} example {prompt1}") {
expect(false).toBeTruthy();
}
let valueBadgeOne = await page.locator('//*[@id="badge0"]').innerText();
if (valueBadgeOne != "prompt") {
expect(false).toBeTruthy();
}
let valueBadgeTwo = await page.locator('//*[@id="badge1"]').innerText();
if (valueBadgeTwo != "prompt1") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="genericModalBtnSave"]').click();
await page.locator('//*[@id="textarea-7"]').click();
await page.locator('//*[@id="textarea-7"]').fill("prompt_value_!@#!@#");
value = await page.locator('//*[@id="textarea-7"]').inputValue();
if (value != "prompt_value_!@#!@#") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="textarea-8"]').click();
await page
.locator('//*[@id="textarea-8"]')
.fill("prompt_name_test_123123!@#!@#");
value = await page.locator('//*[@id="textarea-8"]').inputValue();
if (value != "prompt_name_test_123123!@#!@#") {
expect(false).toBeTruthy();
}
value = await page.locator('//*[@id="prompt-input-4"]').innerText();
if (value != "{prompt} example {prompt1}") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="editAdvancedIcon"]').click();
value = await page.locator('//*[@id="textarea-edit-1"]').inputValue();
if (value != "prompt_value_!@#!@#") {
expect(false).toBeTruthy();
}
value = await page.locator('//*[@id="textarea-edit-2"]').inputValue();
if (value != "prompt_name_test_123123!@#!@#") {
expect(false).toBeTruthy();
}
value = await page.locator('//*[@id="prompt-area-edit0"]').innerText();
if (value != "{prompt} example {prompt1}") {
expect(false).toBeTruthy();
}
await page
.locator('//*[@id="textarea-edit-2"]')
.fill("prompt_edit_test_12312312321!@#$");
await page
.locator('//*[@id="textarea-edit-1"]')
.fill("prompt_edit_test_44444444444!@#$");
await page.locator('//*[@id="showtemplate"]').click();
expect(await page.locator('//*[@id="showtemplate"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showprompt"]').click();
expect(await page.locator('//*[@id="showprompt"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showprompt1"]').click();
expect(await page.locator('//*[@id="showprompt1"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showtemplate"]').click();
expect(
await page.locator('//*[@id="showtemplate"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showprompt"]').click();
expect(await page.locator('//*[@id="showprompt"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showprompt1"]').click();
expect(await page.locator('//*[@id="showprompt1"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showtemplate"]').click();
expect(await page.locator('//*[@id="showtemplate"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showprompt"]').click();
expect(await page.locator('//*[@id="showprompt"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showprompt1"]').click();
expect(await page.locator('//*[@id="showprompt1"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showtemplate"]').click();
expect(
await page.locator('//*[@id="showtemplate"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showprompt"]').click();
expect(await page.locator('//*[@id="showprompt"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="textarea-8"]');
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div/div/div[1]/div/div[1]'
)
.click();
await page.locator('//*[@id="editAdvancedIcon"]').click();
await page.locator('//*[@id="showprompt1"]').click();
expect(
await page.locator('//*[@id="showprompt1"]').isChecked()
).toBeTruthy();
value = await page.locator('//*[@id="textarea-edit-1"]').inputValue();
if (value != "prompt_edit_test_44444444444!@#$") {
expect(false).toBeTruthy();
}
value = await page.locator('//*[@id="textarea-edit-2"]').inputValue();
if (value != "prompt_edit_test_12312312321!@#$") {
expect(false).toBeTruthy();
}
value = await page.locator('//*[@id="prompt-area-edit0"]').innerText();
if (value != "{prompt} example {prompt1}") {
expect(false).toBeTruthy();
}
}
});

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,419 @@
{
"description": "Use this Tool on every query",
"name": "Getting Started: Simple python function applied to each output",
"data": {
"nodes": [
{
"width": 384,
"height": 631,
"id": "ChatOpenAI-tRw3A",
"type": "genericNode",
"position": {
"x": 543.1816229116944,
"y": 942.891611351432
},
"data": {
"type": "ChatOpenAI",
"node": {
"template": {
"lc_kwargs": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "lc_kwargs",
"advanced": true,
"type": "code",
"list": false
},
"verbose": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": false,
"password": false,
"name": "verbose",
"advanced": false,
"type": "bool",
"list": false
},
"callbacks": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "callbacks",
"advanced": false,
"type": "langchain.callbacks.base.BaseCallbackHandler",
"list": true
},
"client": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "client",
"advanced": false,
"type": "Any",
"list": false
},
"model_name": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "gpt-3.5-turbo",
"password": false,
"options": [
"gpt-3.5-turbo-0613",
"gpt-3.5-turbo",
"gpt-3.5-turbo-16k-0613",
"gpt-3.5-turbo-16k",
"gpt-4-0613",
"gpt-4-32k-0613",
"gpt-4",
"gpt-4-32k"
],
"name": "model_name",
"advanced": false,
"type": "str",
"list": true
},
"temperature": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "0.2",
"password": false,
"name": "temperature",
"advanced": false,
"type": "float",
"list": false
},
"model_kwargs": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "model_kwargs",
"advanced": true,
"type": "code",
"list": false
},
"openai_api_key": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "",
"password": true,
"name": "openai_api_key",
"display_name": "OpenAI API Key",
"advanced": false,
"type": "str",
"list": false
},
"openai_api_base": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "openai_api_base",
"display_name": "OpenAI API Base",
"advanced": false,
"type": "str",
"list": false
},
"openai_organization": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "openai_organization",
"display_name": "OpenAI Organization",
"advanced": false,
"type": "str",
"list": false
},
"openai_proxy": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "openai_proxy",
"display_name": "OpenAI Proxy",
"advanced": false,
"type": "str",
"list": false
},
"request_timeout": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "request_timeout",
"advanced": false,
"type": "float",
"list": false
},
"max_retries": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 6,
"password": false,
"name": "max_retries",
"advanced": false,
"type": "int",
"list": false
},
"streaming": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": false,
"password": false,
"name": "streaming",
"advanced": false,
"type": "bool",
"list": false
},
"n": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 1,
"password": false,
"name": "n",
"advanced": false,
"type": "int",
"list": false
},
"max_tokens": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": true,
"name": "max_tokens",
"advanced": false,
"type": "int",
"list": false
},
"_type": "ChatOpenAI"
},
"description": "Wrapper around OpenAI Chat large language models.",
"base_classes": [
"Serializable",
"BaseChatModel",
"ChatOpenAI",
"BaseLanguageModel"
],
"display_name": "ChatOpenAI"
},
"id": "ChatOpenAI-tRw3A",
"value": null
},
"selected": false,
"dragging": false,
"positionAbsolute": {
"x": 543.1816229116944,
"y": 942.891611351432
}
},
{
"width": 384,
"height": 387,
"id": "AgentInitializer-KcVTt",
"type": "genericNode",
"position": {
"x": 1036.6064439140812,
"y": 645.1919693466587
},
"data": {
"type": "AgentInitializer",
"node": {
"template": {
"agent": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"value": "zero-shot-react-description",
"password": false,
"options": [
"zero-shot-react-description",
"react-docstore",
"self-ask-with-search",
"conversational-react-description",
"openai-functions"
],
"name": "agent",
"advanced": false,
"type": "str",
"list": true
},
"memory": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "memory",
"advanced": false,
"type": "BaseChatMemory",
"list": false
},
"tools": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "tools",
"advanced": false,
"type": "Tool",
"list": true
},
"llm": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "llm",
"display_name": "LLM",
"advanced": false,
"type": "BaseLanguageModel",
"list": false
},
"_type": "initialize_agent"
},
"description": "Construct a zero shot agent from an LLM and tools.",
"base_classes": ["AgentExecutor", "function"],
"display_name": "AgentInitializer"
},
"id": "AgentInitializer-KcVTt",
"value": null
},
"selected": false,
"positionAbsolute": {
"x": 1036.6064439140812,
"y": 645.1919693466587
}
},
{
"width": 384,
"height": 437,
"id": "PythonFunctionTool-FwZVF",
"type": "genericNode",
"position": {
"x": 553.050119331742,
"y": 412.9533535948685
},
"data": {
"type": "PythonFunctionTool",
"node": {
"template": {
"name": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"value": "PythonFunction",
"password": false,
"name": "name",
"advanced": false,
"type": "str",
"list": false
},
"description": {
"required": true,
"placeholder": "",
"show": true,
"multiline": true,
"value": "Returns the Text you send. This is a testing tool.",
"password": false,
"name": "description",
"advanced": false,
"type": "str",
"list": false
},
"code": {
"required": true,
"placeholder": "",
"show": true,
"multiline": true,
"value": "\ndef python_function(text: str) -> str:\n \"\"\"This is a default python function that returns the input text\"\"\"\n return text\n",
"password": false,
"name": "code",
"advanced": false,
"type": "code",
"list": false
},
"_type": "PythonFunctionTool"
},
"description": "Python function to be executed.",
"base_classes": ["Tool"],
"display_name": "PythonFunctionTool"
},
"id": "PythonFunctionTool-FwZVF",
"value": null
},
"selected": false,
"dragging": false,
"positionAbsolute": {
"x": 553.050119331742,
"y": 412.9533535948685
}
}
],
"edges": [
{
"source": "ChatOpenAI-tRw3A",
"sourceHandle": "ChatOpenAI|ChatOpenAI-tRw3A|Serializable|BaseChatModel|ChatOpenAI|BaseLanguageModel",
"target": "AgentInitializer-KcVTt",
"targetHandle": "BaseLanguageModel|llm|AgentInitializer-KcVTt",
"style": {
"stroke": "inherit"
},
"className": "stroke-gray-900 dark:stroke-gray-200",
"animated": false,
"id": "reactflow__edge-ChatOpenAI-tRw3AChatOpenAI|ChatOpenAI-tRw3A|Serializable|BaseChatModel|ChatOpenAI|BaseLanguageModel-AgentInitializer-KcVTtBaseLanguageModel|llm|AgentInitializer-KcVTt",
"selected": false
},
{
"source": "PythonFunctionTool-FwZVF",
"sourceHandle": "PythonFunctionTool|PythonFunctionTool-FwZVF|Tool",
"target": "AgentInitializer-KcVTt",
"targetHandle": "Tool|tools|AgentInitializer-KcVTt",
"style": {
"stroke": "inherit"
},
"className": "stroke-gray-900 dark:stroke-gray-200",
"animated": false,
"id": "reactflow__edge-PythonFunctionTool-FwZVFPythonFunctionTool|PythonFunctionTool-FwZVF|Tool-AgentInitializer-KcVTtTool|tools|AgentInitializer-KcVTt",
"selected": false
}
],
"viewport": {
"x": 4.748095479939138,
"y": -155.65184647754464,
"zoom": 0.6079953565987085
}
},
"id": "15030b3c-570d-4658-8473-58138077e9b0"
}

View file

@ -0,0 +1,87 @@
import { expect, test } from "@playwright/test";
import { readFileSync } from "fs";
test.describe("drag and drop test", () => {
/// <reference lib="dom"/>
test("drop collection", async ({ page }) => {
await page.routeFromHAR("harFiles/langflow.har", {
url: "**/api/v1/**",
update: false,
});
await page.route("**/api/v1/flows/", async (route) => {
const json = {
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
};
await route.fulfill({ json, status: 201 });
});
await page.goto("http:localhost:3000/");
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
// Read your file into a buffer.
const jsonContent = readFileSync(
"tests/onlyFront/assets/collection.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], "collection.json", {
type: "application/json",
});
dt.items.add(file);
return dt;
}, jsonContent);
// Now dispatch
await page.dispatchEvent('//*[@id="root"]/div/div[2]/div[2]', "drop", {
dataTransfer,
});
expect(
await page
.locator(".main-page-flows-display")
.evaluate((el) => el.children)
).toBeTruthy();
});
test("drop flow", async ({ page }) => {
await page.routeFromHAR("harFiles/langflow.har", {
url: "**/api/v1/**",
update: false,
});
await page.route("**/api/v1/flows/", async (route) => {
const json = {
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
};
await route.fulfill({ json, status: 201 });
});
await page.goto("http:localhost:3000/");
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
// Read your file into a buffer.
const jsonContent = readFileSync(
"tests/onlyFront/assets/flow.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.json", {
type: "application/json",
});
dt.items.add(file);
return dt;
}, jsonContent);
// Now dispatch
await page.dispatchEvent('//*[@id="root"]/div/div[2]/div[2]', "drop", {
dataTransfer,
});
expect(
await page
.locator(".main-page-flows-display")
.evaluate((el) => el.children)
).toBeTruthy();
});
});

View file

@ -1,14 +1,49 @@
import { expect, test } from "@playwright/test";
import { readFileSync } from "fs";
test.describe("Group component tests", () => {
test("group test", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.getByRole("button", { name: "Community Examples" }).click();
await page
.locator(
"div:nth-child(7) > div:nth-child(2) > .card-component-footer-arrangement > .inline-flex"
)
.click();
test.describe("group node test", () => {
/// <reference lib="dom"/>
test("group and ungroup updating values", async ({ page }) => {
await page.routeFromHAR("harFiles/langflow.har", {
url: "**/api/v1/**",
update: false,
});
await page.route("**/api/v1/flows/", async (route) => {
const json = {
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
};
await route.fulfill({ json, status: 201 });
});
await page.goto("http:localhost:3000/");
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
// Read your file into a buffer.
const jsonContent = readFileSync(
"tests/onlyFront/assets/flow.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.json", {
type: "application/json",
});
dt.items.add(file);
return dt;
}, jsonContent);
// Now dispatch
await page.dispatchEvent('//*[@id="root"]/div/div[2]/div[2]', "drop", {
dataTransfer,
});
expect(
await page
.locator(".main-page-flows-display")
.evaluate((el) => el.children)
).toBeTruthy();
await page.getByRole("button", { name: "Edit Flow" }).click();
//inside the flow
await page
.locator(
"//html/body/div/div/div[2]/div/main/div/div/div/div[1]/div[1]/div[1]/div/div[2]/div[1]/div/div[1]/div"
@ -84,16 +119,11 @@ test.describe("Group component tests", () => {
)
.click();
await page.getByLabel("Ungroup").click();
await expect(
page.locator(
"//html/body/div/div/div[2]/div/main/div/div/div/div[1]/div[1]/div/div/div[2]/div[3]/div/div[2]/div[4]/div/div[2]/div/input"
)
).toHaveValue("fieldValue");
await expect(page.locator('//*[@id="input-2"]')).toHaveValue("fieldValue");
expect(
await page
.locator(
"//html/body/div/div/div[2]/div/main/div/div/div/div[1]/div[1]/div/div/div[2]/div[2]/div/div[2]/div[5]/div/div[2]/div/button/span[1]"
)
.getByTestId(/.*rf__node-AgentInitializer.*/)
.getByRole("button", { name: "openai-functions" })
.textContent()
).toBe("openai-functions");
});

View file

@ -0,0 +1,172 @@
import { expect, test } from "@playwright/test";
test("InputComponent", async ({ page }) => {
await page.routeFromHAR("harFiles/langflow.har", {
url: "**/api/v1/**",
update: false,
});
await page.route("**/api/v1/flows/", async (route) => {
const json = {
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
};
await route.fulfill({ json, status: 201 });
});
await page.goto("http://localhost:3000/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(2000);
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("Chroma");
await page.waitForTimeout(2000);
await page
.locator('//*[@id="sideChroma"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.locator("#input-8").click();
await page
.locator("#input-8")
.fill("collection_name_test_123123123!@#$&*(&%$@");
let value = await page.locator("#input-8").inputValue();
if (value != "collection_name_test_123123123!@#$&*(&%$@") {
expect(false).toBeTruthy();
}
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div/div/div[1]/div/div[1]/div'
)
.click();
await page.locator('//*[@id="editAdvancedIcon"]').click();
await page.locator('//*[@id="showchroma_server_cors_allow_origins"]').click();
expect(
await page
.locator('//*[@id="showchroma_server_cors_allow_origins"]')
.isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_grpc_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_host"]').click();
expect(
await page.locator('//*[@id="showchroma_server_host"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_http_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
expect(
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showcollection_name"]').click();
expect(
await page.locator('//*[@id="showcollection_name"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showpersist"]').click();
expect(await page.locator('//*[@id="showpersist"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showpersist_directory"]').click();
expect(
await page.locator('//*[@id="showpersist_directory"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showsearch_kwargs"]').click();
expect(
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_cors_allow_origins"]').click();
expect(
await page
.locator('//*[@id="showchroma_server_cors_allow_origins"]')
.isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_grpc_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_host"]').click();
expect(
await page.locator('//*[@id="showchroma_server_host"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_http_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
expect(
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showpersist"]').click();
expect(await page.locator('//*[@id="showpersist"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showpersist_directory"]').click();
expect(
await page.locator('//*[@id="showpersist_directory"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showsearch_kwargs"]').click();
expect(
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
).toBeFalsy();
let valueEditNode = await page.locator('//*[@id="input-5"]').inputValue();
if (valueEditNode != "collection_name_test_123123123!@#$&*(&%$@") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="input-5"]').click();
await page
.locator('//*[@id="input-5"]')
.fill("NEW_collection_name_test_123123123!@#$&*(&%$@");
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator("#input-8");
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div/div/div[1]/div/div[1]/div'
)
.click();
await page.locator('//*[@id="editAdvancedIcon"]').click();
await page.locator('//*[@id="showcollection_name"]').click();
expect(
await page.locator('//*[@id="showcollection_name"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="saveChangesBtn"]').click();
let value = await page.locator("#input-8").inputValue();
if (value != "NEW_collection_name_test_123123123!@#$&*(&%$@") {
expect(false).toBeTruthy();
}
}
});

View file

@ -0,0 +1,176 @@
import { expect, test } from "@playwright/test";
test("ToggleComponent", async ({ page }) => {
await page.routeFromHAR("harFiles/langflow.har", {
url: "**/api/v1/**",
update: false,
});
await page.route("**/api/v1/flows/", async (route) => {
const json = {
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
};
await route.fulfill({ json, status: 201 });
});
await page.goto("http://localhost:3000/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(2000);
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("directoryLoader");
await page.waitForTimeout(2000);
await page
.locator('//*[@id="sideDirectoryLoader"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[1]/div'
)
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showload_hidden"]').click();
expect(
await page.locator('//*[@id="showload_hidden"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[1]/div'
)
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
expect(
await page.locator('//*[@id="toggle-edit-1"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showglob"]').click();
expect(await page.locator('//*[@id="showglob"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showload_hidden"]').click();
expect(
await page.locator('//*[@id="showload_hidden"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showmax_concurrency"]').click();
expect(
await page.locator('//*[@id="showmax_concurrency"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showmetadata"]').click();
expect(await page.locator('//*[@id="showmetadata"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showpath"]').click();
expect(await page.locator('//*[@id="showpath"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showrecursive"]').click();
expect(
await page.locator('//*[@id="showrecursive"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showsilent_errors"]').click();
expect(
await page.locator('//*[@id="showsilent_errors"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showuse_multithreading"]').click();
expect(
await page.locator('//*[@id="showuse_multithreading"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showglob"]').click();
expect(await page.locator('//*[@id="showglob"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showmax_concurrency"]').click();
expect(
await page.locator('//*[@id="showmax_concurrency"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showmetadata"]').click();
expect(
await page.locator('//*[@id="showmetadata"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showpath"]').click();
expect(await page.locator('//*[@id="showpath"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showrecursive"]').click();
expect(
await page.locator('//*[@id="showrecursive"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showsilent_errors"]').click();
expect(
await page.locator('//*[@id="showsilent_errors"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showuse_multithreading"]').click();
expect(
await page.locator('//*[@id="showuse_multithreading"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="toggle-1"]');
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div')
.click();
await page.locator('//*[@id="advancedIcon"]').click();
await page.locator('//*[@id="editAdvancedBtn"]').click();
await page.locator('//*[@id="showload_hidden"]').click();
expect(
await page.locator('//*[@id="showload_hidden"]').isChecked()
).toBeTruthy();
expect(
await page.locator('//*[@id="toggle-edit-1"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
}
});

View file

@ -1,5 +0,0 @@
import { test } from "@playwright/test";
test("test", async ({ page }) => {
// Recording...
});