mirror of
https://github.com/hanzoai/flow.git
synced 2026-11-02 23:41:19 +00:00
Completes the rebrand per direction: LANGFLOW_/LANGFLOW -> FLOW_/FLOW (env vars, headers), langflow_ -> flow_ (settings fields, local vars), camelCase identifiers (LangflowClient/Logo/HTTPError, builtWithLangflow, getLangflowDesktop) -> Flow*, and all remaining bare tokens. Fixed the identifier-space hazard (Langflow -> 'Hanzo Flow' is prose-only; in code it collapses to Flow so no identifier gains a space). compileall of flow + lfx is clean. Repo-wide langflow now = 4, all the protected MIT attribution to langflow-ai/ langflow in README (legally required; deliberately preserved). Breaking (per no-backwards-compat / forward-perfection): the LANGFLOW_* env-var prefix is now FLOW_* — deployments must update their env. CI's uv + frontend build is the runtime gate.
204 lines
5.9 KiB
TypeScript
204 lines
5.9 KiB
TypeScript
/**
|
|
* Test template for React components in Flow.
|
|
*
|
|
* Usage:
|
|
* 1. Copy this file to `__tests__/ComponentName.test.tsx`
|
|
* 2. Replace all TEMPLATE_* placeholders with actual values
|
|
* 3. Remove unused sections
|
|
* 4. Run: npm test -- path/to/__tests__/ComponentName.test.tsx
|
|
*/
|
|
|
|
import { render, screen, waitFor } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
// Replace with actual component import path
|
|
import TEMPLATE_COMPONENT from "../TEMPLATE_COMPONENT";
|
|
|
|
// ============================================================
|
|
// Mocks
|
|
// ============================================================
|
|
|
|
// Mock API calls (if component fetches data)
|
|
// jest.mock("@/controllers/API/api", () => ({
|
|
// __esModule: true,
|
|
// default: {
|
|
// get: jest.fn(),
|
|
// post: jest.fn(),
|
|
// },
|
|
// }));
|
|
|
|
// Mock Zustand stores (if component reads from stores)
|
|
// jest.mock("@/stores/flowStore", () => ({
|
|
// __esModule: true,
|
|
// default: (selector?: (state: any) => any) =>
|
|
// selector ? selector({ nodes: [], edges: [] }) : {},
|
|
// }));
|
|
|
|
// Mock child components (only if they have complex dependencies)
|
|
// jest.mock("../ChildComponent", () => ({
|
|
// __esModule: true,
|
|
// default: (props: any) => <div data-testid="mock-child">{props.label}</div>,
|
|
// }));
|
|
|
|
// ============================================================
|
|
// Test Data
|
|
// ============================================================
|
|
|
|
const defaultProps = {
|
|
// Replace with actual default props for the component
|
|
// title: "Test Title",
|
|
// onClick: jest.fn(),
|
|
};
|
|
|
|
// ============================================================
|
|
// Helper Functions
|
|
// ============================================================
|
|
|
|
function renderComponent(overrides = {}) {
|
|
const props = { ...defaultProps, ...overrides };
|
|
return render(<TEMPLATE_COMPONENT {...props} />);
|
|
}
|
|
|
|
// Use this if the component requires providers (router, query client, context)
|
|
// function renderWithProviders(overrides = {}) {
|
|
// const props = { ...defaultProps, ...overrides };
|
|
// const queryClient = new QueryClient({
|
|
// defaultOptions: { queries: { retry: false } },
|
|
// });
|
|
// return render(
|
|
// <QueryClientProvider client={queryClient}>
|
|
// <MemoryRouter>
|
|
// <TEMPLATE_COMPONENT {...props} />
|
|
// </MemoryRouter>
|
|
// </QueryClientProvider>,
|
|
// );
|
|
// }
|
|
|
|
// ============================================================
|
|
// Tests
|
|
// ============================================================
|
|
|
|
describe("TEMPLATE_COMPONENT", () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// Rendering
|
|
// ----------------------------------------------------------
|
|
|
|
describe("rendering", () => {
|
|
it("should render with default props", () => {
|
|
renderComponent();
|
|
|
|
// Replace with actual assertions
|
|
// expect(screen.getByRole("button")).toBeInTheDocument();
|
|
// expect(screen.getByText("Test Title")).toBeInTheDocument();
|
|
});
|
|
|
|
it("should render with all optional props", () => {
|
|
renderComponent({
|
|
// Provide all optional props
|
|
});
|
|
|
|
// Assert all optional elements are rendered
|
|
});
|
|
|
|
it("should apply conditional rendering based on props", () => {
|
|
// Test each conditional branch in the JSX
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// User Interactions
|
|
// ----------------------------------------------------------
|
|
|
|
describe("user interactions", () => {
|
|
it("should handle click events", async () => {
|
|
const user = userEvent.setup();
|
|
const onClick = jest.fn();
|
|
renderComponent({ onClick });
|
|
|
|
await user.click(screen.getByRole("button"));
|
|
|
|
expect(onClick).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("should handle text input", async () => {
|
|
const user = userEvent.setup();
|
|
const onChange = jest.fn();
|
|
renderComponent({ onChange });
|
|
|
|
await user.type(screen.getByRole("textbox"), "test input");
|
|
|
|
expect(onChange).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// Async Behavior
|
|
// ----------------------------------------------------------
|
|
|
|
// describe("async behavior", () => {
|
|
// it("should show loading state initially", () => {
|
|
// renderComponent();
|
|
// expect(screen.getByTestId("loading-spinner")).toBeInTheDocument();
|
|
// });
|
|
//
|
|
// it("should display data after loading", async () => {
|
|
// jest.mocked(api.get).mockResolvedValueOnce({
|
|
// data: { items: [{ id: "1", name: "Test" }] },
|
|
// });
|
|
//
|
|
// renderComponent();
|
|
//
|
|
// await waitFor(() => {
|
|
// expect(screen.getByText("Test")).toBeInTheDocument();
|
|
// });
|
|
// });
|
|
//
|
|
// it("should handle API errors gracefully", async () => {
|
|
// jest.mocked(api.get).mockRejectedValueOnce(new Error("Network error"));
|
|
//
|
|
// renderComponent();
|
|
//
|
|
// await waitFor(() => {
|
|
// expect(screen.getByText(/error/i)).toBeInTheDocument();
|
|
// });
|
|
// });
|
|
// });
|
|
|
|
// ----------------------------------------------------------
|
|
// Edge Cases
|
|
// ----------------------------------------------------------
|
|
|
|
describe("edge cases", () => {
|
|
it("should handle empty data", () => {
|
|
renderComponent({
|
|
// Pass empty arrays, empty strings, etc.
|
|
});
|
|
|
|
// Assert empty state rendering
|
|
});
|
|
|
|
it("should handle undefined optional props", () => {
|
|
renderComponent({
|
|
// Explicitly pass undefined for optional props
|
|
});
|
|
|
|
// Assert fallback behavior
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// Cleanup
|
|
// ----------------------------------------------------------
|
|
|
|
// describe("cleanup", () => {
|
|
// it("should clean up on unmount", () => {
|
|
// const { unmount } = renderComponent();
|
|
// unmount();
|
|
// // Assert cleanup (e.g., clearInterval called, event listeners removed)
|
|
// });
|
|
// });
|
|
});
|