@@ -365,6 +365,104 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: finetune (offline)", () => {
365365 expect ( data . action ) . toBe ( "finetune.create" ) ;
366366 expect ( data . body . training_type ) . toBe ( "efficient_sft" ) ;
367367 } ) ;
368+
369+ test ( "finetune video create --help 暴露视频超参且不含文本超参" , async ( ) => {
370+ // Video exposes --n-epochs / --batch-size / --learning-rate; the text-only
371+ // --training-type / --max-length surface is not offered.
372+ const { stderr, exitCode } = await runCommandE2e ( FINETUNE_ROUTES , [
373+ "finetune" ,
374+ "video" ,
375+ "create" ,
376+ "--help" ,
377+ ] ) ;
378+ expect ( exitCode , stderr ) . toBe ( 0 ) ;
379+ expect ( stderr ) . toMatch ( / - - b a s e - m o d e l / ) ;
380+ expect ( stderr ) . toMatch ( / - - n - e p o c h s / ) ;
381+ expect ( stderr ) . toMatch ( / - - b a t c h - s i z e / ) ;
382+ expect ( stderr ) . toMatch ( / - - l e a r n i n g - r a t e / ) ;
383+ expect ( stderr ) . not . toMatch ( / - - t r a i n i n g - t y p e | - - m a x - l e n g t h / ) ;
384+ } ) ;
385+
386+ test ( "finetune video create --datasets 缺失时退出为用法错误 (2)" , async ( ) => {
387+ const { stderr, exitCode } = await runCommandE2e ( FINETUNE_ROUTES , [
388+ "finetune" ,
389+ "video" ,
390+ "create" ,
391+ "--base-model" ,
392+ "wan2.7-i2v" ,
393+ "--quiet" ,
394+ ] ) ;
395+ expect ( exitCode ) . toBe ( 2 ) ;
396+ expect ( stderr ) . toMatch ( / - - d a t a s e t s | M i s s i n g r e q u i r e d / i) ;
397+ } ) ;
398+
399+ test . each ( [
400+ // Model-family-specific defaults resolved by the sft-lora video profile.
401+ [ "wan2.7-i2v" , 1 , 102400 ] ,
402+ [ "wan2.5-i2v-preview" , 4 , 36864 ] ,
403+ [ "wan2.2-kf2v-flash" , 4 , 262144 ] ,
404+ ] ) (
405+ "finetune video create --dry-run %s 解析 batch_size=%i / max_pixels=%i" ,
406+ async ( baseModel , batchSize , maxPixels ) => {
407+ const { stdout, stderr, exitCode } = await runCommandE2e ( FINETUNE_ROUTES , [
408+ "finetune" ,
409+ "video" ,
410+ "create" ,
411+ "--base-model" ,
412+ baseModel ,
413+ "--datasets" ,
414+ "file-video" ,
415+ "--dry-run" ,
416+ "--output" ,
417+ "json" ,
418+ ] ) ;
419+ expect ( exitCode , stderr ) . toBe ( 0 ) ;
420+ const data = parseStdoutJson < {
421+ action : string ;
422+ body : {
423+ model : string ;
424+ training_type : string ;
425+ hyper_parameters : Record < string , unknown > ;
426+ } ;
427+ } > ( stdout ) ;
428+ expect ( data . action ) . toBe ( "finetune.create" ) ;
429+ expect ( data . body . model ) . toBe ( baseModel ) ;
430+ expect ( data . body . training_type ) . toBe ( "efficient_sft" ) ;
431+ expect ( data . body . hyper_parameters . batch_size ) . toBe ( batchSize ) ;
432+ expect ( data . body . hyper_parameters . max_pixels ) . toBe ( maxPixels ) ;
433+ expect ( data . body . hyper_parameters . learning_rate ) . toBe ( "2e-5" ) ;
434+ expect ( data . body . hyper_parameters . lora_rank ) . toBe ( 32 ) ;
435+ } ,
436+ ) ;
437+
438+ test ( "finetune video create --dry-run 转发超参覆盖且不做 clamp" , async ( ) => {
439+ const { stdout, stderr, exitCode } = await runCommandE2e ( FINETUNE_ROUTES , [
440+ "finetune" ,
441+ "video" ,
442+ "create" ,
443+ "--base-model" ,
444+ "wan2.7-i2v" ,
445+ "--datasets" ,
446+ "file-video" ,
447+ "--n-epochs" ,
448+ "100" ,
449+ "--batch-size" ,
450+ "2" ,
451+ "--learning-rate" ,
452+ "1e-5" ,
453+ "--dry-run" ,
454+ "--output" ,
455+ "json" ,
456+ ] ) ;
457+ expect ( exitCode , stderr ) . toBe ( 0 ) ;
458+ const data = parseStdoutJson < {
459+ body : { hyper_parameters : Record < string , unknown > } ;
460+ } > ( stdout ) ;
461+ // Video overrides are forwarded verbatim (no [8, 1024] text clamp).
462+ expect ( data . body . hyper_parameters . n_epochs ) . toBe ( 100 ) ;
463+ expect ( data . body . hyper_parameters . batch_size ) . toBe ( 2 ) ;
464+ expect ( data . body . hyper_parameters . learning_rate ) . toBe ( "1e-5" ) ;
465+ } ) ;
368466} ) ;
369467
370468describe . skipIf ( ! isDashScopeE2EReady ( ) ) ( "e2e: finetune (DashScope)" , ( ) => {
0 commit comments