|
1 | 1 | import { writeFileSync } from "node:fs"; |
2 | 2 | import { join } from "node:path"; |
3 | 3 | import { describe, expect, test } from "vite-plus/test"; |
4 | | -import { makeE2eOutputDir, parseStdoutJson, runCommandE2e } from "./helpers.ts"; |
| 4 | +import { |
| 5 | + isBailianE2EMediaEnabled, |
| 6 | + isBailianE2EVideoEnabled, |
| 7 | + isDashScopeE2EReady, |
| 8 | + makeE2eOutputDir, |
| 9 | + parseStdoutJson, |
| 10 | + runCommandE2e, |
| 11 | +} from "./helpers.ts"; |
5 | 12 | import type { E2eRouteExports } from "./topic-routes.ts"; |
6 | 13 |
|
7 | 14 | /** |
@@ -321,3 +328,99 @@ describe("e2e: aigc auto → mcp", () => { |
321 | 328 | expect(stderr, label).toMatch(pattern); |
322 | 329 | }); |
323 | 330 | }); |
| 331 | + |
| 332 | +// ---- 真实 MCP 调用(live gated)---- |
| 333 | +// |
| 334 | +// 以上全部是离线 dry-run。以下三条真实打百炼 AIGC MCP,验证 auto 确实能经 MCP |
| 335 | +// 出结果并落地文件。默认 skip:需 BAILIAN_E2E=1 + DASHSCOPE_API_KEY;图像 / 语音 |
| 336 | +// 另受媒体开关控制(默认开),视频耗时长、另需 BAILIAN_E2E_VIDEO=1。 |
| 337 | +// |
| 338 | +// image edit / speech recognize 的真实链路需要合法的图片 / 音频二进制 fixture |
| 339 | +// (静音音频会被下游判为“无语音”而 isError),其请求契约已由上面的 dry-run 预览 |
| 340 | +// 与 data URI 脱敏覆盖,故 live 只覆盖纯 prompt/text 输入的这三条命令。 |
| 341 | + |
| 342 | +describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( |
| 343 | + "e2e: aigc auto → mcp(DashScope 媒体,真实调用)", |
| 344 | + () => { |
| 345 | + test("【auto】image generate 真实经 MCP(bailian_image_gen) 出图并落地", async () => { |
| 346 | + const outDir = makeE2eOutputDir("aigc-auto-live-image-generate"); |
| 347 | + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ |
| 348 | + "image", |
| 349 | + "generate", |
| 350 | + "--model", |
| 351 | + "auto", |
| 352 | + "--prompt", |
| 353 | + "一只简笔画小猫,白底", |
| 354 | + "--out-dir", |
| 355 | + outDir, |
| 356 | + "--out-prefix", |
| 357 | + "e2e-auto-gen", |
| 358 | + "--output", |
| 359 | + "json", |
| 360 | + ]); |
| 361 | + expect(exitCode, stderr).toBe(0); |
| 362 | + const data = parseStdoutJson<{ urls?: string[]; saved?: string[]; total?: number }>(stdout); |
| 363 | + expect(data.saved?.length ?? 0).toBeGreaterThan(0); |
| 364 | + expect(data.saved?.[0]).toContain("e2e-auto-gen"); |
| 365 | + expect(data.urls?.length ?? 0).toBeGreaterThan(0); |
| 366 | + }, 300_000); |
| 367 | + |
| 368 | + test("【auto】speech synthesize 真实经 MCP(bailian_tts) 合成并落地", async () => { |
| 369 | + const outDir = makeE2eOutputDir("aigc-auto-live-speech-synthesize"); |
| 370 | + const outWav = join(outDir, "e2e-auto-tts.wav"); |
| 371 | + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ |
| 372 | + "speech", |
| 373 | + "synthesize", |
| 374 | + "--model", |
| 375 | + "auto", |
| 376 | + "--text", |
| 377 | + "端到端 auto 语音测试", |
| 378 | + // voice 原样透传给 MCP,需为服务端音色枚举内的值(与 REST live 用例一致)。 |
| 379 | + "--voice", |
| 380 | + "longxiaochun_v3", |
| 381 | + "--out", |
| 382 | + outWav, |
| 383 | + "--output", |
| 384 | + "json", |
| 385 | + ]); |
| 386 | + expect(exitCode, stderr).toBe(0); |
| 387 | + const data = parseStdoutJson<{ saved?: string; audio_url?: string; voice?: string }>(stdout); |
| 388 | + expect(data.saved).toBe(outWav); |
| 389 | + expect(data.audio_url?.length ?? 0).toBeGreaterThan(0); |
| 390 | + expect(data.voice).toBe("longxiaochun_v3"); |
| 391 | + }, 180_000); |
| 392 | + }, |
| 393 | +); |
| 394 | + |
| 395 | +describe.skipIf(!isBailianE2EVideoEnabled() || !isDashScopeE2EReady())( |
| 396 | + "e2e: aigc auto → mcp(DashScope 视频,真实调用)", |
| 397 | + () => { |
| 398 | + test("【auto】video generate(t2v) 真实经 MCP 提交→轮询→下载", async () => { |
| 399 | + const outDir = makeE2eOutputDir("aigc-auto-live-video-generate"); |
| 400 | + const outMp4 = join(outDir, "e2e-auto-t2v.mp4"); |
| 401 | + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ |
| 402 | + "video", |
| 403 | + "generate", |
| 404 | + "--model", |
| 405 | + "auto", |
| 406 | + "--prompt", |
| 407 | + "海浪拍打礁石,慢镜头", |
| 408 | + "--download", |
| 409 | + outMp4, |
| 410 | + "--output", |
| 411 | + "json", |
| 412 | + ]); |
| 413 | + expect(exitCode, stderr).toBe(0); |
| 414 | + const data = parseStdoutJson<{ |
| 415 | + task_id?: string; |
| 416 | + video_url?: string; |
| 417 | + status?: string; |
| 418 | + saved?: string; |
| 419 | + }>(stdout); |
| 420 | + expect(data.status).toBe("SUCCEEDED"); |
| 421 | + expect(data.saved).toBe(outMp4); |
| 422 | + expect(data.video_url?.length ?? 0).toBeGreaterThan(0); |
| 423 | + expect(data.task_id?.length ?? 0).toBeGreaterThan(0); |
| 424 | + }, 600_000); |
| 425 | + }, |
| 426 | +); |
0 commit comments