Files
diegosouzapw--omniroute/tests/unit/plugins-hook-payload-chaining-3286.test.ts
2026-07-13 13:39:12 +08:00

87 lines
2.4 KiB
TypeScript

/**
* tests/unit/plugins-hook-payload-chaining-3286.test.ts
*
* Regression for #3286 — emitHookBlocking must CHAIN the payload between
* handlers. Before the fix, every handler received the original static
* `payload`, so plugin B could not observe plugin A's `body`/`metadata`
* mutations (the accumulated mergedBody/mergedMetadata were only used for the
* final return value, never fed forward to the next handler).
*/
import test from "node:test";
import assert from "node:assert/strict";
import {
registerHook,
emitHookBlocking,
resetHooks,
} from "../../src/lib/plugins/hooks.ts";
test.afterEach(() => {
resetHooks();
});
test("emitHookBlocking feeds each handler the body mutated by previous handlers", async () => {
const seenByB: unknown[] = [];
// Plugin A: rewrites the body.
registerHook(
"onRequest",
"plugin-a",
(p: unknown) => {
const ctx = p as { body?: { value?: number } };
return { body: { value: (ctx.body?.value ?? 0) + 1 } };
},
10
);
// Plugin B (lower priority → runs after A): records what body it received.
registerHook(
"onRequest",
"plugin-b",
(p: unknown) => {
const ctx = p as { body?: { value?: number } };
seenByB.push(ctx.body);
return { body: { value: (ctx.body?.value ?? 0) + 1 } };
},
20
);
const result = await emitHookBlocking("onRequest", { body: { value: 0 } });
// Plugin B must have seen plugin A's mutation ({value:1}), not the original {value:0}.
assert.deepEqual(seenByB, [{ value: 1 }]);
// Final merged body reflects BOTH handlers: 0 → 1 (A) → 2 (B).
assert.deepEqual((result as { body?: { value?: number } }).body, { value: 2 });
});
test("emitHookBlocking chains metadata across handlers", async () => {
let metadataSeenByB: Record<string, unknown> | undefined;
registerHook(
"onRequest",
"meta-a",
() => ({ metadata: { a: true } }),
10
);
registerHook(
"onRequest",
"meta-b",
(p: unknown) => {
metadataSeenByB = (p as { metadata?: Record<string, unknown> }).metadata;
return { metadata: { b: true } };
},
20
);
const result = await emitHookBlocking("onRequest", { body: {}, metadata: {} });
// Plugin B sees plugin A's metadata.
assert.equal(metadataSeenByB?.a, true);
// Final metadata carries both.
const meta = (result as { metadata?: Record<string, unknown> }).metadata;
assert.equal(meta?.a, true);
assert.equal(meta?.b, true);
});