@@ -465,6 +465,113 @@ describe("POST /video/process", () => {
465465 } ) ;
466466} ) ;
467467
468+ describe ( "POST /video/edit" , ( ) => {
469+ beforeEach ( ( ) => {
470+ mock . restore ( ) ;
471+ } ) ;
472+
473+ test ( "returns 401 without media server secret" , async ( ) => {
474+ const response = await app . fetch (
475+ unauthenticatedVideoPostRequest ( "/video/edit" , {
476+ videoId : "test-id" ,
477+ userId : "user-id" ,
478+ sourceUrl : "https://example.com/source.mp4" ,
479+ outputPresignedUrl : "https://s3.example.com/output" ,
480+ keepRanges : [ { start : 0 , end : 1 } ] ,
481+ } ) ,
482+ ) ;
483+
484+ expect ( response . status ) . toBe ( 401 ) ;
485+ } ) ;
486+
487+ test ( "returns 400 for invalid JSON" , async ( ) => {
488+ const response = await app . fetch (
489+ new Request ( "http://localhost/video/edit" , {
490+ method : "POST" ,
491+ headers : AUTH_HEADERS ,
492+ body : "{" ,
493+ } ) ,
494+ ) ;
495+
496+ expect ( response . status ) . toBe ( 400 ) ;
497+ const data = await response . json ( ) ;
498+ expect ( data . code ) . toBe ( "INVALID_REQUEST" ) ;
499+ } ) ;
500+
501+ test ( "returns 400 for missing keep ranges" , async ( ) => {
502+ const response = await app . fetch (
503+ videoPostRequest ( "/video/edit" , {
504+ videoId : "test-id" ,
505+ userId : "user-id" ,
506+ sourceUrl : "https://example.com/source.mp4" ,
507+ outputPresignedUrl : "https://s3.example.com/output" ,
508+ } ) ,
509+ ) ;
510+
511+ expect ( response . status ) . toBe ( 400 ) ;
512+ const data = await response . json ( ) ;
513+ expect ( data . code ) . toBe ( "INVALID_REQUEST" ) ;
514+ } ) ;
515+
516+ test ( "returns 400 for invalid ranges" , async ( ) => {
517+ const response = await app . fetch (
518+ videoPostRequest ( "/video/edit" , {
519+ videoId : "test-id" ,
520+ userId : "user-id" ,
521+ sourceUrl : "https://example.com/source.mp4" ,
522+ outputPresignedUrl : "https://s3.example.com/output" ,
523+ keepRanges : [ { start : 3 , end : 1 } ] ,
524+ } ) ,
525+ ) ;
526+
527+ expect ( response . status ) . toBe ( 400 ) ;
528+ const data = await response . json ( ) ;
529+ expect ( data . code ) . toBe ( "INVALID_REQUEST" ) ;
530+ } ) ;
531+
532+ test ( "returns jobId when edit starts successfully" , async ( ) => {
533+ mock . module ( "../../lib/job-manager" , ( ) => ( {
534+ canAcceptNewVideoProcess : ( ) => true ,
535+ getActiveVideoProcessCount : ( ) => 0 ,
536+ getMaxConcurrentVideoProcesses : ( ) => 3 ,
537+ getSystemResources : jobManager . getSystemResources ,
538+ getAllJobs : ( ) => [ ] ,
539+ generateJobId : ( ) => "edit-job-id" ,
540+ createJob : ( ) => ( {
541+ jobId : "edit-job-id" ,
542+ videoId : "test-id" ,
543+ userId : "user-id" ,
544+ phase : "queued" ,
545+ progress : 0 ,
546+ createdAt : new Date ( ) ,
547+ updatedAt : new Date ( ) ,
548+ } ) ,
549+ getJob : ( ) => null ,
550+ updateJob : ( ) => null ,
551+ deleteJob : ( ) => { } ,
552+ sendWebhook : async ( ) => { } ,
553+ getJobProgress : jobManager . getJobProgress ,
554+ } ) ) ;
555+
556+ const { default : appWithMock } = await import ( "../../app" ) ;
557+
558+ const response = await appWithMock . fetch (
559+ videoPostRequest ( "/video/edit" , {
560+ videoId : "test-id" ,
561+ userId : "user-id" ,
562+ sourceUrl : "https://example.com/source.mp4" ,
563+ outputPresignedUrl : "https://s3.example.com/output" ,
564+ keepRanges : [ { start : 0 , end : 1 } ] ,
565+ } ) ,
566+ ) ;
567+
568+ expect ( response . status ) . toBe ( 200 ) ;
569+ const data = await response . json ( ) ;
570+ expect ( data . jobId ) . toBe ( "edit-job-id" ) ;
571+ expect ( data . status ) . toBe ( "queued" ) ;
572+ } ) ;
573+ } ) ;
574+
468575describe ( "GET /video/process/:jobId/status" , ( ) => {
469576 beforeEach ( ( ) => {
470577 mock . restore ( ) ;
0 commit comments