mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-13 10:11:20 +00:00
Merged via squash.
Prepared head SHA: b7c20a7398
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
227 lines
5.7 KiB
TypeScript
227 lines
5.7 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import { createRuntimeChannel } from "./runtime-channel.js";
|
|
|
|
describe("runtimeContexts", () => {
|
|
it("registers, resolves, watches, and unregisters contexts", () => {
|
|
const channel = createRuntimeChannel();
|
|
const onEvent = vi.fn();
|
|
const unsubscribe = channel.runtimeContexts.watch({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
onEvent,
|
|
});
|
|
|
|
const lease = channel.runtimeContexts.register({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
context: { client: "ok" },
|
|
});
|
|
|
|
expect(
|
|
channel.runtimeContexts.get<{ client: string }>({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
}),
|
|
).toEqual({ client: "ok" });
|
|
expect(onEvent).toHaveBeenCalledWith({
|
|
type: "registered",
|
|
key: {
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
},
|
|
context: { client: "ok" },
|
|
});
|
|
|
|
lease.dispose();
|
|
|
|
expect(
|
|
channel.runtimeContexts.get({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
}),
|
|
).toBeUndefined();
|
|
expect(onEvent).toHaveBeenLastCalledWith({
|
|
type: "unregistered",
|
|
key: {
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
},
|
|
});
|
|
|
|
unsubscribe();
|
|
});
|
|
|
|
it("auto-disposes registrations when the abort signal fires", () => {
|
|
const channel = createRuntimeChannel();
|
|
const controller = new AbortController();
|
|
const lease = channel.runtimeContexts.register({
|
|
channelId: "telegram",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
context: { token: "abc" },
|
|
abortSignal: controller.signal,
|
|
});
|
|
|
|
controller.abort();
|
|
|
|
expect(
|
|
channel.runtimeContexts.get({
|
|
channelId: "telegram",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
}),
|
|
).toBeUndefined();
|
|
lease.dispose();
|
|
});
|
|
|
|
it("does not register contexts when the abort signal is already aborted", () => {
|
|
const channel = createRuntimeChannel();
|
|
const onEvent = vi.fn();
|
|
const controller = new AbortController();
|
|
controller.abort();
|
|
channel.runtimeContexts.watch({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
onEvent,
|
|
});
|
|
|
|
const lease = channel.runtimeContexts.register({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
context: { client: "stale" },
|
|
abortSignal: controller.signal,
|
|
});
|
|
|
|
expect(
|
|
channel.runtimeContexts.get({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
}),
|
|
).toBeUndefined();
|
|
expect(onEvent).not.toHaveBeenCalled();
|
|
lease.dispose();
|
|
});
|
|
|
|
it("isolates watcher exceptions so registration and disposal still complete", () => {
|
|
const channel = createRuntimeChannel();
|
|
const badWatcher = vi.fn((event) => {
|
|
throw new Error(`boom:${event.type}`);
|
|
});
|
|
const goodWatcher = vi.fn();
|
|
|
|
channel.runtimeContexts.watch({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
onEvent: badWatcher,
|
|
});
|
|
channel.runtimeContexts.watch({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
onEvent: goodWatcher,
|
|
});
|
|
|
|
const lease = channel.runtimeContexts.register({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
context: { client: "ok" },
|
|
});
|
|
|
|
expect(
|
|
channel.runtimeContexts.get({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
}),
|
|
).toEqual({ client: "ok" });
|
|
expect(badWatcher).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
type: "registered",
|
|
}),
|
|
);
|
|
expect(goodWatcher).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
type: "registered",
|
|
}),
|
|
);
|
|
|
|
lease.dispose();
|
|
|
|
expect(
|
|
channel.runtimeContexts.get({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
}),
|
|
).toBeUndefined();
|
|
expect(badWatcher).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
type: "unregistered",
|
|
}),
|
|
);
|
|
expect(goodWatcher).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
type: "unregistered",
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("auto-disposes when a watcher aborts during the registered event", () => {
|
|
const channel = createRuntimeChannel();
|
|
const controller = new AbortController();
|
|
const onEvent = vi.fn((event) => {
|
|
if (event.type === "registered") {
|
|
controller.abort();
|
|
}
|
|
});
|
|
|
|
channel.runtimeContexts.watch({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
onEvent,
|
|
});
|
|
|
|
const lease = channel.runtimeContexts.register({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
context: { client: "ok" },
|
|
abortSignal: controller.signal,
|
|
});
|
|
|
|
expect(
|
|
channel.runtimeContexts.get({
|
|
channelId: "matrix",
|
|
accountId: "default",
|
|
capability: "approval.native",
|
|
}),
|
|
).toBeUndefined();
|
|
expect(onEvent).toHaveBeenNthCalledWith(
|
|
1,
|
|
expect.objectContaining({
|
|
type: "registered",
|
|
}),
|
|
);
|
|
expect(onEvent).toHaveBeenNthCalledWith(
|
|
2,
|
|
expect.objectContaining({
|
|
type: "unregistered",
|
|
}),
|
|
);
|
|
|
|
lease.dispose();
|
|
});
|
|
});
|