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.
241 lines
7.0 KiB
TypeScript
241 lines
7.0 KiB
TypeScript
/**
|
|
* Test template for custom React hooks in Flow.
|
|
*
|
|
* Usage:
|
|
* 1. Copy this file to `__tests__/use-hook-name.test.ts`
|
|
* 2. Replace all TEMPLATE_* placeholders with actual values
|
|
* 3. Remove unused sections
|
|
* 4. Run: npm test -- path/to/__tests__/use-hook-name.test.ts
|
|
*/
|
|
|
|
import { act, renderHook, waitFor } from "@testing-library/react";
|
|
// Replace with actual hook import path
|
|
import { TEMPLATE_HOOK } from "../TEMPLATE_HOOK";
|
|
|
|
// ============================================================
|
|
// Mocks
|
|
// ============================================================
|
|
|
|
// Mock dependencies (if the hook calls APIs, reads stores, etc.)
|
|
// jest.mock("@/controllers/API/api", () => ({
|
|
// __esModule: true,
|
|
// default: {
|
|
// get: jest.fn(),
|
|
// post: jest.fn(),
|
|
// },
|
|
// }));
|
|
|
|
// Mock Zustand store (if the hook reads from a store)
|
|
// import useMyStore from "@/stores/myStore";
|
|
// beforeEach(() => {
|
|
// useMyStore.setState({ items: [], loading: false });
|
|
// });
|
|
|
|
// ============================================================
|
|
// Tests
|
|
// ============================================================
|
|
|
|
describe("TEMPLATE_HOOK", () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// Initial State
|
|
// ----------------------------------------------------------
|
|
|
|
describe("initial state", () => {
|
|
it("should return the correct initial value", () => {
|
|
const { result } = renderHook(() => TEMPLATE_HOOK());
|
|
|
|
// Replace with actual initial state assertions
|
|
// expect(result.current.value).toBe(initialValue);
|
|
// expect(result.current.loading).toBe(false);
|
|
// expect(result.current.error).toBeNull();
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// State Updates
|
|
// ----------------------------------------------------------
|
|
|
|
describe("state updates", () => {
|
|
it("should update state when action is called", () => {
|
|
const { result } = renderHook(() => TEMPLATE_HOOK());
|
|
|
|
act(() => {
|
|
// Call the hook's update function
|
|
// result.current.setValue("new value");
|
|
});
|
|
|
|
// Assert the new state
|
|
// expect(result.current.value).toBe("new value");
|
|
});
|
|
|
|
it("should handle multiple sequential updates", () => {
|
|
const { result } = renderHook(() => TEMPLATE_HOOK());
|
|
|
|
act(() => {
|
|
// result.current.increment();
|
|
// result.current.increment();
|
|
// result.current.increment();
|
|
});
|
|
|
|
// expect(result.current.count).toBe(3);
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// Parameters
|
|
// ----------------------------------------------------------
|
|
|
|
describe("parameters", () => {
|
|
it("should accept and use initial parameters", () => {
|
|
const { result } = renderHook(() =>
|
|
TEMPLATE_HOOK(/* initial params */),
|
|
);
|
|
|
|
// Assert hook uses the provided parameters
|
|
});
|
|
|
|
it("should react to parameter changes on rerender", () => {
|
|
const { result, rerender } = renderHook(
|
|
({ param }) => TEMPLATE_HOOK(param),
|
|
{ initialProps: { param: "initial" } },
|
|
);
|
|
|
|
// Assert initial state
|
|
// expect(result.current.value).toBe("initial");
|
|
|
|
// Rerender with new parameter
|
|
rerender({ param: "updated" });
|
|
|
|
// Assert updated state
|
|
// expect(result.current.value).toBe("updated");
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// Async Behavior
|
|
// ----------------------------------------------------------
|
|
|
|
// describe("async behavior", () => {
|
|
// it("should fetch data on mount", async () => {
|
|
// jest.mocked(api.get).mockResolvedValueOnce({
|
|
// data: { items: [{ id: "1" }] },
|
|
// });
|
|
//
|
|
// const { result } = renderHook(() => TEMPLATE_HOOK());
|
|
//
|
|
// // Initially loading
|
|
// expect(result.current.loading).toBe(true);
|
|
//
|
|
// // Wait for data
|
|
// await waitFor(() => {
|
|
// expect(result.current.loading).toBe(false);
|
|
// });
|
|
//
|
|
// expect(result.current.data).toEqual([{ id: "1" }]);
|
|
// });
|
|
//
|
|
// it("should handle fetch errors", async () => {
|
|
// jest.mocked(api.get).mockRejectedValueOnce(new Error("Failed"));
|
|
//
|
|
// const { result } = renderHook(() => TEMPLATE_HOOK());
|
|
//
|
|
// await waitFor(() => {
|
|
// expect(result.current.error).toBeTruthy();
|
|
// });
|
|
// });
|
|
// });
|
|
|
|
// ----------------------------------------------------------
|
|
// Debounced/Throttled Behavior
|
|
// ----------------------------------------------------------
|
|
|
|
// describe("debounced behavior", () => {
|
|
// beforeEach(() => {
|
|
// jest.useFakeTimers();
|
|
// });
|
|
//
|
|
// afterEach(() => {
|
|
// jest.runOnlyPendingTimers();
|
|
// jest.useRealTimers();
|
|
// });
|
|
//
|
|
// it("should debounce the callback", () => {
|
|
// const callback = jest.fn();
|
|
// const { result } = renderHook(() => TEMPLATE_HOOK(callback, 500));
|
|
//
|
|
// result.current("arg1");
|
|
// result.current("arg2");
|
|
// result.current("arg3");
|
|
//
|
|
// expect(callback).not.toHaveBeenCalled();
|
|
//
|
|
// jest.advanceTimersByTime(500);
|
|
//
|
|
// expect(callback).toHaveBeenCalledTimes(1);
|
|
// expect(callback).toHaveBeenCalledWith("arg3");
|
|
// });
|
|
// });
|
|
|
|
// ----------------------------------------------------------
|
|
// Memoization
|
|
// ----------------------------------------------------------
|
|
|
|
describe("memoization", () => {
|
|
it("should return stable reference when dependencies do not change", () => {
|
|
const { result, rerender } = renderHook(() => TEMPLATE_HOOK());
|
|
|
|
const firstResult = result.current;
|
|
rerender();
|
|
const secondResult = result.current;
|
|
|
|
// For functions/objects that should be memoized:
|
|
// expect(firstResult.handler).toBe(secondResult.handler);
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// Edge Cases
|
|
// ----------------------------------------------------------
|
|
|
|
describe("edge cases", () => {
|
|
it("should handle empty input", () => {
|
|
const { result } = renderHook(() => TEMPLATE_HOOK(/* empty/null */));
|
|
|
|
// Assert graceful handling
|
|
});
|
|
|
|
it("should handle rapid calls", () => {
|
|
const { result } = renderHook(() => TEMPLATE_HOOK());
|
|
|
|
act(() => {
|
|
for (let i = 0; i < 100; i++) {
|
|
// result.current.action();
|
|
}
|
|
});
|
|
|
|
// Assert correct final state
|
|
});
|
|
});
|
|
|
|
// ----------------------------------------------------------
|
|
// Cleanup
|
|
// ----------------------------------------------------------
|
|
|
|
// describe("cleanup", () => {
|
|
// it("should clean up resources on unmount", () => {
|
|
// const removeListenerSpy = jest.fn();
|
|
// jest.spyOn(window, "addEventListener").mockImplementation(() => {});
|
|
// jest.spyOn(window, "removeEventListener").mockImplementation(removeListenerSpy);
|
|
//
|
|
// const { unmount } = renderHook(() => TEMPLATE_HOOK());
|
|
// unmount();
|
|
//
|
|
// expect(removeListenerSpy).toHaveBeenCalled();
|
|
// });
|
|
// });
|
|
});
|