Merge branch 'zustand/io/migration' into state_theories

This commit is contained in:
Gabriel Luiz Freitas Almeida 2024-03-02 00:48:40 -03:00
commit dc8ad28418
79 changed files with 1598 additions and 1613 deletions

View file

@ -24,3 +24,7 @@ yarn-error.log*
/test-results/
/playwright-report/*/
/playwright/.cache/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -48,6 +48,7 @@
"lodash": "^4.17.21",
"lucide-react": "^0.331.0",
"moment": "^2.29.4",
"playwright": "^1.42.0",
"react": "^18.2.0",
"react-ace": "^10.1.0",
"react-cookie": "^4.1.1",
@ -77,7 +78,7 @@
"zustand": "^4.4.7"
},
"devDependencies": {
"@playwright/test": "^1.41.2",
"@playwright/test": "^1.42.0",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.80",
"@tailwindcss/typography": "^0.5.9",
@ -1492,12 +1493,12 @@
}
},
"node_modules/@playwright/test": {
"version": "1.41.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz",
"integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==",
"version": "1.42.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.0.tgz",
"integrity": "sha512-2k1HzC28Fs+HiwbJOQDUwrWMttqSLUVdjCqitBOjdCD0svWOMQUVqrXX6iFD7POps6xXAojsX/dGBpKnjZctLA==",
"dev": true,
"dependencies": {
"playwright": "1.41.2"
"playwright": "1.42.0"
},
"bin": {
"playwright": "cli.js"
@ -8719,12 +8720,11 @@
}
},
"node_modules/playwright": {
"version": "1.41.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz",
"integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==",
"dev": true,
"version": "1.42.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0.tgz",
"integrity": "sha512-Ko7YRUgj5xBHbntrgt4EIw/nE//XBHOKVKnBjO1KuZkmkhlbgyggTe5s9hjqQ1LpN+Xg+kHsQyt5Pa0Bw5XpvQ==",
"dependencies": {
"playwright-core": "1.41.2"
"playwright-core": "1.42.0"
},
"bin": {
"playwright": "cli.js"
@ -8737,10 +8737,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.41.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz",
"integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==",
"dev": true,
"version": "1.42.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0.tgz",
"integrity": "sha512-0HD9y8qEVlcbsAjdpBaFjmaTHf+1FeIddy8VJLeiqwhcNqGCBe4Wp2e8knpqiYbzxtxarxiXyNDw2cG8sCaNMQ==",
"bin": {
"playwright-core": "cli.js"
},

View file

@ -43,6 +43,7 @@
"lodash": "^4.17.21",
"lucide-react": "^0.331.0",
"moment": "^2.29.4",
"playwright": "^1.42.0",
"react": "^18.2.0",
"react-ace": "^10.1.0",
"react-cookie": "^4.1.1",
@ -99,7 +100,7 @@
},
"proxy": "http://127.0.0.1:7860",
"devDependencies": {
"@playwright/test": "^1.41.2",
"@playwright/test": "^1.42.0",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.80",
"@tailwindcss/typography": "^0.5.9",

View file

@ -10,9 +10,6 @@
<li>
<a href="./e2e/index.html">e2e report</a>
</li>
<li>
<a href="./onlyFront/index.html">frontEnd Only report</a>
</li>
</ul>
</body>
</html>

View file

@ -27,8 +27,16 @@ terminate_process_by_port() {
echo "Process terminated."
}
delete_temp() {
cd ../../
echo "Deleting temp database"
rm temp
echo "Temp database deleted."
}
# Trap signals to ensure cleanup on script termination
trap 'terminate_process_by_port 7860; terminate_process_by_port 3000' EXIT
trap 'terminate_process_by_port 7860; terminate_process_by_port 3000; delete_temp' EXIT
# install playwright if there is not installed yet
npx playwright install
@ -42,26 +50,16 @@ make frontend &
# Give some time for the frontend to start (adjust sleep duration as needed)
sleep 10
# Navigate to the test directory
cd src/frontend
# Run frontend only Playwright tests with or without UI based on the --ui flag
if [ "$ui" = true ]; then
PLAYWRIGHT_HTML_REPORT=playwright-report/onlyFront npx playwright test tests/onlyFront --ui --project=chromium
else
PLAYWRIGHT_HTML_REPORT=playwright-report/onlyFront npx playwright test tests/onlyFront --project=chromium
fi
# Navigate back to the project root directory
cd ../../
#install backend
poetry install --extras deploy
# Start the backend using 'make backend' in the background
make backend &
LANGFLOW_DATABASE_URL=sqlite:///./temp LANGFLOW_AUTO_LOGIN=True poetry run langflow run --backend-only --port 7860 --host 0.0.0.0 --no-open-browser &
# Give some time for the backend to start (adjust sleep duration as needed)
sleep 25
# Navigate back to the test directory
# Navigate to the test directory
cd src/frontend
# Run Playwright tests with or without UI based on the --ui flag

View file

@ -212,7 +212,7 @@ export default function ParameterComponent({
{item.display_name === "" ? "" : " - "}
{item.display_name.split(", ").length > 2
? item.display_name.split(", ").map((el, index) => (
<React.Fragment key={el + index}>
<React.Fragment key={el + name}>
<span>
{index ===
item.display_name.split(", ").length - 1
@ -229,7 +229,7 @@ export default function ParameterComponent({
{item.type === "" ? "" : " - "}
{item.type.split(", ").length > 2
? item.type.split(", ").map((el, index) => (
<React.Fragment key={el + index}>
<React.Fragment key={el + name}>
<span>
{index === item.type.split(", ").length - 1
? el
@ -409,7 +409,7 @@ export default function ParameterComponent({
<div className="mt-2 flex w-full items-center">
<div className="w-5/6 flex-grow">
<InputComponent
id={"input-" + index}
id={"input-" + name}
disabled={disabled}
password={data.node?.template[name].password ?? false}
value={data.node?.template[name].value ?? ""}
@ -432,11 +432,12 @@ export default function ParameterComponent({
) : left === true && type === "bool" ? (
<div className="mt-2 w-full">
<ToggleShadComponent
id={"toggle-" + index}
id={"toggle-" + name}
disabled={disabled}
enabled={data.node?.template[name].value ?? false}
setEnabled={handleOnNewValue}
size="large"
editNode={false}
/>
</div>
) : left === true && type === "float" ? (
@ -458,7 +459,7 @@ export default function ParameterComponent({
options={data.node.template[name].options}
onSelect={handleOnNewValue}
value={data.node.template[name].value ?? "Choose an option"}
id={"dropdown-" + index}
id={"dropdown-" + name}
/>
</div>
{data.node?.template[name].refresh && (
@ -486,7 +487,7 @@ export default function ParameterComponent({
disabled={disabled}
value={data.node?.template[name].value ?? ""}
onChange={handleOnNewValue}
id={"code-input-" + index}
id={"code-input-" + name}
/>
</div>
) : left === true && type === "file" ? (
@ -507,7 +508,7 @@ export default function ParameterComponent({
disabled={disabled}
value={data.node?.template[name].value ?? ""}
onChange={handleOnNewValue}
id={"int-input-" + index}
id={"int-input-" + name}
/>
</div>
) : left === true && type === "prompt" ? (
@ -520,8 +521,8 @@ export default function ParameterComponent({
disabled={disabled}
value={data.node?.template[name].value ?? ""}
onChange={handleOnNewValue}
id={"prompt-input-" + index}
data-testid={"prompt-input-" + index}
id={"prompt-input-" + name}
data-testid={"prompt-input-" + name}
/>
</div>
) : left === true && type === "NestedDict" ? (

View file

@ -49,8 +49,10 @@ export default function AccordionComponent({
>
{trigger}
</AccordionTrigger>
<AccordionContent className="AccordionContent flex flex-col">
{children}
<AccordionContent>
<div className="AccordionContent flex flex-col">
{children}
</div>
</AccordionContent>
</AccordionItem>
</Accordion>

View file

@ -17,7 +17,7 @@ export default function IOOutputView({
case "TextOutput":
return (
<Textarea
className="w-full custom-scroll"
className="w-full h-full custom-scroll"
placeholder={"Empty"}
// update to real value on flowPool
value={
@ -31,7 +31,7 @@ export default function IOOutputView({
default:
return (
<Textarea
className="w-full custom-scroll"
className="w-full h-full custom-scroll"
placeholder={"Enter text..."}
value={node.data.node!.template["input_value"]}
onChange={(e) => {

View file

@ -12,6 +12,7 @@ import { cn } from "../../utils/utils";
import AccordionComponent from "../AccordionComponent";
import IOInputField from "../IOInputField";
import IOOutputView from "../IOOutputView";
import ShadTooltip from "../ShadTooltipComponent";
import IconComponent from "../genericIconComponent";
import NewChatView from "../newChatView";
import { Badge } from "../ui/badge";
@ -213,9 +214,16 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
<AccordionComponent
trigger={
<div className="file-component-badge-div">
<Badge variant="gray" size="md">
{output.id}
</Badge>
<ShadTooltip
content={output.id}
styleClasses="z-50"
>
<div>
<Badge variant="gray" size="md">
{output.displayName}
</Badge>
</div>
</ShadTooltip>
{haveChat && (
<div
className="-mb-1 pr-4"
@ -272,7 +280,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
</button>
{selectedViewField.type}
</div>
<div className="h-full">
<div className="h-full w-full">
{inputs.some(
(input) => input.id === selectedViewField.id
) ? (
@ -308,28 +316,30 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
<div className="absolute bottom-8 right-8"></div>
)}
</div>
{!haveChat && (
<div className="flex w-full justify-end pt-6">
<Button
variant={"outline"}
className="flex gap-2 px-3"
onClick={() => sendMessage(1)}
>
<IconComponent
name={isBuilding ? "Loader2" : "Play"}
className={cn(
"h-4 w-4",
isBuilding
? "animate-spin"
: "fill-current text-medium-indigo"
)}
/>
Run Flow
</Button>
</div>
)}
</div>
</BaseModal.Content>
<BaseModal.Footer>
{!haveChat && (
<div className="flex w-full justify-end pt-6">
<Button
variant={"outline"}
className="flex gap-2 px-3"
onClick={() => sendMessage(1)}
>
<IconComponent
name={isBuilding ? "Loader2" : "Play"}
className={cn(
"h-4 w-4",
isBuilding
? "animate-spin"
: "fill-current text-medium-indigo"
)}
/>
Run Flow
</Button>
</div>
)}
</BaseModal.Footer>
</BaseModal>
);
}

View file

@ -126,7 +126,7 @@ export default function CodeTabsComponent({
<Tabs
value={activeTab}
className={
"api-modal-tabs " +
"api-modal-tabs m-0 inset-0 " +
(isMessage ? "dark " : "") +
(dark && isMessage ? "bg-background" : "")
}
@ -166,7 +166,7 @@ export default function CodeTabsComponent({
) : (
<IconComponent name="Clipboard" className="h-4 w-4" />
)}
{isCopied ? "Copied!" : "Copy code"}
{isCopied ? "Copied!" : "Copy Code"}
</button>
<button
className="flex items-center gap-1.5 rounded bg-none p-1 text-xs text-gray-500 dark:text-gray-300"

View file

@ -91,6 +91,7 @@ export default function InputComponent({
handleKeyDown(e, value, "");
if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
}}
data-testid={editNode ? id + "-edit" : id}
/>
)}
{password && (

View file

@ -45,6 +45,7 @@ export default function IntComponent({
onChange={(event) => {
onChange(event.target.value);
}}
data-testid={id}
/>
</div>
);

View file

@ -50,7 +50,7 @@ export function CodeBlock({ language, value }: Props): JSX.Element {
<div className="flex items-center">
<button className="code-block-modal-button" onClick={copyToClipboard}>
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
{isCopied ? "Copied!" : "Copy code"}
{isCopied ? "Copied!" : "Copy Code"}
</button>
<button className="code-block-modal-button" onClick={downloadAsFile}>
<IconDownload size={18} />

View file

@ -7,6 +7,7 @@ export default function ToggleShadComponent({
disabled,
size,
id = "",
editNode = false,
}: ToggleComponentType): JSX.Element {
let scaleX, scaleY;
switch (size) {
@ -31,6 +32,7 @@ export default function ToggleShadComponent({
<div className={disabled ? "pointer-events-none cursor-not-allowed " : ""}>
<Switch
id={id}
data-testid={id}
style={{
transform: `scaleX(${scaleX}) scaleY(${scaleY})`,
}}

View file

@ -25,10 +25,18 @@ export const INVALID_CHARACTERS = [
/**
* regex to highlight the variables in the text
* @constant
* @constant regexHighlight
* @type {RegExp}
* @default
* @example
* {{variable}} or {variable}
* @returns {RegExp}
* @description
* This regex is used to highlight the variables in the text.
* It matches the variables in the text that are between {{}} or {}.
*/
export const regexHighlight = /\{([^}]+)\}/g;
export const regexHighlight = /\{\{(.*?)\}\}|\{([^{}]+)\}/g;
export const specialCharsRegex = /[!@#$%^&*()\-_=+[\]{}|;:'",.<>/?\\`´]/;
export const programmingLanguages: languageMap = {
@ -708,8 +716,8 @@ export const chatInputPlaceholder =
export const chatInputPlaceholderSend = "Send a message...";
export const editCodeTitle = "Edit Code";
export const myCollectionDesc =
"Manage your personal projects. Download or upload your collection.";
export const storeDesc = "Search flows and components from the community.";
"Manage your personal projects. Download and upload entire collections.";
export const storeDesc = "Explore community-shared flows and components.";
export const storeTitle = "Langflow Store";
export const noApi = "You don't have an API key. ";
export const insertApi = "Insert your Langflow API key.";

View file

@ -89,6 +89,7 @@ function ConfirmationModal({
setModalOpen(false);
onConfirm(index, data);
}}
data-testid="replace-button"
>
{confirmationText}
</Button>

View file

@ -35,9 +35,9 @@ export default function DeleteConfirmationModal({
</DialogTitle>
</DialogHeader>
<span>
Are you sure you want to delete this {description ?? "component"}?
Confirm deletion of {description ?? "component"}?
<br></br>
This action cannot be undone.
Note: This action is irreversible.
</span>
<DialogFooter>
<DialogClose>

View file

@ -242,7 +242,11 @@ const EditNodeModal = forwardRef(
/>
) : (
<InputComponent
id={"input-" + index}
id={
"input-" +
myData.node.template[templateParam]
.name
}
editNode={true}
disabled={disabled}
password={
@ -338,7 +342,10 @@ const EditNodeModal = forwardRef(
<div className="ml-auto">
{" "}
<ToggleShadComponent
id={"toggle-edit-" + index}
id={
"toggle-edit-" +
myData.node.template[templateParam].name
}
disabled={disabled}
enabled={
myData.node.template[templateParam]
@ -351,6 +358,7 @@ const EditNodeModal = forwardRef(
);
}}
size="small"
editNode={true}
/>
</div>
) : myData.node?.template[templateParam]
@ -391,14 +399,20 @@ const EditNodeModal = forwardRef(
myData.node.template[templateParam]
.value ?? "Choose an option"
}
id={"dropdown-edit-" + index}
id={
"dropdown-edit-" +
myData.node.template[templateParam].name
}
></Dropdown>
</div>
) : myData.node?.template[templateParam]
.type === "int" ? (
<div className="mx-auto">
<IntComponent
id={"edit-int-input-" + index}
id={
"edit-int-input-" +
myData.node.template[templateParam].name
}
disabled={disabled}
editNode={true}
value={
@ -493,7 +507,10 @@ const EditNodeModal = forwardRef(
onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam);
}}
id={"code-area-edit" + index}
id={
"code-area-edit" +
myData.node.template[templateParam].name
}
/>
</div>
) : myData.node?.template[templateParam]
@ -519,6 +536,7 @@ const EditNodeModal = forwardRef(
}}
disabled={disabled}
size="small"
editNode={true}
/>
</div>
</TableCell>

View file

@ -50,7 +50,7 @@ export function CodeBlock({ language, value }: Props): JSX.Element {
<div className="flex items-center">
<button className="code-block-modal-button" onClick={copyToClipboard}>
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
{isCopied ? "Copied!" : "Copy code"}
{isCopied ? "Copied!" : "Copy Code"}
</button>
<button className="code-block-modal-button" onClick={downloadAsFile}>
<IconDownload size={18} />

View file

@ -97,13 +97,23 @@ export default function GenericModal({
useEffect(() => {
setInputValue(value);
}, [value, modalOpen]);
const coloredContent = (inputValue || "")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(regexHighlight, varHighlightHTML({ name: "$1" }))
.replace(/\n/g, "<br />");
.replace(regexHighlight, (match, p1, p2) => {
// Decide which group was matched. If p1 is not undefined, do nothing
// we don't want to change the text. If p2 is not undefined, then we
// have a variable, so we should highlight it.
// ! This will not work with multiline or indented json yet
if (p1 !== undefined) {
return match;
} else if (p2 !== undefined) {
return varHighlightHTML({ name: p2 });
}
return match;
})
.replace(/\n/g, "<br />");
function getClassByNumberLength(): string {
let sumOfCaracteres: number = 0;
wordsHighlight.forEach((element) => {
@ -159,7 +169,7 @@ export default function GenericModal({
setIsEdit(true);
return setErrorData({
title: PROMPT_ERROR_ALERT,
list: [error.toString()],
list: [error.response.data.detail ?? ""],
});
});
}

View file

@ -48,7 +48,7 @@ export default function ShareModal({
const setErrorData = useAlertStore((state) => state.setErrorData);
const [internalOpen, internalSetOpen] = useState(children ? false : true);
const [openConfirmationModal, setOpenConfirmationModal] = useState(false);
const nameComponent = is_component ? "component" : "flow";
const nameComponent = is_component ? "component" : "workflow";
const [tags, setTags] = useState<{ id: string; name: string }[]>([]);
const [loadingTags, setLoadingTags] = useState<boolean>(false);
@ -179,7 +179,7 @@ export default function ShareModal({
</span>
<br></br>
<span className=" text-xs text-destructive ">
Warning: This action cannot be undone.
Note: This action is irreversible.
</span>
</ConfirmationModal.Content>
</ConfirmationModal>
@ -204,7 +204,7 @@ export default function ShareModal({
{children ? children : <></>}
</BaseModal.Trigger>
<BaseModal.Header
description={`Share your ${nameComponent} to the Langflow Store.`}
description={`Publish ${is_component ? "your component" : "workflow"} to the Langflow Store.`}
>
<span className="pr-2">Share</span>
<IconComponent
@ -235,12 +235,11 @@ export default function ShareModal({
}}
/>
<label htmlFor="public" className="export-modal-save-api text-sm ">
Make {nameComponent} public
Set {nameComponent} status to public
</label>
</div>
<span className=" text-xs text-destructive ">
<b>Warning:</b> API keys in designated fields are removed when
sharing.
<b>Attention:</b> API keys in specified fields are automatically removed upon sharing.
</span>
</BaseModal.Content>

View file

@ -386,7 +386,7 @@ export default function NodeToolbarComponent({
value={"Share"}
disabled={!hasApiKey || !validApiKey}
>
<div className="flex" data-testid="save-button-modal">
<div className="flex" data-testid="share-button-modal">
<IconComponent
name="Share3"
className="relative top-0.5 -m-1 mr-1 h-6 w-6"

View file

@ -223,10 +223,12 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
selection.nodes.some((node) => node.data.type === "ChatInput") &&
checkChatInput(get().nodes)
) {
useAlertStore.getState().setErrorData({
title: "Error pasting components",
list: ["You can only have one ChatInput component in the flow"],
});
useAlertStore
.getState()
.setErrorData({
title: "Error pasting components",
list: ["You can only have one ChatInput component in the flow"],
});
return;
}
let minimumX = Infinity;
@ -500,7 +502,6 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
updateVerticesBuild: (
vertices: {
verticesIds: string[];
verticesOrder: string[][];
verticesLayers: string[][];
runId: string;
} | null

View file

@ -27,6 +27,7 @@ export type ToggleComponentType = {
disabled: boolean | undefined;
size: "small" | "medium" | "large";
id?: string;
editNode?: boolean;
};
export type DropDownComponentType = {
value: string;

View file

@ -41,8 +41,8 @@ export type FlowPoolType = {
export type FlowStoreType = {
flowPool: FlowPoolType;
inputs: Array<{ type: string; id: string }>;
outputs: Array<{ type: string; id: string }>;
inputs: Array<{ type: string; id: string; displayName: string }>;
outputs: Array<{ type: string; id: string; displayName: string }>;
hasIO: boolean;
setFlowPool: (flowPool: FlowPoolType) => void;
addDataToFlowPool: (data: FlowPoolObjectType, nodeId: string) => void;
@ -101,7 +101,6 @@ export type FlowStoreType = {
vertices: {
verticesIds: string[];
verticesLayers: string[][];
verticesOrder: string[][];
runId: string;
} | null
) => void;
@ -110,7 +109,6 @@ export type FlowStoreType = {
verticesBuild: {
verticesIds: string[];
verticesLayers: string[][];
verticesOrder: string[][];
runId: string;
} | null;
updateBuildStatus: (nodeId: string[], status: BuildStatus) => void;

View file

@ -46,7 +46,6 @@ export async function updateVerticesOrder(
): Promise<{
verticesLayers: string[][];
verticesIds: string[];
verticesOrder: string[][];
runId: string;
}> {
return new Promise(async (resolve, reject) => {
@ -64,9 +63,8 @@ export async function updateVerticesOrder(
throw new Error("Invalid nodes");
}
let verticesOrder: Array<Array<string>> = orderResponse.data.ids;
const runId = orderResponse.data.run_id;
let verticesLayers: Array<Array<string>> = [];
const runId = orderResponse.data.run_id;
if (nodeId) {
for (let i = 0; i < verticesOrder.length; i += 1) {
const innerArray = verticesOrder[i];
@ -84,15 +82,13 @@ export async function updateVerticesOrder(
} else {
verticesLayers = verticesOrder;
}
const verticesIds = verticesLayers.flat();
const verticesIds = verticesOrder.flat();
useFlowStore.getState().updateVerticesBuild({
verticesLayers,
verticesIds,
verticesOrder,
runId,
});
resolve({ verticesLayers, verticesIds, verticesOrder, runId });
resolve({ verticesLayers, verticesIds, runId });
});
}
@ -108,12 +104,13 @@ export async function buildVertices({
validateNodes,
}: BuildVerticesParams) {
let verticesBuild = useFlowStore.getState().verticesBuild;
if (!verticesBuild || nodeId) {
verticesBuild = await updateVerticesOrder(flowId, nodeId);
}
let verticesIds = verticesBuild?.verticesIds!;
const verticesIds = verticesBuild?.verticesIds!;
const verticesLayers = verticesBuild?.verticesLayers!;
const verticesOrder = verticesBuild?.verticesOrder!;
const runId = verticesBuild?.runId!;
let stop = false;
@ -121,7 +118,7 @@ export async function buildVertices({
if (validateNodes) {
try {
validateNodes(verticesOrder.flatMap((id) => id));
validateNodes(verticesIds);
} catch (e) {
return;
}
@ -242,6 +239,7 @@ async function buildVertex({
}) {
try {
const buildRes = await postBuildVertex(flowId, id, input_value);
const buildData: VertexBuildTypeAPI = buildRes.data;
if (onBuildUpdate) {
if (!buildData.valid) {

View file

@ -25,15 +25,23 @@ export function getTagsIds(
}
export function getInputsAndOutputs(nodes: Node[]) {
let inputs: { type: string; id: string }[] = [];
let outputs: { type: string; id: string }[] = [];
let inputs: { type: string; id: string; displayName: string }[] = [];
let outputs: { type: string; id: string; displayName: string }[] = [];
nodes.forEach((node) => {
const nodeData: NodeDataType = node.data as NodeDataType;
if (isOutputNode(nodeData)) {
outputs.push({ type: nodeData.type, id: nodeData.id });
outputs.push({
type: nodeData.type,
id: nodeData.id,
displayName: nodeData.node?.display_name ?? nodeData.id,
});
}
if (isInputNode(nodeData)) {
inputs.push({ type: nodeData.type, id: nodeData.id });
inputs.push({
type: nodeData.type,
id: nodeData.id,
displayName: nodeData.node?.display_name ?? nodeData.id,
});
}
});
return { inputs, outputs };

File diff suppressed because one or more lines are too long

View file

@ -2,19 +2,11 @@ import { test } from "@playwright/test";
test.describe("Auto_login tests", () => {
test("auto_login sign in", async ({ page }) => {
await page.routeFromHAR("harFiles/langflow.har", {
url: "**/api/v1/**",
update: false,
});
await page.goto("http:localhost:3000/");
await page.locator('//*[@id="new-project-btn"]').click();
});
test("auto_login block_admin", async ({ page }) => {
await page.routeFromHAR("harFiles/langflow.har", {
url: "**/api/v1/**",
update: false,
});
await page.goto("http:localhost:3000/");
await page.locator('//*[@id="new-project-btn"]').click();
await page.goto("http:localhost:3000/login");

View file

@ -117,7 +117,7 @@ test("CodeAreaModalComponent", async ({ page }) => {
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="code-area-edit0"]').click();
await page.locator('//*[@id="code-area-editcode"]').click();
let value = await page.locator('//*[@id="codeValue"]').inputValue();
@ -132,6 +132,7 @@ test("CodeAreaModalComponent", async ({ page }) => {
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.locator('//*[@id="code-input-0"]').click();
await page.getByTestId("div-generic-node").click();
await page.getByTestId("code-button-modal").click();
}
});

View file

@ -4,21 +4,11 @@ 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",
"tests/end-to-end/assets/collection.json",
"utf-8"
);
@ -42,9 +32,7 @@ test.describe("drag and drop test", () => {
}
);
await page
.getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0")
.click();
await page.getByText("Edit Flow").first().click();
await page.waitForTimeout(2000);
const genericNoda = page.getByTestId("div-generic-node");

View file

@ -1,17 +1,6 @@
import { expect, test } from "@playwright/test";
test("dropDownComponent", async ({ page }) => {
await page.routeFromHAR("harFiles/backend_12112023.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);
@ -24,24 +13,24 @@ test("dropDownComponent", async ({ page }) => {
await page.waitForTimeout(2000);
await page
.getByTestId("llmsAmazon Bedrock")
.getByTestId("model_specsAmazon Bedrock")
.first()
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.getByTestId("dropdown-2-display").click();
await page.getByTestId("dropdown-model_id-display").click();
await page.getByTestId("ai21.j2-grande-instruct-0-option").click();
let value = await page.getByTestId("dropdown-2-display").innerText();
let value = await page.getByTestId("dropdown-model_id-display").innerText();
if (value !== "ai21.j2-grande-instruct") {
expect(false).toBeTruthy();
}
await page.getByTestId("dropdown-2-display").click();
await page.getByTestId("dropdown-model_id-display").click();
await page.getByTestId("ai21.j2-jumbo-instruct-1-option").click();
value = await page.getByTestId("dropdown-2-display").innerText();
value = await page.getByTestId("dropdown-model_id-display").innerText();
if (value !== "ai21.j2-jumbo-instruct") {
expect(false).toBeTruthy();
}
@ -49,14 +38,14 @@ test("dropDownComponent", async ({ page }) => {
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
value = await page.getByTestId("dropdown-edit-1-display").innerText();
value = await page.getByTestId("dropdown-edit-model_id-display").innerText();
if (value !== "ai21.j2-jumbo-instruct") {
expect(false).toBeTruthy();
}
// showcode
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
// showmodel_id
await page.locator('//*[@id="showmodel_id"]').click();
@ -64,7 +53,7 @@ test("dropDownComponent", async ({ page }) => {
// showcode
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
// showmodel_id
await page.locator('//*[@id="showmodel_id"]').click();
@ -74,7 +63,7 @@ test("dropDownComponent", async ({ page }) => {
// showcode
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
// showmodel_id
await page.locator('//*[@id="showmodel_id"]').click();
@ -82,7 +71,7 @@ test("dropDownComponent", async ({ page }) => {
// showcode
await page.locator('//*[@id="showcode"]').click();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy();
expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy();
// showmodel_id
await page.locator('//*[@id="showmodel_id"]').click();
@ -90,17 +79,17 @@ test("dropDownComponent", async ({ page }) => {
await page.locator('//*[@id="showmodel_id"]').isChecked()
).toBeTruthy();
await page.getByTestId("dropdown-edit-1-display").click();
await page.getByTestId("dropdown-edit-model_id-display").click();
await page.getByTestId("ai21.j2-ultra-v1-5-option").click();
value = await page.getByTestId("dropdown-edit-1-display").innerText();
value = await page.getByTestId("dropdown-edit-model_id-display").innerText();
if (value !== "ai21.j2-ultra-v1") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="saveChangesBtn"]').click();
value = await page.getByTestId("dropdown-2-display").innerText();
value = await page.getByTestId("dropdown-model_id-display").innerText();
if (value !== "ai21.j2-ultra-v1") {
expect(false).toBeTruthy();
}

View file

@ -1,16 +1,6 @@
import { expect, test } from "@playwright/test";
test("FloatComponent", async ({ page }) => {
await page.routeFromHAR("harFiles/backend_12112023.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);
@ -23,7 +13,7 @@ test("FloatComponent", async ({ page }) => {
await page.waitForTimeout(2000);
await page
.locator('//*[@id="llmsLlamaCpp"]')
.locator('//*[@id="model_specsLlamaCpp"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
@ -102,18 +92,6 @@ test("FloatComponent", async ({ page }) => {
await page.locator('//*[@id="showmax_tokens"]').isChecked()
).toBeTruthy();
// showmetadata
await page.locator('//*[@id="showmetadata"]').click();
expect(
await page.locator('//*[@id="showmetadata"]').isChecked()
).toBeTruthy();
// showmodel_kwargs
await page.locator('//*[@id="showmodel_kwargs"]').click();
expect(
await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
).toBeTruthy();
// showmodel_path
await page.locator('//*[@id="showmodel_path"]').click();
expect(
@ -271,16 +249,6 @@ test("FloatComponent", async ({ page }) => {
await page.locator('//*[@id="showmax_tokens"]').isChecked()
).toBeFalsy();
// showmetadata
await page.locator('//*[@id="showmetadata"]').click();
expect(await page.locator('//*[@id="showmetadata"]').isChecked()).toBeFalsy();
// showmodel_kwargs
await page.locator('//*[@id="showmodel_kwargs"]').click();
expect(
await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
).toBeFalsy();
// showmodel_path
await page.locator('//*[@id="showmodel_path"]').click();
expect(

View file

@ -7,16 +7,6 @@ test.describe("Flow Page tests", () => {
}
test("save", async ({ page }) => {
await page.routeFromHAR("harFiles/backend_12112023.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);

View file

@ -4,21 +4,11 @@ import { readFileSync } from "fs";
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();
await page.locator('//*[@id="new-project-btn"]').click();
// Read your file into a buffer.
const jsonContent = readFileSync(
"tests/onlyFront/assets/collection.json",
"tests/end-to-end/assets/flow_group_test.json",
"utf-8"
);
@ -26,7 +16,7 @@ test.describe("group node test", () => {
const dataTransfer = await page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data], "flowtest.json", {
const file = new File([data], "flow_group_test.json", {
type: "application/json",
});
dt.items.add(file);
@ -35,24 +25,27 @@ test.describe("group node test", () => {
page.waitForTimeout(2000);
// Now dispatch
await page.dispatchEvent(
'//*[@id="root"]/div/div[1]/div[2]/div[3]/div/div',
"//*[@id='react-flow-id']/div[1]/div[1]/div",
"drop",
{
dataTransfer,
}
);
await page
.getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0")
.click();
await page.waitForTimeout(2000);
const genericNoda = page.getByTestId("div-generic-node");
const elementCount = await genericNoda.count();
if (elementCount > 0) {
expect(true).toBeTruthy();
}
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[3]')
.click();
await page.getByTestId("title-Agent Initializer").click({
modifiers: ["Control"],
});
await page.getByTestId("title-PythonFunctionTool").click({
modifiers: ["Control"],
@ -61,10 +54,6 @@ test.describe("group node test", () => {
modifiers: ["Control"],
});
await page.getByTestId("title-AgentInitializer").click({
modifiers: ["Control"],
});
await page.getByRole("button", { name: "Group" }).click();
const textArea = page.getByTestId("div-textarea-description");

View file

@ -1,16 +1,6 @@
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);
@ -28,12 +18,12 @@ test("InputComponent", async ({ page }) => {
await page.mouse.up();
await page.mouse.down();
await page.locator("#input-8").click();
await page.getByTestId("input-collection_name").click();
await page
.locator("#input-8")
.getByTestId("input-collection_name")
.fill("collection_name_test_123123123!@#$&*(&%$@");
let value = await page.locator("#input-8").inputValue();
let value = await page.getByTestId("input-collection_name").inputValue();
if (value != "collection_name_test_123123123!@#$&*(&%$@") {
expect(false).toBeTruthy();
@ -61,9 +51,9 @@ test("InputComponent", async ({ page }) => {
await page.locator('//*[@id="showchroma_server_host"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_http_port"]').click();
await page.locator('//*[@id="showchroma_server_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
await page.locator('//*[@id="showchroma_server_port"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
@ -76,19 +66,11 @@ test("InputComponent", async ({ page }) => {
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();
await page.locator('//*[@id="showindex_directory"]').click();
expect(
await page.locator('//*[@id="showpersist_directory"]').isChecked()
await page.locator('//*[@id="showindex_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
@ -106,9 +88,9 @@ test("InputComponent", async ({ page }) => {
await page.locator('//*[@id="showchroma_server_host"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_http_port"]').click();
await page.locator('//*[@id="showchroma_server_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
await page.locator('//*[@id="showchroma_server_port"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
@ -116,33 +98,27 @@ test("InputComponent", async ({ page }) => {
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();
await page.locator('//*[@id="showindex_directory"]').click();
expect(
await page.locator('//*[@id="showpersist_directory"]').isChecked()
await page.locator('//*[@id="showindex_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();
let valueEditNode = await page
.getByTestId("input-collection_name-edit")
.inputValue();
if (valueEditNode != "collection_name_test_123123123!@#$&*(&%$@") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="input-5"]').click();
await page.getByTestId("input-collection_name-edit").click();
await page
.locator('//*[@id="input-5"]')
.getByTestId("input-collection_name-edit")
.fill("NEW_collection_name_test_123123123!@#$&*(&%$@");
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator("#input-8");
const plusButtonLocator = page.getByTestId("input-collection_name");
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
@ -159,7 +135,7 @@ test("InputComponent", async ({ page }) => {
await page.locator('//*[@id="saveChangesBtn"]').click();
let value = await page.locator("#input-8").inputValue();
let value = await page.getByTestId("input-collection_name").inputValue();
if (value != "NEW_collection_name_test_123123123!@#$&*(&%$@") {
expect(false).toBeTruthy();

View file

@ -1,17 +1,6 @@
import { expect, test } from "@playwright/test";
test("IntComponent", async ({ page }) => {
await page.routeFromHAR("harFiles/backend_12112023.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);
@ -30,21 +19,21 @@ test("IntComponent", async ({ page }) => {
await page.mouse.up();
await page.mouse.down();
await page.locator('//*[@id="int-input-2"]').click();
await page.getByTestId("int-input-timeout").click();
await page
.locator('//*[@id="int-input-2"]')
.getByTestId("int-input-timeout")
.fill("123456789123456789123456789");
let value = await page.locator('//*[@id="int-input-2"]').inputValue();
let value = await page.getByTestId("int-input-timeout").inputValue();
if (value != "123456789123456789123456789") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="int-input-2"]').click();
await page.locator('//*[@id="int-input-2"]').fill("0");
await page.getByTestId("int-input-timeout").click();
await page.getByTestId("int-input-timeout").fill("0");
value = await page.locator('//*[@id="int-input-2"]').inputValue();
value = await page.getByTestId("int-input-timeout").inputValue();
if (value != "0") {
expect(false).toBeTruthy();
@ -53,15 +42,15 @@ test("IntComponent", async ({ page }) => {
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
value = await page.locator('//*[@id="edit-int-input-2"]').inputValue();
value = await page.getByTestId("edit-int-input-timeout").inputValue();
if (value != "0") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="edit-int-input-2"]').click();
await page.getByTestId("edit-int-input-timeout").click();
await page
.locator('//*[@id="edit-int-input-2"]')
.getByTestId("edit-int-input-timeout")
.fill("123456789123456789123456789");
await page.locator('//*[@id="showheaders"]').click();
@ -81,7 +70,7 @@ test("IntComponent", async ({ page }) => {
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="int-input-2"]');
const plusButtonLocator = page.getByTestId("int-input-timeout");
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
@ -95,7 +84,7 @@ test("IntComponent", async ({ page }) => {
).toBeTruthy();
const valueEditNode = await page
.locator('//*[@id="edit-int-input-2"]')
.getByTestId("edit-int-input-timeout")
.inputValue();
if (valueEditNode != "123456789123456789123456789") {
@ -103,19 +92,19 @@ test("IntComponent", async ({ page }) => {
}
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.locator('//*[@id="int-input-2"]').click();
await page.locator('//*[@id="int-input-2"]').fill("3");
await page.getByTestId("int-input-timeout").click();
await page.getByTestId("int-input-timeout").fill("3");
let value = await page.locator('//*[@id="int-input-2"]').inputValue();
let value = await page.getByTestId("int-input-timeout").inputValue();
if (value != "3") {
expect(false).toBeTruthy();
}
await page.locator('//*[@id="int-input-2"]').click();
await page.locator('//*[@id="int-input-2"]').fill("-3");
await page.getByTestId("int-input-timeout").click();
await page.getByTestId("int-input-timeout").fill("-3");
value = await page.locator('//*[@id="int-input-2"]').inputValue();
value = await page.getByTestId("int-input-timeout").inputValue();
if (value != "0") {
expect(false).toBeTruthy();

View file

@ -1,16 +1,6 @@
import { expect, test } from "@playwright/test";
test("KeypairListComponent", async ({ page }) => {
await page.routeFromHAR("harFiles/backend_12112023.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);

View file

@ -1,16 +1,6 @@
import { expect, test } from "@playwright/test";
test("NestedComponent", async ({ page }) => {
await page.routeFromHAR("harFiles/backend_12112023.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);
@ -31,75 +21,17 @@ test("NestedComponent", async ({ page }) => {
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
// showindex_name
await page.locator('//*[@id="showindex_name"]').click();
//showpool_threads
await page.locator('//*[@id="showpool_threads"]').click();
expect(
await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeFalsy();
// shownamespace
await page.locator('//*[@id="shownamespace"]').click();
expect(
await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeFalsy();
// showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click();
expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
await page.locator('//*[@id="showpool_threads"]').isChecked()
).toBeTruthy();
// showpinecone_env
await page.locator('//*[@id="showpinecone_env"]').click();
//showtext_key
await page.locator('//*[@id="showtext_key"]').click();
expect(
await page.locator('//*[@id="showpinecone_env"]').isChecked()
).toBeTruthy();
// showsearch_kwargs
await page.locator('//*[@id="showsearch_kwargs"]').click();
expect(
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
).toBeTruthy();
// showindex_name
await page.locator('//*[@id="showindex_name"]').click();
expect(
await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeTruthy();
// shownamespace
await page.locator('//*[@id="shownamespace"]').click();
expect(
await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeTruthy();
// showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click();
expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeFalsy();
// showpinecone_env
await page.locator('//*[@id="showpinecone_env"]').click();
expect(
await page.locator('//*[@id="showpinecone_env"]').isChecked()
).toBeFalsy();
// showsearch_kwargs
await page.locator('//*[@id="showsearch_kwargs"]').click();
expect(
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
).toBeFalsy();
expect(await page.locator('//*[@id="showtext_key"]').isChecked()).toBeFalsy();
// showindex_name
await page.locator('//*[@id="showindex_name"]').click();
@ -120,21 +52,14 @@ test("NestedComponent", async ({ page }) => {
expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeTruthy();
).toBeFalsy();
// showpinecone_env
await page.locator('//*[@id="showpinecone_env"]').click();
expect(
await page.locator('//*[@id="showpinecone_env"]').isChecked()
).toBeTruthy();
// showsearch_kwargs
await page.locator('//*[@id="showsearch_kwargs"]').click();
expect(
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
).toBeTruthy();
).toBeFalsy();
// showindex_name
await page.locator('//*[@id="showindex_name"]').click();
@ -155,21 +80,14 @@ test("NestedComponent", async ({ page }) => {
expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeFalsy();
).toBeTruthy();
// showpinecone_env
await page.locator('//*[@id="showpinecone_env"]').click();
expect(
await page.locator('//*[@id="showpinecone_env"]').isChecked()
).toBeFalsy();
// showsearch_kwargs
await page.locator('//*[@id="showsearch_kwargs"]').click();
expect(
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
).toBeFalsy();
).toBeTruthy();
// showindex_name
await page.locator('//*[@id="showindex_name"]').click();
@ -190,21 +108,14 @@ test("NestedComponent", async ({ page }) => {
expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeTruthy();
).toBeFalsy();
// showpinecone_env
await page.locator('//*[@id="showpinecone_env"]').click();
expect(
await page.locator('//*[@id="showpinecone_env"]').isChecked()
).toBeTruthy();
// showsearch_kwargs
await page.locator('//*[@id="showsearch_kwargs"]').click();
expect(
await page.locator('//*[@id="showsearch_kwargs"]').isChecked()
).toBeTruthy();
).toBeFalsy();
// showindex_name
await page.locator('//*[@id="showindex_name"]').click();
@ -223,6 +134,34 @@ test("NestedComponent", async ({ page }) => {
// showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click();
expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeTruthy();
// showpinecone_env
await page.locator('//*[@id="showpinecone_env"]').click();
expect(
await page.locator('//*[@id="showpinecone_env"]').isChecked()
).toBeTruthy();
// showindex_name
await page.locator('//*[@id="showindex_name"]').click();
expect(
await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeFalsy();
// shownamespace
await page.locator('//*[@id="shownamespace"]').click();
expect(
await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeFalsy();
// showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click();
expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeFalsy();
@ -234,7 +173,47 @@ test("NestedComponent", async ({ page }) => {
await page.locator('//*[@id="showpinecone_env"]').isChecked()
).toBeFalsy();
// showindex_name
await page.locator('//*[@id="showindex_name"]').click();
expect(
await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeTruthy();
// shownamespace
await page.locator('//*[@id="shownamespace"]').click();
expect(
await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeTruthy();
// showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click();
expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeTruthy();
// showpinecone_env
await page.locator('//*[@id="showpinecone_env"]').click();
expect(
await page.locator('//*[@id="showpinecone_env"]').isChecked()
).toBeTruthy();
//showpool_threads
await page.locator('//*[@id="showpool_threads"]').click();
expect(
await page.locator('//*[@id="showpool_threads"]').isChecked()
).toBeFalsy();
//showtext_key
await page.locator('//*[@id="showtext_key"]').click();
expect(
await page.locator('//*[@id="showtext_key"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.getByTestId("div-dict-input").click();
});

View file

@ -8,25 +8,27 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.waitForTimeout(2000);
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("promptTemplate");
await page.getByPlaceholder("Search").fill("prompt");
await page.waitForTimeout(2000);
await page
.locator('//*[@id="promptsPromptTemplate"]')
.locator('//*[@id="promptsPrompt"]')
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.getByTestId("prompt-input-0").click();
await page.getByTestId("prompt-input-template").click();
// await page.getByTestId("edit-prompt-sanitized").click();
// await page.getByTestId("modal-title").click();
await page
.getByTestId("modal-prompt-input-0")
.getByTestId("modal-prompt-input-template")
.fill("{prompt} example {prompt1}");
let value = await page.getByTestId("modal-prompt-input-0").inputValue();
let value = await page
.getByTestId("modal-prompt-input-template")
.inputValue();
if (value != "{prompt} example {prompt1}") {
expect(false).toBeTruthy();
@ -45,35 +47,39 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.getByTestId("genericModalBtnSave").click();
await page.getByTestId("div-textarea-prompt").click();
await page.getByTestId("text-area-modal").fill("prompt_value_!@#!@#");
await page.getByTestId("textarea-prompt").fill("prompt_value_!@#!@#");
value = await page.getByTestId("text-area-modal").inputValue();
value = await page.getByTestId("textarea-prompt").inputValue();
if (value != "prompt_value_!@#!@#") {
expect(false).toBeTruthy();
}
await page.getByTestId("genericModalBtnSave").click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("save-button-modal").click();
const replace = await page.getByTestId("replace-button");
if (replace) {
await page.getByTestId("replace-button").click();
}
await page.getByTestId("div-textarea-prompt1").click();
await page
.getByTestId("text-area-modal")
.getByTestId("textarea-prompt1")
.fill("prompt_name_test_123123!@#!@#");
value = await page.getByTestId("text-area-modal").inputValue();
value = await page.getByTestId("textarea-prompt1").inputValue();
if (value != "prompt_name_test_123123!@#!@#") {
expect(false).toBeTruthy();
}
value = await page.getByTestId("text-area-modal").inputValue();
value = await page.getByTestId("textarea-prompt1").inputValue();
if (value != "prompt_name_test_123123!@#!@#") {
expect(false).toBeTruthy();
}
await page.getByTestId("genericModalBtnSave").click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();

View file

@ -11,22 +11,12 @@ test.describe("save component tests", () => {
/// <reference lib="dom"/>
test("save group component tests", async ({ page }) => {
//make front work withoput backend
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();
await page.locator('//*[@id="new-project-btn"]').click();
// Read your file into a buffer.
const jsonContent = readFileSync(
"tests/onlyFront/assets/collection.json",
"tests/end-to-end/assets/flow_group_test.json",
"utf-8"
);
@ -34,32 +24,32 @@ test.describe("save component tests", () => {
const dataTransfer = await page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data], "flowtest.json", {
const file = new File([data], "flow_group_test.json", {
type: "application/json",
});
dt.items.add(file);
return dt;
}, jsonContent);
page.waitForTimeout(2000);
// Now dispatch
await page.dispatchEvent(
'//*[@id="root"]/div/div[1]/div[2]/div[3]/div/div',
"//*[@id='react-flow-id']/div[1]/div[1]/div",
"drop",
{
dataTransfer,
}
);
await page
.getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0")
.click();
await page.waitForTimeout(2000);
const genericNoda = page.getByTestId("div-generic-node");
const elementCount = await genericNoda.count();
if (elementCount > 0) {
expect(true).toBeTruthy();
}
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[3]')
.click();
await page.getByTestId("title-PythonFunctionTool").click({
modifiers: ["Control"],
@ -68,7 +58,7 @@ test.describe("save component tests", () => {
modifiers: ["Control"],
});
await page.getByTestId("title-AgentInitializer").click({
await page.getByTestId("title-Agent Initializer").click({
modifiers: ["Control"],
});
@ -87,9 +77,13 @@ test.describe("save component tests", () => {
}
await page.getByTestId("title-Group").click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("save-button-modal").click();
await page.getByTestId("delete-button-modal").click();
await page.getByTestId("icon-SaveAll").click();
const replaceButton = page.getByTestId("replace-button");
if (replaceButton) {
await replaceButton.click();
}
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("group");

View file

@ -1,16 +1,6 @@
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);
@ -38,29 +28,27 @@ test("ToggleComponent", async ({ page }) => {
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.getByTestId("toggle-load_hidden").click();
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
await page.getByTestId("toggle-load_hidden").click();
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.getByTestId("toggle-load_hidden").click();
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
await page.getByTestId("toggle-load_hidden").click();
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.getByTestId("toggle-load_hidden").click();
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
await page.getByTestId("div-generic-node").click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
expect(
await page.locator('//*[@id="toggle-edit-1"]').isChecked()
).toBeFalsy();
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
await page.locator('//*[@id="showglob"]').click();
expect(await page.locator('//*[@id="showglob"]').isChecked()).toBeFalsy();
@ -129,7 +117,7 @@ test("ToggleComponent", async ({ page }) => {
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="toggle-1"]');
const plusButtonLocator = page.getByTestId("toggle-load_hidden");
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
@ -145,24 +133,34 @@ test("ToggleComponent", async ({ page }) => {
).toBeTruthy();
expect(
await page.locator('//*[@id="toggle-edit-1"]').isChecked()
await page.getByTestId("toggle-edit-load_hidden").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.getByTestId("toggle-load_hidden").click();
expect(
await page.getByTestId("toggle-load_hidden").isChecked()
).toBeTruthy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.getByTestId("toggle-load_hidden").click();
expect(
await page.getByTestId("toggle-load_hidden").isChecked()
).toBeFalsy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
await page.getByTestId("toggle-load_hidden").click();
expect(
await page.getByTestId("toggle-load_hidden").isChecked()
).toBeTruthy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy();
await page.getByTestId("toggle-load_hidden").click();
expect(
await page.getByTestId("toggle-load_hidden").isChecked()
).toBeFalsy();
await page.locator('//*[@id="toggle-1"]').click();
expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy();
await page.getByTestId("toggle-load_hidden").click();
expect(
await page.getByTestId("toggle-load_hidden").isChecked()
).toBeTruthy();
}
});

View file

@ -1,121 +0,0 @@
import { test } from "@playwright/test";
test.describe("Login Tests", () => {
test("Login_Success", async ({ page }) => {
// await page.route("**/api/v1/login", async (route) => {
// const json = {
// access_token:
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWNlM2FkOS1iZTE2LTRiNjgtOGRhYi1hYjA4YTVjMmZjZTkiLCJleHAiOjE2OTUyNTIwNTh9.MBYFwMhTcZnsW_L7p4qavUhSDylCllJQWUCJdU1wX8o",
// refresh_token:
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWNlM2FkOS1iZTE2LTRiNjgtOGRhYi1hYjA4YTVjMmZjZTkiLCJ0eXBlIjoicmYiLCJleHAiOjE2OTUyNTI2NTh9.a4wL9-XK_zyTyrXduBFgCsODFXrqiByVr5HOeiCbiQA",
// token_type: "bearer",
// };
// await route.fulfill({ json });
// });
// await page.goto("http://localhost:3000/");
// await page.waitForURL("http://localhost:3000/login");
// await page.waitForURL("http://localhost:3000/login", { timeout: 100 });
// await page.getByPlaceholder("Username").click();
// await page.getByPlaceholder("Username").fill("test");
// await page.getByPlaceholder("Password").click();
// await page.getByPlaceholder("Password").fill("test");
// await page.getByRole("button", { name: "Sign in" }).click();
// await page.getByRole("button", { name: "Community Examples" }).click();
// await page.waitForSelector(".community-pages-flows-panel");
// expect(
// await page
// .locator(".community-pages-flows-panel")
// .evaluate((el) => el.children)
// ).toBeTruthy();
// });
// test("Login Error", async ({ page }) => {
// await page.route("**/api/v1/login", async (route) => {
// const json = { detail: "Incorrect username or password" };
// await route.fulfill({ json, status: 401 });
// });
// await page.goto("http://localhost:3000/");
// await page.waitForURL("http://localhost:3000/login");
// await page.waitForURL("http://localhost:3000/login", { timeout: 100 });
// await page.getByPlaceholder("Username").click();
// await page.getByPlaceholder("Username").fill("test");
// await page.getByPlaceholder("Password").click();
// await page.getByPlaceholder("Password").fill("test5");
// await page.getByRole("button", { name: "Sign in" }).click();
// await page.getByRole("heading", { name: "Error signing in" }).click();
// });
// test("Login create account wrong form", async ({ page }) => {
// const fullfillForm = async (username, password, confirmPassword) => {
// await page.getByPlaceholder("Username").click();
// await page.getByPlaceholder("Username").fill(username);
// await page.getByPlaceholder("Password", { exact: true }).click();
// await page.getByPlaceholder("Password", { exact: true }).fill(password);
// await page.getByPlaceholder("Confirm your password").click();
// await page
// .getByPlaceholder("Confirm your password")
// .fill(confirmPassword);
// };
// await page.goto("http://localhost:3000/");
// await page.waitForURL("http://localhost:3000/login");
// await page.waitForURL("http://localhost:3000/login", { timeout: 100 });
// await page
// .getByRole("button", { name: "Don't have an account? Sign Up" })
// .click();
// await page.getByText("Sign up to Langflow").click();
// await page.goto("http://localhost:3000/signup");
// await page.getByText("Sign up to Langflow").click();
// await fullfillForm("name", "vazz", "vazz5");
// expect(
// await page.getByRole("button", { name: "Sign up" }).isDisabled()
// ).toBeTruthy();
// await fullfillForm("", "vazz", "vazz");
// expect(
// await page.getByRole("button", { name: "Sign up" }).isDisabled()
// ).toBeTruthy();
// await fullfillForm("name", "", "");
// expect(
// await page.getByRole("button", { name: "Sign up" }).isDisabled()
// ).toBeTruthy();
// await fullfillForm("", "", "");
// expect(
// await page.getByRole("button", { name: "Sign up" }).isDisabled()
// ).toBeTruthy();
// });
// test("Login create account success", async ({ page }) => {
// await page.route("**/api/v1/users/", async (route) => {
// const json = {
// id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
// username: "teste",
// profile_image: null,
// is_active: false,
// is_superuser: false,
// create_at: "2023-09-21T01:45:51.873303",
// updated_at: "2023-09-21T01:45:51.873305",
// last_login_at: null,
// };
// await route.fulfill({ json, status: 201 });
// });
// const submitForm = async (username, password, confirmPassword) => {
// await page.getByPlaceholder("Username").click();
// await page.getByPlaceholder("Username").fill(username);
// await page.getByPlaceholder("Password", { exact: true }).click();
// await page.getByPlaceholder("Password", { exact: true }).fill(password);
// await page.getByPlaceholder("Confirm your password").click();
// await page
// .getByPlaceholder("Confirm your password")
// .fill(confirmPassword);
// };
// await page.goto("http://localhost:3000/");
// await page.waitForURL("http://localhost:3000/login");
// await page.waitForURL("http://localhost:3000/login", { timeout: 100 });
// await page
// .getByRole("button", { name: "Don't have an account? Sign Up" })
// .click();
// await page.getByText("Sign up to Langflow").click();
// await page.goto("http://localhost:3000/signup");
// await page.getByText("Sign up to Langflow").click();
// await submitForm("teste", "pass", "pass");
// await page.getByRole("button", { name: "Sign up" }).click();
// await page.waitForURL("http://localhost:3000/login", { timeout: 1000 });
// await page.getByText("Account created! Await admin activation.").click();
});
});