mirror of https://github.com/openclaw/openclaw.git
test: share startup account lifecycle helpers
This commit is contained in:
parent
b61bc4948e
commit
0acd1f63fc
|
|
@ -1,6 +1,10 @@
|
|||
import type { ChannelAccountSnapshot } from "openclaw/plugin-sdk/googlechat";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStartAccountContext } from "../../test-utils/start-account-context.js";
|
||||
import {
|
||||
abortStartedAccount,
|
||||
expectPendingUntilAbort,
|
||||
startAccountAndTrackLifecycle,
|
||||
} from "../../test-utils/start-account-lifecycle.js";
|
||||
import type { ResolvedGoogleChatAccount } from "./accounts.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
|
|
@ -39,29 +43,25 @@ describe("googlechatPlugin gateway.startAccount", () => {
|
|||
},
|
||||
};
|
||||
|
||||
const patches: ChannelAccountSnapshot[] = [];
|
||||
const abort = new AbortController();
|
||||
const task = googlechatPlugin.gateway!.startAccount!(
|
||||
createStartAccountContext({
|
||||
account,
|
||||
abortSignal: abort.signal,
|
||||
statusPatchSink: (next) => patches.push({ ...next }),
|
||||
}),
|
||||
);
|
||||
let settled = false;
|
||||
void task.then(() => {
|
||||
settled = true;
|
||||
const { abort, patches, task, isSettled } = startAccountAndTrackLifecycle({
|
||||
startAccount: googlechatPlugin.gateway!.startAccount!,
|
||||
account,
|
||||
});
|
||||
await vi.waitFor(() => {
|
||||
expect(hoisted.startGoogleChatMonitor).toHaveBeenCalledOnce();
|
||||
await expectPendingUntilAbort({
|
||||
waitForStarted: () =>
|
||||
vi.waitFor(() => {
|
||||
expect(hoisted.startGoogleChatMonitor).toHaveBeenCalledOnce();
|
||||
}),
|
||||
isSettled,
|
||||
abort,
|
||||
task,
|
||||
assertBeforeAbort: () => {
|
||||
expect(unregister).not.toHaveBeenCalled();
|
||||
},
|
||||
assertAfterAbort: () => {
|
||||
expect(unregister).toHaveBeenCalledOnce();
|
||||
},
|
||||
});
|
||||
expect(settled).toBe(false);
|
||||
expect(unregister).not.toHaveBeenCalled();
|
||||
|
||||
abort.abort();
|
||||
await task;
|
||||
|
||||
expect(unregister).toHaveBeenCalledOnce();
|
||||
expect(patches.some((entry) => entry.running === true)).toBe(true);
|
||||
expect(patches.some((entry) => entry.running === false)).toBe(true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStartAccountContext } from "../../test-utils/start-account-context.js";
|
||||
import {
|
||||
expectStopPendingUntilAbort,
|
||||
startAccountAndTrackLifecycle,
|
||||
} from "../../test-utils/start-account-lifecycle.js";
|
||||
import type { ResolvedIrcAccount } from "./accounts.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
|
|
@ -41,27 +44,20 @@ describe("ircPlugin gateway.startAccount", () => {
|
|||
config: {} as ResolvedIrcAccount["config"],
|
||||
};
|
||||
|
||||
const abort = new AbortController();
|
||||
const task = ircPlugin.gateway!.startAccount!(
|
||||
createStartAccountContext({
|
||||
account,
|
||||
abortSignal: abort.signal,
|
||||
}),
|
||||
);
|
||||
let settled = false;
|
||||
void task.then(() => {
|
||||
settled = true;
|
||||
const { abort, task, isSettled } = startAccountAndTrackLifecycle({
|
||||
startAccount: ircPlugin.gateway!.startAccount!,
|
||||
account,
|
||||
});
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(hoisted.monitorIrcProvider).toHaveBeenCalledOnce();
|
||||
await expectStopPendingUntilAbort({
|
||||
waitForStarted: () =>
|
||||
vi.waitFor(() => {
|
||||
expect(hoisted.monitorIrcProvider).toHaveBeenCalledOnce();
|
||||
}),
|
||||
isSettled,
|
||||
abort,
|
||||
task,
|
||||
stop,
|
||||
});
|
||||
expect(settled).toBe(false);
|
||||
expect(stop).not.toHaveBeenCalled();
|
||||
|
||||
abort.abort();
|
||||
await task;
|
||||
|
||||
expect(stop).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStartAccountContext } from "../../test-utils/start-account-context.js";
|
||||
import {
|
||||
expectStopPendingUntilAbort,
|
||||
startAccountAndTrackLifecycle,
|
||||
} from "../../test-utils/start-account-lifecycle.js";
|
||||
import type { ResolvedNextcloudTalkAccount } from "./accounts.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
|
|
@ -40,28 +44,20 @@ describe("nextcloudTalkPlugin gateway.startAccount", () => {
|
|||
it("keeps startAccount pending until abort, then stops the monitor", async () => {
|
||||
const stop = vi.fn();
|
||||
hoisted.monitorNextcloudTalkProvider.mockResolvedValue({ stop });
|
||||
const abort = new AbortController();
|
||||
|
||||
const task = nextcloudTalkPlugin.gateway!.startAccount!(
|
||||
createStartAccountContext({
|
||||
account: buildAccount(),
|
||||
abortSignal: abort.signal,
|
||||
}),
|
||||
);
|
||||
let settled = false;
|
||||
void task.then(() => {
|
||||
settled = true;
|
||||
const { abort, task, isSettled } = startAccountAndTrackLifecycle({
|
||||
startAccount: nextcloudTalkPlugin.gateway!.startAccount!,
|
||||
account: buildAccount(),
|
||||
});
|
||||
await vi.waitFor(() => {
|
||||
expect(hoisted.monitorNextcloudTalkProvider).toHaveBeenCalledOnce();
|
||||
await expectStopPendingUntilAbort({
|
||||
waitForStarted: () =>
|
||||
vi.waitFor(() => {
|
||||
expect(hoisted.monitorNextcloudTalkProvider).toHaveBeenCalledOnce();
|
||||
}),
|
||||
isSettled,
|
||||
abort,
|
||||
task,
|
||||
stop,
|
||||
});
|
||||
expect(settled).toBe(false);
|
||||
expect(stop).not.toHaveBeenCalled();
|
||||
|
||||
abort.abort();
|
||||
await task;
|
||||
|
||||
expect(stop).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("stops immediately when startAccount receives an already-aborted signal", async () => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
import type { ChannelAccountSnapshot, ChannelGatewayContext } from "openclaw/plugin-sdk/test-utils";
|
||||
import { expect, vi } from "vitest";
|
||||
import { createStartAccountContext } from "./start-account-context.js";
|
||||
|
||||
export function startAccountAndTrackLifecycle<TAccount extends { accountId: string }>(params: {
|
||||
startAccount: (ctx: ChannelGatewayContext<TAccount>) => Promise<unknown>;
|
||||
account: TAccount;
|
||||
}) {
|
||||
const patches: ChannelAccountSnapshot[] = [];
|
||||
const abort = new AbortController();
|
||||
const task = params.startAccount(
|
||||
createStartAccountContext({
|
||||
account: params.account,
|
||||
abortSignal: abort.signal,
|
||||
statusPatchSink: (next) => patches.push({ ...next }),
|
||||
}),
|
||||
);
|
||||
let settled = false;
|
||||
void task.then(() => {
|
||||
settled = true;
|
||||
});
|
||||
return {
|
||||
abort,
|
||||
patches,
|
||||
task,
|
||||
isSettled: () => settled,
|
||||
};
|
||||
}
|
||||
|
||||
export async function abortStartedAccount(params: {
|
||||
abort: AbortController;
|
||||
task: Promise<unknown>;
|
||||
}) {
|
||||
params.abort.abort();
|
||||
await params.task;
|
||||
}
|
||||
|
||||
export async function expectPendingUntilAbort(params: {
|
||||
waitForStarted: () => Promise<void>;
|
||||
isSettled: () => boolean;
|
||||
abort: AbortController;
|
||||
task: Promise<unknown>;
|
||||
assertBeforeAbort?: () => void;
|
||||
assertAfterAbort?: () => void;
|
||||
}) {
|
||||
await params.waitForStarted();
|
||||
expect(params.isSettled()).toBe(false);
|
||||
params.assertBeforeAbort?.();
|
||||
await abortStartedAccount({ abort: params.abort, task: params.task });
|
||||
params.assertAfterAbort?.();
|
||||
}
|
||||
|
||||
export async function expectStopPendingUntilAbort(params: {
|
||||
waitForStarted: () => Promise<void>;
|
||||
isSettled: () => boolean;
|
||||
abort: AbortController;
|
||||
task: Promise<unknown>;
|
||||
stop: ReturnType<typeof vi.fn>;
|
||||
}) {
|
||||
await expectPendingUntilAbort({
|
||||
waitForStarted: params.waitForStarted,
|
||||
isSettled: params.isSettled,
|
||||
abort: params.abort,
|
||||
task: params.task,
|
||||
assertBeforeAbort: () => {
|
||||
expect(params.stop).not.toHaveBeenCalled();
|
||||
},
|
||||
assertAfterAbort: () => {
|
||||
expect(params.stop).toHaveBeenCalledOnce();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
import type { ChannelAccountSnapshot } from "openclaw/plugin-sdk/zalo";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStartAccountContext } from "../../test-utils/start-account-context.js";
|
||||
import {
|
||||
expectPendingUntilAbort,
|
||||
startAccountAndTrackLifecycle,
|
||||
} from "../../test-utils/start-account-lifecycle.js";
|
||||
import type { ResolvedZaloAccount } from "./accounts.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
|
|
@ -57,37 +60,28 @@ describe("zaloPlugin gateway.startAccount", () => {
|
|||
}),
|
||||
);
|
||||
|
||||
const patches: ChannelAccountSnapshot[] = [];
|
||||
const abort = new AbortController();
|
||||
const task = zaloPlugin.gateway!.startAccount!(
|
||||
createStartAccountContext({
|
||||
account: buildAccount(),
|
||||
abortSignal: abort.signal,
|
||||
statusPatchSink: (next) => patches.push({ ...next }),
|
||||
}),
|
||||
);
|
||||
|
||||
let settled = false;
|
||||
void task.then(() => {
|
||||
settled = true;
|
||||
const { abort, patches, task, isSettled } = startAccountAndTrackLifecycle({
|
||||
startAccount: zaloPlugin.gateway!.startAccount!,
|
||||
account: buildAccount(),
|
||||
});
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(hoisted.probeZalo).toHaveBeenCalledOnce();
|
||||
expect(hoisted.monitorZaloProvider).toHaveBeenCalledOnce();
|
||||
await expectPendingUntilAbort({
|
||||
waitForStarted: () =>
|
||||
vi.waitFor(() => {
|
||||
expect(hoisted.probeZalo).toHaveBeenCalledOnce();
|
||||
expect(hoisted.monitorZaloProvider).toHaveBeenCalledOnce();
|
||||
}),
|
||||
isSettled,
|
||||
abort,
|
||||
task,
|
||||
});
|
||||
|
||||
expect(settled).toBe(false);
|
||||
expect(patches).toContainEqual(
|
||||
expect.objectContaining({
|
||||
accountId: "default",
|
||||
}),
|
||||
);
|
||||
|
||||
abort.abort();
|
||||
await task;
|
||||
|
||||
expect(settled).toBe(true);
|
||||
expect(isSettled()).toBe(true);
|
||||
expect(hoisted.monitorZaloProvider).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
token: "test-token",
|
||||
|
|
|
|||
Loading…
Reference in New Issue