test: share speech tts payload fixture

This commit is contained in:
Peter Steinberger
2026-04-20 17:11:33 +01:00
parent 3ae3a5e77d
commit 6ed67fc873

View File

@@ -1,7 +1,6 @@
import { rmSync } from "node:fs";
import path from "node:path";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-payload";
import type { SpeechProviderPlugin, SpeechSynthesisRequest } from "openclaw/plugin-sdk/speech-core";
import { afterEach, describe, expect, it, vi } from "vitest";
@@ -66,6 +65,35 @@ function createTtsConfig(prefsName: string): OpenClawConfig {
};
}
async function expectTtsPayloadResult(params: {
channel: string;
prefsName: string;
text: string;
target: "voice-note" | "audio-file";
audioAsVoice: true | undefined;
}) {
const cfg = createTtsConfig(params.prefsName);
let mediaDir: string | undefined;
try {
const result = await maybeApplyTtsToPayload({
payload: { text: params.text },
cfg,
channel: params.channel,
kind: "final",
});
expect(synthesizeMock).toHaveBeenCalledWith(expect.objectContaining({ target: params.target }));
expect(result.audioAsVoice).toBe(params.audioAsVoice);
expect(result.mediaUrl).toMatch(/voice-\d+\.ogg$/);
mediaDir = result.mediaUrl ? path.dirname(result.mediaUrl) : undefined;
} finally {
if (mediaDir) {
rmSync(mediaDir, { recursive: true, force: true });
}
}
}
describe("speech-core native voice-note routing", () => {
afterEach(() => {
synthesizeMock.mockClear();
@@ -81,60 +109,22 @@ describe("speech-core native voice-note routing", () => {
});
it("marks Discord auto TTS replies as native voice messages", async () => {
const cfg = createTtsConfig("openclaw-speech-core-tts-test");
const payload: ReplyPayload = {
await expectTtsPayloadResult({
channel: "discord",
prefsName: "openclaw-speech-core-tts-test",
text: "This Discord reply should be delivered as a native voice note.",
};
let mediaDir: string | undefined;
try {
const result = await maybeApplyTtsToPayload({
payload,
cfg,
channel: "discord",
kind: "final",
});
expect(synthesizeMock).toHaveBeenCalledWith(
expect.objectContaining({ target: "voice-note" }),
);
expect(result.audioAsVoice).toBe(true);
expect(result.mediaUrl).toMatch(/voice-\d+\.ogg$/);
mediaDir = result.mediaUrl ? path.dirname(result.mediaUrl) : undefined;
} finally {
if (mediaDir) {
rmSync(mediaDir, { recursive: true, force: true });
}
}
target: "voice-note",
audioAsVoice: true,
});
});
it("keeps non-native voice-note channels as regular audio files", async () => {
const cfg = createTtsConfig("openclaw-speech-core-tts-slack-test");
const payload: ReplyPayload = {
await expectTtsPayloadResult({
channel: "slack",
prefsName: "openclaw-speech-core-tts-slack-test",
text: "Slack replies should be delivered as regular audio attachments.",
};
let mediaDir: string | undefined;
try {
const result = await maybeApplyTtsToPayload({
payload,
cfg,
channel: "slack",
kind: "final",
});
expect(synthesizeMock).toHaveBeenCalledWith(
expect.objectContaining({ target: "audio-file" }),
);
expect(result.audioAsVoice).toBeUndefined();
expect(result.mediaUrl).toMatch(/voice-\d+\.ogg$/);
mediaDir = result.mediaUrl ? path.dirname(result.mediaUrl) : undefined;
} finally {
if (mediaDir) {
rmSync(mediaDir, { recursive: true, force: true });
}
}
target: "audio-file",
audioAsVoice: undefined,
});
});
});