feat: Add New Link Parameter Type for External Links in Node UI (#3806)
* ✨ (inputs/__init__.py): Add LinkInput class to support linking functionality in inputs 📝 (inputs/input_mixin.py): Add Link field type to support linking functionality in inputs 📝 (inputs/inputs.py): Add LinkInput class to support linking functionality in inputs 📝 (io/__init__.py): Import and export LinkInput class for linking functionality in inputs 📝 (frontend/src/components/linkComponent/index.tsx): Create LinkComponent to display and handle links in frontend components 📝 (frontend/src/components/parameterRenderComponent/index.tsx): Add support for rendering LinkComponent in parameter rendering based on template type 📝 (frontend/src/constants/constants.ts): Add "link" as a supported type for LANGFLOW_SUPPORTED_TYPES 📝 (frontend/src/types/api/index.ts): Add icon and text fields to InputFieldType for link component 📝 (frontend/src/types/components/index.ts): Define LinkComponentType for passing link data to LinkComponent ✨ (linkComponent.spec.ts): Add unit test for link component interaction to ensure proper functionality and behavior 📝 (unit-test-components.spec.ts): Add template for a unit test file to be used for testing components in the frontend application * style: apply make format * Update input_mixin.py --------- Co-authored-by: italojohnny <italojohnnydosanjos@gmail.com>
This commit is contained in:
parent
d4bed03f9c
commit
3e617acf2f
11 changed files with 221 additions and 1 deletions
117
src/frontend/tests/core/unit/linkComponent.spec.ts
Normal file
117
src/frontend/tests/core/unit/linkComponent.spec.ts
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import { expect, Page, test } from "@playwright/test";
|
||||
import uaParser from "ua-parser-js";
|
||||
|
||||
test("user should interact with link component", async ({ context, page }) => {
|
||||
await page.goto("/");
|
||||
await page.waitForSelector('[data-testid="mainpage_title"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
await page.waitForSelector('[id="new-project-btn"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.getByText("New Project", { exact: true }).click();
|
||||
await page.waitForTimeout(3000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
const getUA = await page.evaluate(() => navigator.userAgent);
|
||||
const userAgentInfo = uaParser(getUA);
|
||||
let control = "Control";
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
|
||||
await page.waitForSelector('[data-testid="extended-disclosure"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
const focusElementsOnBoard = async ({ page }) => {
|
||||
const focusElements = await page.getByTestId("extended-disclosure");
|
||||
focusElements.click();
|
||||
};
|
||||
|
||||
await focusElementsOnBoard({ page });
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("custom component");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.locator('//*[@id="helpersCustom Component"]')
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page.getByTestId("title-Custom Component").first().click();
|
||||
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId("code-button-modal").click();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
let cleanCode = await extractAndCleanCode(page);
|
||||
|
||||
// Replace the import statement
|
||||
cleanCode = cleanCode.replace(
|
||||
"from langflow.io import MessageTextInput, Output",
|
||||
"from langflow.io import MessageTextInput, Output, LinkInput",
|
||||
);
|
||||
|
||||
// Replace the MessageTextInput line and add LinkInput
|
||||
cleanCode = cleanCode.replace(
|
||||
'MessageTextInput(name="input_value", display_name="Input Value", value="Hello, World!"),',
|
||||
`MessageTextInput(name="input_value", display_name="Input Value", value="Hello, World!"),
|
||||
LinkInput(name="link", display_name="BUTTON", value="https://www.datastax.com", text="Click me"),`,
|
||||
);
|
||||
|
||||
await page.locator("textarea").last().press(`Meta+a`);
|
||||
await page.keyboard.press("Backspace");
|
||||
await page.locator("textarea").last().fill(cleanCode);
|
||||
await page.locator('//*[@id="checkAndSaveBtn"]').click();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
expect(await page.getByText("BUTTON").isVisible()).toBeTruthy();
|
||||
expect(await page.getByText("Click me").isVisible()).toBeTruthy();
|
||||
expect(await page.getByTestId("link_link_link")).toBeEnabled();
|
||||
await page.getByTestId("link_link_link").click();
|
||||
});
|
||||
|
||||
async function extractAndCleanCode(page: Page): Promise<string> {
|
||||
const outerHTML = await page
|
||||
.locator('//*[@id="codeValue"]')
|
||||
.evaluate((el) => el.outerHTML);
|
||||
|
||||
const valueMatch = outerHTML.match(/value="([\s\S]*?)"/);
|
||||
if (!valueMatch) {
|
||||
throw new Error("Could not find value attribute in the HTML");
|
||||
}
|
||||
|
||||
let codeContent = valueMatch[1]
|
||||
.replace(/"/g, '"')
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/'/g, "'")
|
||||
.replace(///g, "/");
|
||||
|
||||
return codeContent;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { test } from "@playwright/test";
|
||||
|
||||
test("your_test_name", async ({ page }) => {});
|
||||
Loading…
Add table
Add a link
Reference in a new issue