Skip to content
Merged
479 changes: 479 additions & 0 deletions src/backend/tests/unit/components/flow_controls/test_loop_freeze.py

Large diffs are not rendered by default.

167 changes: 54 additions & 113 deletions src/frontend/package-lock.json

Large diffs are not rendered by default.

574 changes: 288 additions & 286 deletions src/frontend/tests/core/regression/generalBugs-shard-5.spec.ts

Large diffs are not rendered by default.

88 changes: 43 additions & 45 deletions src/frontend/tests/core/unit/codeAreaModalComponent.spec.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,35 @@
import { expect } from "@playwright/test";
import { test } from "../../fixtures";
import { addLegacyComponents } from "../../utils/add-legacy-components";
import { adjustScreenView } from "../../utils/adjust-screen-view";
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";

test(
"CodeAreaModalComponent",
{ tag: ["@release", "@workspace"] },
async ({ page }) => {
await awaitBootstrapTest(page);
"CodeAreaModalComponent",
{ tag: ["@release", "@workspace"] },
async ({ page }) => {
await awaitBootstrapTest(page);

await page.waitForSelector('[data-testid="blank-flow"]', {
timeout: 3000,
});
await page.waitForSelector('[data-testid="blank-flow"]', {
timeout: 3000,
});

await page.getByTestId("blank-flow").click();
await page.getByTestId("blank-flow").click();

await page.getByTestId("canvas_controls_dropdown").click();
await page.getByTestId("canvas_controls_dropdown").click();

await page.waitForSelector('[data-testid="zoom_out"]', {
timeout: 3000,
});
await page.getByTestId("canvas_controls_dropdown").click({ force: true });
await page.waitForSelector('[data-testid="zoom_out"]', {
timeout: 3000,
});
await page.getByTestId("canvas_controls_dropdown").click({ force: true });

await page.getByTestId("sidebar-custom-component-button").click();
await page.getByTestId("sidebar-custom-component-button").click();

await expect(page.getByTestId("code-button-modal")).toBeVisible({
timeout: 3000,
});
await expect(page.getByTestId("code-button-modal")).toBeVisible({
timeout: 3000,
});

await page.getByTestId("code-button-modal").last().click();
await page.getByTestId("code-button-modal").last().click();

const codeInputCode = `
const codeInputCode = `
# from langflow.field_typing import Data
from langflow.custom import Component
from langflow.io import CodeInput, Output
Expand Down Expand Up @@ -64,20 +62,20 @@ class CustomComponent(Component):
sleep(60)
return data`;

await page.locator(".ace_content").click();
await page.keyboard.press(`ControlOrMeta+A`);
await page.locator("textarea").fill(codeInputCode);
await page.locator(".ace_content").click();
await page.keyboard.press(`ControlOrMeta+A`);
await page.locator("textarea").fill(codeInputCode);

await page.getByText("Check & Save").last().click();
await page.getByText("Check & Save").last().click();

await page.getByTestId("div-generic-node").click();
await page.getByTestId("div-generic-node").click();

await page.getByTestId("codearea_code_function_code").click();
await page.getByTestId("codearea_code_function_code").click();

const wCode =
'def python_function(text: str) -> st: """This is a default python function that returns the input text""" return text';
const wCode =
'def python_function(text: str) -> st: """This is a default python function that returns the input text""" return text';

const customComponentCode = `from typing import Callable
const customComponentCode = `from typing import Callable
from langflow.field_typing import Code
from langflow.interface.custom.custom_component import CustomComponent
from langflow.interface.custom.utils import get_function
Expand All @@ -87,19 +85,19 @@ class PythonFunctionComponent(CustomComponent):
"""This is a default python function that returns the input text"""
return text`;

await page.locator(".ace_content").click();
await page.locator("textarea").press("ControlOrMeta+a");
await page.locator("textarea").fill(wCode);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await expect(
page.getByText("invalid syntax (<unknown>, line 1)"),
).toBeVisible({ timeout: 3000 });
await page.locator("textarea").press("ControlOrMeta+a");
await page.locator("textarea").fill(customComponentCode);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await expect(page.getByTestId("codearea_code_function_code")).toHaveText(
customComponentCode,
{ timeout: 3000 },
);
},
await page.locator(".ace_content").click();
await page.locator("textarea").press("ControlOrMeta+a");
await page.locator("textarea").fill(wCode);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await expect(
page.getByText("invalid syntax (<unknown>, line 1)"),
).toBeVisible({ timeout: 3000 });
await page.locator("textarea").press("ControlOrMeta+a");
await page.locator("textarea").fill(customComponentCode);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await expect(page.getByTestId("codearea_code_function_code")).toHaveText(
customComponentCode,
{ timeout: 3000 },
);
},
);
3 changes: 3 additions & 0 deletions src/frontend/tests/core/unit/fileUploadComponent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { adjustScreenView } from "../../utils/adjust-screen-view";
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
import { generateRandomFilename } from "../../utils/generate-filename";

// Run tests in this file serially to avoid database conflicts with shared file state
test.describe.configure({ mode: "serial" });

test(
"should be able to upload a file",
{
Expand Down
2 changes: 1 addition & 1 deletion src/lfx/src/lfx/_assets/component_index.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion src/lfx/src/lfx/graph/graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1519,7 +1519,10 @@ async def build_vertex(
try:
params = ""
should_build = False
if not vertex.frozen:
# Loop components must always build, even when frozen,
# because they need to iterate through their data
is_loop_component = vertex.display_name == "Loop" or vertex.is_loop
if not vertex.frozen or is_loop_component:
should_build = True
else:
# Check the cache for the vertex
Expand Down
5 changes: 4 additions & 1 deletion src/lfx/src/lfx/graph/vertex/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,10 @@ async def build(
self.build_inactive()
return None

if self.frozen and self.built:
# Loop components should always run, even when frozen,
# because they need to iterate through their data
is_loop_component = self.display_name == "Loop" or self.is_loop
if self.frozen and self.built and not is_loop_component:
return await self.get_requester_result(requester)
if self.built and requester is not None:
# This means that the vertex has already been built
Expand Down
8 changes: 4 additions & 4 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading