test: merge tts config gating cases

This commit is contained in:
Peter Steinberger 2026-03-17 08:33:05 +00:00
parent 74cc748ff7
commit eef0f5bfbc

View File

@ -596,49 +596,54 @@ describe("tts", () => {
messages: { tts: {} },
};
it("defaults to the official OpenAI endpoint", () => {
withEnv({ OPENAI_TTS_BASE_URL: undefined }, () => {
const config = resolveTtsConfig(baseCfg);
expect(config.openai.baseUrl).toBe("https://api.openai.com/v1");
});
});
it("picks up OPENAI_TTS_BASE_URL env var when no config baseUrl is set", () => {
withEnv({ OPENAI_TTS_BASE_URL: "http://localhost:8880/v1" }, () => {
const config = resolveTtsConfig(baseCfg);
expect(config.openai.baseUrl).toBe("http://localhost:8880/v1");
});
});
it("config baseUrl takes precedence over env var", () => {
const cfg: OpenClawConfig = {
...baseCfg,
messages: {
tts: { openai: { baseUrl: "http://my-server:9000/v1" } },
it("resolves openai.baseUrl from config/env with config precedence and slash trimming", () => {
for (const testCase of [
{
name: "default endpoint",
cfg: baseCfg,
env: { OPENAI_TTS_BASE_URL: undefined },
expected: "https://api.openai.com/v1",
},
};
withEnv({ OPENAI_TTS_BASE_URL: "http://localhost:8880/v1" }, () => {
const config = resolveTtsConfig(cfg);
expect(config.openai.baseUrl).toBe("http://my-server:9000/v1");
});
});
it("strips trailing slashes from the resolved baseUrl", () => {
const cfg: OpenClawConfig = {
...baseCfg,
messages: {
tts: { openai: { baseUrl: "http://my-server:9000/v1///" } },
{
name: "env override",
cfg: baseCfg,
env: { OPENAI_TTS_BASE_URL: "http://localhost:8880/v1" },
expected: "http://localhost:8880/v1",
},
};
const config = resolveTtsConfig(cfg);
expect(config.openai.baseUrl).toBe("http://my-server:9000/v1");
});
it("strips trailing slashes from env var baseUrl", () => {
withEnv({ OPENAI_TTS_BASE_URL: "http://localhost:8880/v1/" }, () => {
const config = resolveTtsConfig(baseCfg);
expect(config.openai.baseUrl).toBe("http://localhost:8880/v1");
});
{
name: "config wins over env",
cfg: {
...baseCfg,
messages: {
tts: { openai: { baseUrl: "http://my-server:9000/v1" } },
},
} as OpenClawConfig,
env: { OPENAI_TTS_BASE_URL: "http://localhost:8880/v1" },
expected: "http://my-server:9000/v1",
},
{
name: "config slash trimming",
cfg: {
...baseCfg,
messages: {
tts: { openai: { baseUrl: "http://my-server:9000/v1///" } },
},
} as OpenClawConfig,
env: { OPENAI_TTS_BASE_URL: undefined },
expected: "http://my-server:9000/v1",
},
{
name: "env slash trimming",
cfg: baseCfg,
env: { OPENAI_TTS_BASE_URL: "http://localhost:8880/v1/" },
expected: "http://localhost:8880/v1",
},
] as const) {
withEnv(testCase.env, () => {
const config = resolveTtsConfig(testCase.cfg);
expect(config.openai.baseUrl, testCase.name).toBe(testCase.expected);
});
}
});
});
@ -678,12 +683,13 @@ describe("tts", () => {
});
}
it("omits instructions for unsupported speech models", async () => {
await expectTelephonyInstructions("tts-1", undefined);
});
it("includes instructions for gpt-4o-mini-tts", async () => {
await expectTelephonyInstructions("gpt-4o-mini-tts", "Speak warmly");
it("only includes instructions for supported telephony models", async () => {
for (const testCase of [
{ model: "tts-1", expectedInstructions: undefined },
{ model: "gpt-4o-mini-tts", expectedInstructions: "Speak warmly" },
] as const) {
await expectTelephonyInstructions(testCase.model, testCase.expectedInstructions);
}
});
});
@ -769,31 +775,36 @@ describe("tts", () => {
}
});
it("skips auto-TTS in tagged mode unless a tts tag is present", async () => {
await withMockedAutoTtsFetch(async (fetchMock) => {
const payload = { text: "Hello world" };
const result = await maybeApplyTtsToPayload({
payload,
cfg: taggedCfg,
kind: "final",
});
expect(result).toBe(payload);
expect(fetchMock).not.toHaveBeenCalled();
});
});
it("runs auto-TTS in tagged mode when tags are present", async () => {
await withMockedAutoTtsFetch(async (fetchMock) => {
const result = await maybeApplyTtsToPayload({
it("respects tagged-mode auto-TTS gating", async () => {
for (const testCase of [
{
name: "plain text is skipped",
payload: { text: "Hello world" },
expectedFetchCalls: 0,
expectSamePayload: true,
},
{
name: "tagged text is synthesized",
payload: { text: "[[tts:text]]Hello world[[/tts:text]]" },
cfg: taggedCfg,
kind: "final",
});
expectedFetchCalls: 1,
expectSamePayload: false,
},
] as const) {
await withMockedAutoTtsFetch(async (fetchMock) => {
const result = await maybeApplyTtsToPayload({
payload: testCase.payload,
cfg: taggedCfg,
kind: "final",
});
expect(result.mediaUrl).toBeDefined();
expect(fetchMock).toHaveBeenCalledTimes(1);
});
expect(fetchMock, testCase.name).toHaveBeenCalledTimes(testCase.expectedFetchCalls);
if (testCase.expectSamePayload) {
expect(result, testCase.name).toBe(testCase.payload);
} else {
expect(result.mediaUrl, testCase.name).toBeDefined();
}
});
}
});
});
});