3862996045
CI/CD Pipeline / Check if frontend-only change (push) Waiting to run
CI/CD Pipeline / Validate - Code Quality (push) Waiting to run
CI/CD Pipeline / Validate - Type Check (mypy) (push) Waiting to run
CI/CD Pipeline / Validate - Migration (alembic) (push) Waiting to run
CI/CD Pipeline / Unit Tests (push) Blocked by required conditions
CI/CD Pipeline / Integration Tests (push) Blocked by required conditions
CI/CD Pipeline / Frontend Lint (push) Waiting to run
CI/CD Pipeline / Frontend Unit Tests (push) Blocked by required conditions
CI/CD Pipeline / PR Build API Image (push) Waiting to run
CI/CD Pipeline / PR Build Web Image (push) Waiting to run
CI/CD Pipeline / PR Build Worker Image (push) Waiting to run
CI/CD Pipeline / Build Staging API Image (push) Waiting to run
CI/CD Pipeline / Build Staging Web Image (push) Waiting to run
CI/CD Pipeline / Build Staging Worker Image (push) Waiting to run
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Blocked by required conditions
CI/CD Pipeline / Staging E2E Tests (push) Blocked by required conditions
CI/CD Pipeline / Staging API Integration Tests (push) Blocked by required conditions
CI/CD Pipeline / Build Production API Image (push) Waiting to run
CI/CD Pipeline / Build Production Web Image (push) Waiting to run
CI/CD Pipeline / Build Production Worker Image (push) Waiting to run
CI/CD Pipeline / Deploy Production (push) Blocked by required conditions
CI/CD Pipeline / Production Browser E2E (push) Blocked by required conditions
CI/CD Pipeline / ACR Image Cleanup (push) Blocked by required conditions
72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
import { describe, expect, it } from "vitest"
|
|
import { toVoiceClone, formatDuration } from "@/api/voice-clone"
|
|
import type { VoiceCloneProfile } from "@/api/voice-clone"
|
|
|
|
describe("formatDuration", () => {
|
|
it("should format seconds correctly", () => {
|
|
expect(formatDuration(0)).toBe("0:00")
|
|
expect(formatDuration(5)).toBe("0:05")
|
|
expect(formatDuration(59)).toBe("0:59")
|
|
expect(formatDuration(60)).toBe("1:00")
|
|
expect(formatDuration(90)).toBe("1:30")
|
|
expect(formatDuration(3600)).toBe("60:00")
|
|
})
|
|
})
|
|
|
|
describe("toVoiceClone", () => {
|
|
const baseProfile: VoiceCloneProfile = {
|
|
id: "clone-1",
|
|
name: "测试克隆",
|
|
description: "测试描述",
|
|
status: "ready",
|
|
source_audio_url: "https://example.com/audio.wav",
|
|
language: "zh",
|
|
gender: "female",
|
|
error_message: null,
|
|
created_at: "2026-01-01T00:00:00Z",
|
|
updated_at: "2026-01-02T00:00:00Z",
|
|
}
|
|
|
|
it("should map profile to VoiceClone correctly", () => {
|
|
const result = toVoiceClone(baseProfile)
|
|
|
|
expect(result.id).toBe("clone-1")
|
|
expect(result.name).toBe("测试克隆")
|
|
expect(result.description).toBe("测试描述")
|
|
expect(result.status).toBe("ready")
|
|
expect(result.sample_url).toBe("https://example.com/audio.wav")
|
|
expect(result.language).toBe("zh")
|
|
expect(result.gender).toBe("female")
|
|
expect(result.duration_seconds).toBe(0)
|
|
expect(result.progress).toBe(0)
|
|
})
|
|
|
|
it("should map pending status to processing", () => {
|
|
const pending = { ...baseProfile, status: "pending" as const }
|
|
const result = toVoiceClone(pending)
|
|
expect(result.status).toBe("processing")
|
|
})
|
|
|
|
it("should handle missing optional fields", () => {
|
|
const minimal: VoiceCloneProfile = {
|
|
id: "clone-2",
|
|
name: "最小克隆",
|
|
description: null as any,
|
|
status: "failed",
|
|
source_audio_url: null as any,
|
|
language: null as any,
|
|
gender: null as any,
|
|
error_message: "错误信息",
|
|
created_at: "2026-01-01T00:00:00Z",
|
|
updated_at: "2026-01-01T00:00:00Z",
|
|
}
|
|
const result = toVoiceClone(minimal)
|
|
|
|
expect(result.description).toBe("")
|
|
expect(result.sample_url).toBeUndefined()
|
|
expect(result.language).toBe("")
|
|
expect(result.gender).toBe("")
|
|
expect(result.error_message).toBe("错误信息")
|
|
})
|
|
})
|