@@ -741,6 +741,156 @@ sessionDefaults:
741741 expect ( parsed . sessionDefaults ?. simulatorName ) . toBeUndefined ( ) ;
742742 } ) ;
743743
744+ it ( 'continues setup with no default device when xctrace spawn fails' , async ( ) => {
745+ const { fs, getStoredConfig } = createSetupFs ( ) ;
746+
747+ const executor : CommandExecutor = async ( command ) => {
748+ if ( command [ 0 ] === 'xcrun' && command [ 1 ] === 'devicectl' ) {
749+ throw new Error ( 'devicectl unavailable' ) ;
750+ }
751+
752+ if ( command [ 0 ] === 'xcrun' && command [ 1 ] === 'xctrace' ) {
753+ throw new Error ( 'xctrace spawn failed' ) ;
754+ }
755+
756+ if ( command . includes ( '--json' ) ) {
757+ return createMockCommandResponse ( {
758+ success : true ,
759+ output : JSON . stringify ( {
760+ devices : {
761+ 'iOS 17.0' : [
762+ {
763+ name : 'iPhone 15' ,
764+ udid : 'SIM-1' ,
765+ state : 'Shutdown' ,
766+ isAvailable : true ,
767+ } ,
768+ ] ,
769+ } ,
770+ } ) ,
771+ } ) ;
772+ }
773+
774+ return createMockCommandResponse ( {
775+ success : true ,
776+ output : `Information about workspace "App":\n Schemes:\n App` ,
777+ } ) ;
778+ } ;
779+
780+ const prompter : Prompter = {
781+ selectOne : async < T > ( opts : { options : Array < { value : T } > } ) => opts . options [ 0 ] . value ,
782+ selectMany : async < T > ( opts : { options : Array < { value : T } > } ) => {
783+ const loggingOption = opts . options . find ( ( option ) => option . value === ( 'logging' as T ) ) ;
784+ return loggingOption ? [ loggingOption . value ] : opts . options . map ( ( option ) => option . value ) ;
785+ } ,
786+ confirm : async ( opts : { defaultValue : boolean } ) => opts . defaultValue ,
787+ } ;
788+
789+ await runSetupWizard ( {
790+ cwd,
791+ fs,
792+ executor,
793+ prompter,
794+ quietOutput : true ,
795+ } ) ;
796+
797+ const parsed = parseYaml ( getStoredConfig ( ) ) as {
798+ sessionDefaults ?: Record < string , unknown > ;
799+ } ;
800+
801+ expect ( parsed . sessionDefaults ?. deviceId ) . toBeUndefined ( ) ;
802+ expect ( parsed . sessionDefaults ?. simulatorId ) . toBeUndefined ( ) ;
803+ expect ( parsed . sessionDefaults ?. simulatorName ) . toBeUndefined ( ) ;
804+ } ) ;
805+
806+ it ( 'continues setup with no default device when temp path creation fails' , async ( ) => {
807+ const { fs, getStoredConfig } = createSetupFs ( ) ;
808+ fs . tmpdir = ( ) => {
809+ throw new Error ( 'tmpdir unavailable' ) ;
810+ } ;
811+
812+ const executor : CommandExecutor = async ( command ) => {
813+ if ( command [ 0 ] === 'xcrun' && command [ 1 ] === 'xctrace' ) {
814+ throw new Error ( 'xctrace spawn failed' ) ;
815+ }
816+
817+ return createMockCommandResponse ( {
818+ success : true ,
819+ output : `Information about workspace "App":\n Schemes:\n App` ,
820+ } ) ;
821+ } ;
822+
823+ const prompter : Prompter = {
824+ selectOne : async < T > ( opts : { options : Array < { value : T } > } ) => opts . options [ 0 ] . value ,
825+ selectMany : async < T > ( opts : { options : Array < { value : T } > } ) => {
826+ const loggingOption = opts . options . find ( ( option ) => option . value === ( 'logging' as T ) ) ;
827+ return loggingOption ? [ loggingOption . value ] : opts . options . map ( ( option ) => option . value ) ;
828+ } ,
829+ confirm : async ( opts : { defaultValue : boolean } ) => opts . defaultValue ,
830+ } ;
831+
832+ await runSetupWizard ( {
833+ cwd,
834+ fs,
835+ executor,
836+ prompter,
837+ quietOutput : true ,
838+ } ) ;
839+
840+ const parsed = parseYaml ( getStoredConfig ( ) ) as {
841+ sessionDefaults ?: Record < string , unknown > ;
842+ } ;
843+
844+ expect ( parsed . sessionDefaults ?. deviceId ) . toBeUndefined ( ) ;
845+ expect ( parsed . sessionDefaults ?. simulatorId ) . toBeUndefined ( ) ;
846+ expect ( parsed . sessionDefaults ?. simulatorName ) . toBeUndefined ( ) ;
847+ } ) ;
848+
849+ it ( 'continues setup with no default simulator when simulator discovery fails' , async ( ) => {
850+ const { fs, getStoredConfig } = createSetupFs ( ) ;
851+
852+ const executor : CommandExecutor = async ( command ) => {
853+ if ( command [ 0 ] === 'xcrun' && command [ 1 ] === 'devicectl' ) {
854+ throw new Error ( 'device lookup should not run for simulator-only workflows' ) ;
855+ }
856+
857+ if ( command [ 0 ] === 'xcrun' && command [ 1 ] === 'simctl' ) {
858+ throw new Error ( 'simctl unavailable' ) ;
859+ }
860+
861+ return createMockCommandResponse ( {
862+ success : true ,
863+ output : `Information about workspace "App":\n Schemes:\n App` ,
864+ } ) ;
865+ } ;
866+
867+ const prompter : Prompter = {
868+ selectOne : async < T > ( opts : { options : Array < { value : T } > } ) => opts . options [ 0 ] . value ,
869+ selectMany : async < T > ( opts : { options : Array < { value : T } > } ) => {
870+ const simulatorOption = opts . options . find ( ( option ) => option . value === ( 'simulator' as T ) ) ;
871+ return simulatorOption
872+ ? [ simulatorOption . value ]
873+ : opts . options . map ( ( option ) => option . value ) ;
874+ } ,
875+ confirm : async ( opts : { defaultValue : boolean } ) => opts . defaultValue ,
876+ } ;
877+
878+ await runSetupWizard ( {
879+ cwd,
880+ fs,
881+ executor,
882+ prompter,
883+ quietOutput : true ,
884+ } ) ;
885+
886+ const parsed = parseYaml ( getStoredConfig ( ) ) as {
887+ sessionDefaults ?: Record < string , unknown > ;
888+ } ;
889+
890+ expect ( parsed . sessionDefaults ?. simulatorId ) . toBeUndefined ( ) ;
891+ expect ( parsed . sessionDefaults ?. simulatorName ) . toBeUndefined ( ) ;
892+ } ) ;
893+
744894 it ( 'continues setup with no default simulator when no simulators are available' , async ( ) => {
745895 const { fs, getStoredConfig } = createSetupFs ( ) ;
746896
0 commit comments