

























1+import {
2+createStartAccountContext,
3+expectStopPendingUntilAbort,
4+startAccountAndTrackLifecycle,
5+waitForStartedMocks,
6+} from "openclaw/plugin-sdk/channel-test-helpers";
7+import { afterEach, describe, expect, it, vi } from "vitest";
8+import { getActiveNostrBuses, startNostrGatewayAccount } from "./gateway.js";
9+import { buildResolvedNostrAccount } from "./test-fixtures.js";
10+11+const mocks = vi.hoisted(() => ({
12+startNostrBus: vi.fn(),
13+}));
14+15+vi.mock("./nostr-bus.js", () => ({
16+DEFAULT_RELAYS: ["wss://relay.example.com"],
17+startNostrBus: mocks.startNostrBus,
18+}));
19+20+function createMockBus() {
21+return {
22+sendDm: vi.fn(async () => {}),
23+close: vi.fn(),
24+getMetrics: vi.fn(() => ({ counters: {} })),
25+publishProfile: vi.fn(),
26+getProfileState: vi.fn(async () => null),
27+};
28+}
29+30+describe("nostr gateway lifecycle", () => {
31+afterEach(() => {
32+mocks.startNostrBus.mockReset();
33+});
34+35+it("keeps startAccount pending until abort, then closes the bus", async () => {
36+const bus = createMockBus();
37+mocks.startNostrBus.mockResolvedValueOnce(bus as never);
38+39+const { abort, task, isSettled } = startAccountAndTrackLifecycle({
40+startAccount: startNostrGatewayAccount,
41+account: buildResolvedNostrAccount(),
42+});
43+44+await expectStopPendingUntilAbort({
45+waitForStarted: waitForStartedMocks(mocks.startNostrBus),
46+ isSettled,
47+ abort,
48+ task,
49+stop: bus.close,
50+});
51+});
52+53+it("keeps the active bus registered while pending and removes it after abort", async () => {
54+const bus = createMockBus();
55+mocks.startNostrBus.mockResolvedValueOnce(bus as never);
56+57+const { abort, task, isSettled } = startAccountAndTrackLifecycle({
58+startAccount: startNostrGatewayAccount,
59+account: buildResolvedNostrAccount(),
60+});
61+62+await vi.waitFor(() => {
63+expect(getActiveNostrBuses().get("default")).toBe(bus);
64+});
65+expect(isSettled()).toBe(false);
66+67+abort.abort();
68+await task;
69+70+expect(bus.close).toHaveBeenCalledOnce();
71+expect(getActiveNostrBuses().has("default")).toBe(false);
72+});
73+74+it("stops immediately when startAccount receives an already-aborted signal", async () => {
75+const bus = createMockBus();
76+mocks.startNostrBus.mockResolvedValueOnce(bus as never);
77+const abort = new AbortController();
78+abort.abort();
79+80+await startNostrGatewayAccount(
81+createStartAccountContext({
82+account: buildResolvedNostrAccount(),
83+abortSignal: abort.signal,
84+}),
85+);
86+87+expect(mocks.startNostrBus).toHaveBeenCalledOnce();
88+expect(bus.close).toHaveBeenCalledOnce();
89+});
90+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。