@@ -479,6 +479,28 @@ def test_resume_migration_promotes_validate_only_succeeded(self):
479479 self .assertFalse (payload ['validateOnly' ])
480480 self .assertEqual (payload ['statusRequested' ], 'active' )
481481
482+ def test_resume_migration_promotes_validate_only_completed (self ):
483+ with patch ('azext_devops.dev.migration.migration.get_migration' ) as mock_get , \
484+ patch ('azext_devops.dev.migration.migration.resolve_instance' ) as mock_resolve , \
485+ patch ('azext_devops.dev.migration.migration._get_service_client' ) as mock_client , \
486+ patch ('azext_devops.dev.migration.migration._send_request' ) as mock_send :
487+ mock_send .return_value = {}
488+ mock_get .return_value = {
489+ 'status' : 'completed' ,
490+ 'validateOnly' : True ,
491+ }
492+ mock_resolve .return_value = self ._TEST_ORG
493+
494+ resume_migration (repository_id = '00000000-0000-0000-0000-000000000000' ,
495+ migration = True ,
496+ organization = self ._TEST_ORG , detect = False )
497+
498+ args = mock_send .call_args [0 ]
499+ self .assertEqual (args [1 ], 'PUT' )
500+ payload = args [3 ]
501+ self .assertFalse (payload ['validateOnly' ])
502+ self .assertEqual (payload ['statusRequested' ], 'active' )
503+
482504 def test_resume_migration_promote_uses_only_state_transition_fields (self ):
483505 with patch ('azext_devops.dev.migration.migration.get_migration' ) as mock_get , \
484506 patch ('azext_devops.dev.migration.migration.resolve_instance' ) as mock_resolve , \
@@ -521,6 +543,17 @@ def test_resume_succeeded_without_migration_flag_errors(self):
521543 organization = self ._TEST_ORG , detect = False )
522544 self .assertIn ('--migration' , str (ctx .exception ))
523545
546+ def test_resume_completed_without_migration_flag_errors (self ):
547+ with patch ('azext_devops.dev.migration.migration.get_migration' ) as mock_get , \
548+ patch ('azext_devops.dev.migration.migration.resolve_instance' ) as mock_resolve :
549+ mock_get .return_value = {'status' : 'completed' , 'validateOnly' : True }
550+ mock_resolve .return_value = self ._TEST_ORG
551+
552+ with self .assertRaises (CLIError ) as ctx :
553+ resume_migration (repository_id = '00000000-0000-0000-0000-000000000000' ,
554+ organization = self ._TEST_ORG , detect = False )
555+ self .assertIn ('--migration' , str (ctx .exception ))
556+
524557 def test_resume_succeeded_full_migration_errors (self ):
525558 with patch ('azext_devops.dev.migration.migration.get_migration' ) as mock_get , \
526559 patch ('azext_devops.dev.migration.migration.resolve_instance' ) as mock_resolve :
@@ -532,6 +565,54 @@ def test_resume_succeeded_full_migration_errors(self):
532565 organization = self ._TEST_ORG , detect = False )
533566 self .assertIn ('abandon' , str (ctx .exception ))
534567
568+ def test_resume_completed_full_migration_errors (self ):
569+ with patch ('azext_devops.dev.migration.migration.get_migration' ) as mock_get , \
570+ patch ('azext_devops.dev.migration.migration.resolve_instance' ) as mock_resolve :
571+ mock_get .return_value = {'status' : 'completed' , 'validateOnly' : False }
572+ mock_resolve .return_value = self ._TEST_ORG
573+
574+ with self .assertRaises (CLIError ) as ctx :
575+ resume_migration (repository_id = '00000000-0000-0000-0000-000000000000' ,
576+ organization = self ._TEST_ORG , detect = False )
577+ self .assertIn ('abandon' , str (ctx .exception ))
578+
579+ def test_resume_completed_status_takes_precedence_over_active_status_requested (self ):
580+ with patch ('azext_devops.dev.migration.migration.get_migration' ) as mock_get , \
581+ patch ('azext_devops.dev.migration.migration.resolve_instance' ) as mock_resolve :
582+ mock_get .return_value = {
583+ 'status' : 'completed' ,
584+ 'statusRequested' : 'active' ,
585+ 'validateOnly' : True ,
586+ }
587+ mock_resolve .return_value = self ._TEST_ORG
588+
589+ with self .assertRaises (CLIError ) as ctx :
590+ resume_migration (repository_id = '00000000-0000-0000-0000-000000000000' ,
591+ organization = self ._TEST_ORG , detect = False )
592+ self .assertIn ('--migration' , str (ctx .exception ))
593+
594+ def test_resume_completed_status_requested_without_status_is_terminal (self ):
595+ with patch ('azext_devops.dev.migration.migration.get_migration' ) as mock_get , \
596+ patch ('azext_devops.dev.migration.migration.resolve_instance' ) as mock_resolve :
597+ mock_get .return_value = {'statusRequested' : 'completed' , 'validateOnly' : False }
598+ mock_resolve .return_value = self ._TEST_ORG
599+
600+ with self .assertRaises (CLIError ) as ctx :
601+ resume_migration (repository_id = '00000000-0000-0000-0000-000000000000' ,
602+ organization = self ._TEST_ORG , detect = False )
603+ self .assertIn ('abandon' , str (ctx .exception ))
604+
605+ def test_resume_completed_case_variants_are_treated_as_terminal (self ):
606+ with patch ('azext_devops.dev.migration.migration.get_migration' ) as mock_get , \
607+ patch ('azext_devops.dev.migration.migration.resolve_instance' ) as mock_resolve :
608+ mock_get .return_value = {'status' : 'Com_PleTed' , 'validateOnly' : False }
609+ mock_resolve .return_value = self ._TEST_ORG
610+
611+ with self .assertRaises (CLIError ) as ctx :
612+ resume_migration (repository_id = '00000000-0000-0000-0000-000000000000' ,
613+ organization = self ._TEST_ORG , detect = False )
614+ self .assertIn ('abandon' , str (ctx .exception ))
615+
535616
536617if __name__ == '__main__' :
537618 unittest .main ()
0 commit comments