mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 07:07:27 +00:00
test: dedupe telegram draft stream setup and extend state-dir env coverage
This commit is contained in:
@@ -2,6 +2,8 @@ import type { Bot } from "grammy";
|
|||||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { createTelegramDraftStream } from "./draft-stream.js";
|
import { createTelegramDraftStream } from "./draft-stream.js";
|
||||||
|
|
||||||
|
type TelegramDraftStreamParams = Parameters<typeof createTelegramDraftStream>[0];
|
||||||
|
|
||||||
function createMockDraftApi(sendMessageImpl?: () => Promise<{ message_id: number }>) {
|
function createMockDraftApi(sendMessageImpl?: () => Promise<{ message_id: number }>) {
|
||||||
return {
|
return {
|
||||||
sendMessage: vi.fn(sendMessageImpl ?? (async () => ({ message_id: 17 }))),
|
sendMessage: vi.fn(sendMessageImpl ?? (async () => ({ message_id: 17 }))),
|
||||||
@@ -17,11 +19,18 @@ function createForumDraftStream(api: ReturnType<typeof createMockDraftApi>) {
|
|||||||
function createThreadedDraftStream(
|
function createThreadedDraftStream(
|
||||||
api: ReturnType<typeof createMockDraftApi>,
|
api: ReturnType<typeof createMockDraftApi>,
|
||||||
thread: { id: number; scope: "forum" | "dm" },
|
thread: { id: number; scope: "forum" | "dm" },
|
||||||
|
) {
|
||||||
|
return createDraftStream(api, { thread });
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDraftStream(
|
||||||
|
api: ReturnType<typeof createMockDraftApi>,
|
||||||
|
overrides: Omit<Partial<TelegramDraftStreamParams>, "api" | "chatId"> = {},
|
||||||
) {
|
) {
|
||||||
return createTelegramDraftStream({
|
return createTelegramDraftStream({
|
||||||
api: api as unknown as Bot["api"],
|
api: api as unknown as Bot["api"],
|
||||||
chatId: 123,
|
chatId: 123,
|
||||||
thread,
|
...overrides,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +43,18 @@ async function expectInitialForumSend(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createForceNewMessageHarness(params: { throttleMs?: number } = {}) {
|
||||||
|
const api = createMockDraftApi();
|
||||||
|
api.sendMessage
|
||||||
|
.mockResolvedValueOnce({ message_id: 17 })
|
||||||
|
.mockResolvedValueOnce({ message_id: 42 });
|
||||||
|
const stream = createDraftStream(
|
||||||
|
api,
|
||||||
|
params.throttleMs != null ? { throttleMs: params.throttleMs } : {},
|
||||||
|
);
|
||||||
|
return { api, stream };
|
||||||
|
}
|
||||||
|
|
||||||
describe("createTelegramDraftStream", () => {
|
describe("createTelegramDraftStream", () => {
|
||||||
it("sends stream preview message with message_thread_id when provided", async () => {
|
it("sends stream preview message with message_thread_id when provided", async () => {
|
||||||
const api = createMockDraftApi();
|
const api = createMockDraftApi();
|
||||||
@@ -100,18 +121,7 @@ describe("createTelegramDraftStream", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("creates new message after forceNewMessage is called", async () => {
|
it("creates new message after forceNewMessage is called", async () => {
|
||||||
const api = {
|
const { api, stream } = createForceNewMessageHarness();
|
||||||
sendMessage: vi
|
|
||||||
.fn()
|
|
||||||
.mockResolvedValueOnce({ message_id: 17 })
|
|
||||||
.mockResolvedValueOnce({ message_id: 42 }),
|
|
||||||
editMessageText: vi.fn().mockResolvedValue(true),
|
|
||||||
deleteMessage: vi.fn().mockResolvedValue(true),
|
|
||||||
};
|
|
||||||
const stream = createTelegramDraftStream({
|
|
||||||
api: api as unknown as Bot["api"],
|
|
||||||
chatId: 123,
|
|
||||||
});
|
|
||||||
|
|
||||||
// First message
|
// First message
|
||||||
stream.update("Hello");
|
stream.update("Hello");
|
||||||
@@ -136,19 +146,7 @@ describe("createTelegramDraftStream", () => {
|
|||||||
it("sends first update immediately after forceNewMessage within throttle window", async () => {
|
it("sends first update immediately after forceNewMessage within throttle window", async () => {
|
||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
try {
|
try {
|
||||||
const api = {
|
const { api, stream } = createForceNewMessageHarness({ throttleMs: 1000 });
|
||||||
sendMessage: vi
|
|
||||||
.fn()
|
|
||||||
.mockResolvedValueOnce({ message_id: 17 })
|
|
||||||
.mockResolvedValueOnce({ message_id: 42 }),
|
|
||||||
editMessageText: vi.fn().mockResolvedValue(true),
|
|
||||||
deleteMessage: vi.fn().mockResolvedValue(true),
|
|
||||||
};
|
|
||||||
const stream = createTelegramDraftStream({
|
|
||||||
api: api as unknown as Bot["api"],
|
|
||||||
chatId: 123,
|
|
||||||
throttleMs: 1000,
|
|
||||||
});
|
|
||||||
|
|
||||||
stream.update("Hello");
|
stream.update("Hello");
|
||||||
await vi.waitFor(() => expect(api.sendMessage).toHaveBeenCalledTimes(1));
|
await vi.waitFor(() => expect(api.sendMessage).toHaveBeenCalledTimes(1));
|
||||||
|
|||||||
@@ -29,6 +29,16 @@ async function expectPathMissing(filePath: string) {
|
|||||||
await expect(fs.stat(filePath)).rejects.toThrow();
|
await expect(fs.stat(filePath)).rejects.toThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function expectStateDirEnvRestored(params: {
|
||||||
|
prev: EnvSnapshot;
|
||||||
|
capturedStateDir: string;
|
||||||
|
capturedTempRoot: string;
|
||||||
|
}) {
|
||||||
|
expectStateDirVars(params.prev);
|
||||||
|
await expectPathMissing(params.capturedStateDir);
|
||||||
|
await expectPathMissing(params.capturedTempRoot);
|
||||||
|
}
|
||||||
|
|
||||||
describe("state-dir-env helpers", () => {
|
describe("state-dir-env helpers", () => {
|
||||||
it("set/snapshot/restore round-trips OPENCLAW_STATE_DIR", () => {
|
it("set/snapshot/restore round-trips OPENCLAW_STATE_DIR", () => {
|
||||||
const prev = snapshotCurrentStateDirVars();
|
const prev = snapshotCurrentStateDirVars();
|
||||||
@@ -55,9 +65,7 @@ describe("state-dir-env helpers", () => {
|
|||||||
await fs.writeFile(path.join(stateDir, "probe.txt"), "ok", "utf8");
|
await fs.writeFile(path.join(stateDir, "probe.txt"), "ok", "utf8");
|
||||||
});
|
});
|
||||||
|
|
||||||
expectStateDirVars(prev);
|
await expectStateDirEnvRestored({ prev, capturedStateDir, capturedTempRoot });
|
||||||
await expectPathMissing(capturedStateDir);
|
|
||||||
await expectPathMissing(capturedTempRoot);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("withStateDirEnv restores env and cleans temp root when callback throws", async () => {
|
it("withStateDirEnv restores env and cleans temp root when callback throws", async () => {
|
||||||
@@ -73,8 +81,28 @@ describe("state-dir-env helpers", () => {
|
|||||||
}),
|
}),
|
||||||
).rejects.toThrow("boom");
|
).rejects.toThrow("boom");
|
||||||
|
|
||||||
expectStateDirVars(prev);
|
await expectStateDirEnvRestored({ prev, capturedStateDir, capturedTempRoot });
|
||||||
await expectPathMissing(capturedStateDir);
|
});
|
||||||
await expectPathMissing(capturedTempRoot);
|
|
||||||
|
it("withStateDirEnv restores both env vars when legacy var was previously set", async () => {
|
||||||
|
const testSnapshot = snapshotStateDirEnv();
|
||||||
|
process.env.OPENCLAW_STATE_DIR = "/tmp/original-openclaw";
|
||||||
|
process.env.CLAWDBOT_STATE_DIR = "/tmp/original-legacy";
|
||||||
|
const prev = snapshotCurrentStateDirVars();
|
||||||
|
|
||||||
|
let capturedTempRoot = "";
|
||||||
|
let capturedStateDir = "";
|
||||||
|
try {
|
||||||
|
await withStateDirEnv("openclaw-state-dir-env-", async ({ tempRoot, stateDir }) => {
|
||||||
|
capturedTempRoot = tempRoot;
|
||||||
|
capturedStateDir = stateDir;
|
||||||
|
expect(process.env.OPENCLAW_STATE_DIR).toBe(stateDir);
|
||||||
|
expect(process.env.CLAWDBOT_STATE_DIR).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
await expectStateDirEnvRestored({ prev, capturedStateDir, capturedTempRoot });
|
||||||
|
} finally {
|
||||||
|
restoreStateDirEnv(testSnapshot);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user