refactor(hook-tests): share subagent hook helpers

This commit is contained in:
Peter Steinberger
2026-03-17 06:43:34 +00:00
parent 52ad686ab5
commit e56e4923bd
3 changed files with 65 additions and 64 deletions

View File

@@ -1,5 +1,9 @@
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/feishu";
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
getRequiredHookHandler,
registerHookHandlersForTest,
} from "../../test-utils/subagent-hooks.js";
import { registerFeishuSubagentHooks } from "./subagent-hooks.js";
import {
__testing as threadBindingTesting,
@@ -12,26 +16,10 @@ const baseConfig = {
};
function registerHandlersForTest(config: Record<string, unknown> = baseConfig) {
const handlers = new Map<string, (event: unknown, ctx: unknown) => unknown>();
const api = {
return registerHookHandlersForTest<OpenClawPluginApi>({
config,
on: (hookName: string, handler: (event: unknown, ctx: unknown) => unknown) => {
handlers.set(hookName, handler);
},
} as unknown as OpenClawPluginApi;
registerFeishuSubagentHooks(api);
return handlers;
}
function getRequiredHandler(
handlers: Map<string, (event: unknown, ctx: unknown) => unknown>,
hookName: string,
): (event: unknown, ctx: unknown) => unknown {
const handler = handlers.get(hookName);
if (!handler) {
throw new Error(`expected ${hookName} hook handler`);
}
return handler;
register: registerFeishuSubagentHooks,
});
}
describe("feishu subagent hook handlers", () => {
@@ -49,7 +37,7 @@ describe("feishu subagent hook handlers", () => {
it("binds a Feishu DM conversation on subagent_spawning", async () => {
const handlers = registerHandlersForTest();
const handler = getRequiredHandler(handlers, "subagent_spawning");
const handler = getRequiredHookHandler(handlers, "subagent_spawning");
createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
const result = await handler(
@@ -70,7 +58,7 @@ describe("feishu subagent hook handlers", () => {
expect(result).toEqual({ status: "ok", threadBindingReady: true });
const deliveryTargetHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const deliveryTargetHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
expect(
deliveryTargetHandler(
{
@@ -96,7 +84,7 @@ describe("feishu subagent hook handlers", () => {
it("preserves the original Feishu DM delivery target", async () => {
const handlers = registerHandlersForTest();
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
const manager = createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
manager.bindConversation({
@@ -134,8 +122,8 @@ describe("feishu subagent hook handlers", () => {
it("binds a Feishu topic conversation and preserves parent context", async () => {
const handlers = registerHandlersForTest();
const spawnHandler = getRequiredHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const spawnHandler = getRequiredHookHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
const result = await spawnHandler(
@@ -183,8 +171,8 @@ describe("feishu subagent hook handlers", () => {
it("uses the requester session binding to preserve sender-scoped topic conversations", async () => {
const handlers = registerHandlersForTest();
const spawnHandler = getRequiredHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const spawnHandler = getRequiredHookHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
const manager = createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
manager.bindConversation({
@@ -252,8 +240,8 @@ describe("feishu subagent hook handlers", () => {
it("prefers requester-matching bindings when multiple child bindings exist", async () => {
const handlers = registerHandlersForTest();
const spawnHandler = getRequiredHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const spawnHandler = getRequiredHookHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
await spawnHandler(
@@ -312,8 +300,8 @@ describe("feishu subagent hook handlers", () => {
it("fails closed when requester-session bindings remain ambiguous for the same topic", async () => {
const handlers = registerHandlersForTest();
const spawnHandler = getRequiredHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const spawnHandler = getRequiredHookHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
const manager = createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
manager.bindConversation({
@@ -375,8 +363,8 @@ describe("feishu subagent hook handlers", () => {
it("fails closed when both topic-level and sender-scoped requester bindings exist", async () => {
const handlers = registerHandlersForTest();
const spawnHandler = getRequiredHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const spawnHandler = getRequiredHookHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
const manager = createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
manager.bindConversation({
@@ -438,9 +426,9 @@ describe("feishu subagent hook handlers", () => {
it("no-ops for non-Feishu channels and non-threaded spawns", async () => {
const handlers = registerHandlersForTest();
const spawnHandler = getRequiredHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const endedHandler = getRequiredHandler(handlers, "subagent_ended");
const spawnHandler = getRequiredHookHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
const endedHandler = getRequiredHookHandler(handlers, "subagent_ended");
await expect(
spawnHandler(
@@ -506,7 +494,7 @@ describe("feishu subagent hook handlers", () => {
});
it("returns an error for unsupported non-topic Feishu group conversations", async () => {
const handler = getRequiredHandler(registerHandlersForTest(), "subagent_spawning");
const handler = getRequiredHookHandler(registerHandlersForTest(), "subagent_spawning");
createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
await expect(
@@ -532,9 +520,9 @@ describe("feishu subagent hook handlers", () => {
it("unbinds Feishu bindings on subagent_ended", async () => {
const handlers = registerHandlersForTest();
const spawnHandler = getRequiredHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const endedHandler = getRequiredHandler(handlers, "subagent_ended");
const spawnHandler = getRequiredHookHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
const endedHandler = getRequiredHookHandler(handlers, "subagent_ended");
createFeishuThreadBindingManager({ cfg: baseConfig as any, accountId: "work" });
await spawnHandler(
@@ -581,8 +569,8 @@ describe("feishu subagent hook handlers", () => {
it("fails closed when the Feishu monitor-owned binding manager is unavailable", async () => {
const handlers = registerHandlersForTest();
const spawnHandler = getRequiredHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHandler(handlers, "subagent_delivery_target");
const spawnHandler = getRequiredHookHandler(handlers, "subagent_spawning");
const deliveryHandler = getRequiredHookHandler(handlers, "subagent_delivery_target");
await expect(
spawnHandler(