fix(cli): validate the complete TTS speed argument (#5264)

This commit is contained in:
Abdullah M. Nazif
2026-10-08 20:20:37 +00:00
committed by GitHub
parent c9c9f4d363
commit 5a7ada63bf
2 changed files with 38 additions and 2 deletions
+36
View File
@@ -1,4 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { runCommand } from "citty";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
@@ -44,6 +45,41 @@ describe("tts command", () => {
);
});
it.each(["0.05", "1x", "1.5junk", "1 2", "", " ", "NaN", "Infinity", "0", "-1", "3.01"])(
"rejects invalid speed %j before synthesis",
async (speed) => {
const errors = vi.spyOn(console, "error").mockImplementation(() => {});
await expect(
runCommand(ttsCommand, { rawArgs: ["Hello", "--speed", speed, "--json"] }),
).rejects.toThrow();
expect(synthesizeMock).not.toHaveBeenCalled();
expect(errors.mock.calls.flat().join(" ")).toContain("between 0.1 and 3.0");
},
);
it.each([
["0.1", 0.1],
["3", 3],
["1e-1", 0.1],
[" 1.25 ", 1.25],
])("uses the complete valid speed %j", async (speed, expected) => {
await runCommand(ttsCommand, { rawArgs: ["Hello", "--speed", speed, "--json"] });
expect(synthesizeMock).toHaveBeenCalledWith(
"Hello",
expect.any(String),
expect.objectContaining({ speed: expected }),
);
});
it("defaults the speed only when the argument is omitted", async () => {
await runCommand(ttsCommand, { rawArgs: ["Hello", "--json"] });
expect(synthesizeMock).toHaveBeenCalledWith(
"Hello",
expect.any(String),
expect.objectContaining({ speed: 1 }),
);
});
it("rejects text words with --text-file even under --list", async () => {
const input = join(dir, "script.txt");
writeFileSync(input, "From the file\n");
+2 -2
View File
@@ -121,9 +121,9 @@ export default defineCommand({
// ── Resolve output path ───────────────────────────────────────────
const output = resolve(args.output ?? "speech.wav");
const voice = args.voice ?? DEFAULT_VOICE;
const speed = args.speed ? parseFloat(args.speed) : 1.0;
const speed = args.speed === undefined ? 1.0 : Number(args.speed);
if (isNaN(speed) || speed <= 0 || speed > 3) {
if (!Number.isFinite(speed) || speed < 0.1 || speed > 3) {
console.error(c.error("Speed must be a number between 0.1 and 3.0"));
failCommand();
}