Download __tests__/api/hooks-service.test.ts from SaylorTwift/openhands: direct link, hf CLI and curl.
- Browser
- Download file 4.23 kB
-
https://huggingface.co/SaylorTwift/openhands/resolve/main/__tests__/api/hooks-service.test.ts
- Command line
-
hf download hf://SaylorTwift/openhands/__tests__/api/hooks-service.test.ts
-
curl -L -o hooks-service.test.ts https://huggingface.co/SaylorTwift/openhands/resolve/main/__tests__/api/hooks-service.test.ts
4.23 kB
| import { HooksClient } from "@openhands/typescript-client/clients"; | |
| import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; | |
| import { | |
| __resetActiveStoreForTests, | |
| setActiveSelection, | |
| setRegisteredBackends, | |
| } from "#/api/backend-registry/active-store"; | |
| import { DEFAULT_WORKING_DIR } from "#/api/agent-server-config"; | |
| import type { Backend } from "#/api/backend-registry/types"; | |
| const { mockLoadHooks } = vi.hoisted(() => ({ | |
| mockLoadHooks: vi.fn(), | |
| })); | |
| vi.mock("@openhands/typescript-client/clients", () => ({ | |
| HooksClient: vi.fn(function HooksClientMock() { | |
| return { loadHooks: mockLoadHooks }; | |
| }), | |
| })); | |
| import HooksService from "#/api/hooks-service"; | |
| const localBackend: Backend = { | |
| id: "local", | |
| name: "Local", | |
| host: "http://127.0.0.1:8000", | |
| apiKey: "", | |
| kind: "local", | |
| }; | |
| const cloudBackend: Backend = { | |
| id: "cloud", | |
| name: "Cloud", | |
| host: "https://openhands.dev", | |
| apiKey: "cloud-key", | |
| kind: "cloud", | |
| }; | |
| beforeEach(() => { | |
| window.localStorage.clear(); | |
| __resetActiveStoreForTests(); | |
| setRegisteredBackends([localBackend]); | |
| setActiveSelection({ backendId: localBackend.id }); | |
| mockLoadHooks.mockReset(); | |
| vi.mocked(HooksClient).mockClear(); | |
| }); | |
| afterEach(() => { | |
| __resetActiveStoreForTests(); | |
| }); | |
| describe("HooksService.loadWorkspaceHooks", () => { | |
| it("loads workspace hooks from the agent-server when present", async () => { | |
| const mockHookConfig = { | |
| session_start: [ | |
| { | |
| matcher: "*", | |
| hooks: [{ command: "cat AGENTS.md", type: "command" }], | |
| }, | |
| ], | |
| pre_tool_use: [], | |
| post_tool_use: [], | |
| user_prompt_submit: [], | |
| session_end: [], | |
| stop: [], | |
| }; | |
| mockLoadHooks.mockResolvedValue({ hook_config: mockHookConfig }); | |
| const result = await HooksService.loadWorkspaceHooks( | |
| "/workspace/test-project", | |
| ); | |
| expect(mockLoadHooks).toHaveBeenCalledTimes(1); | |
| expect(mockLoadHooks).toHaveBeenCalledWith({ | |
| project_dir: "/workspace/test-project", | |
| }); | |
| expect(result).toEqual(mockHookConfig); | |
| }); | |
| it("defaults project_dir to getAgentServerWorkingDir() when omitted", async () => { | |
| mockLoadHooks.mockResolvedValue({ hook_config: null }); | |
| const result = await HooksService.loadWorkspaceHooks(); | |
| expect(mockLoadHooks).toHaveBeenCalledTimes(1); | |
| expect(mockLoadHooks).toHaveBeenCalledWith({ | |
| project_dir: DEFAULT_WORKING_DIR, | |
| }); | |
| expect(result).toBeNull(); | |
| }); | |
| it("gracefully returns null and warns when the agent-server throws an error", async () => { | |
| const warn = vi.spyOn(console, "warn").mockImplementation(() => {}); | |
| mockLoadHooks.mockRejectedValue(new Error("500 Internal Server Error")); | |
| const result = await HooksService.loadWorkspaceHooks("/workspace/broken"); | |
| expect(result).toBeNull(); | |
| expect(warn).toHaveBeenCalled(); | |
| warn.mockRestore(); | |
| }); | |
| // The lookup is on the launch critical path; the SDK's 60s default would | |
| // stall a launch against a wedged agent-server. | |
| it("bounds the request so a wedged agent-server cannot stall a launch", async () => { | |
| mockLoadHooks.mockResolvedValue({ hook_config: null }); | |
| await HooksService.loadWorkspaceHooks("/workspace/test-project"); | |
| const [clientOptions] = vi.mocked(HooksClient).mock.calls[0]; | |
| expect(clientOptions.timeout).toBeLessThanOrEqual(10_000); | |
| }); | |
| it("returns null immediately for cloud backend without calling HooksClient", async () => { | |
| setRegisteredBackends([cloudBackend]); | |
| setActiveSelection({ backendId: cloudBackend.id }); | |
| const result = await HooksService.loadWorkspaceHooks("/workspace/cloud"); | |
| expect(mockLoadHooks).not.toHaveBeenCalled(); | |
| expect(result).toBeNull(); | |
| }); | |
| it("returns null for unseeded/empty registry (NO_BACKEND sentinel) without calling HooksClient", async () => { | |
| // Simulate a fresh install with no backends registered. | |
| // setRegisteredBackends([]) computes the snapshot with NO_BACKEND, | |
| // so getEffectiveLocalBackend() returns null. | |
| setRegisteredBackends([]); | |
| const result = await HooksService.loadWorkspaceHooks("/workspace/test"); | |
| expect(mockLoadHooks).not.toHaveBeenCalled(); | |
| expect(result).toBeNull(); | |
| }); | |
| }); | |