@@ -10,6 +10,7 @@ import {
1010 createMockExecutor ,
1111 createMockFileSystemExecutor ,
1212 createCommandMatchingMockExecutor ,
13+ mockProcess ,
1314} from '../../../../test-utils/mock-executors.ts' ;
1415import type { CommandExecutor } from '../../../../utils/execution/index.ts' ;
1516import { SystemError } from '../../../../utils/responses/index.ts' ;
@@ -48,18 +49,34 @@ describe('screenshot plugin', () => {
4849 } ) ;
4950
5051 describe ( 'Command Generation' , ( ) => {
52+ // Mock device list JSON for proper device name lookup
53+ const mockDeviceListJson = JSON . stringify ( {
54+ devices : {
55+ 'com.apple.CoreSimulator.SimRuntime.iOS-17-2' : [
56+ { udid : 'test-uuid' , name : 'iPhone 15 Pro' , state : 'Booted' } ,
57+ { udid : 'another-uuid' , name : 'iPhone 15' , state : 'Booted' } ,
58+ ] ,
59+ } ,
60+ } ) ;
61+
5162 it ( 'should generate correct simctl and sips commands' , async ( ) => {
5263 const capturedCommands : string [ ] [ ] = [ ] ;
5364
54- const mockExecutor = createCommandMatchingMockExecutor ( {
55- 'xcrun simctl' : { success : true , output : 'Screenshot saved' } ,
56- sips : { success : true , output : 'Image optimized' } ,
57- } ) ;
58-
59- // Wrap to capture both commands
65+ // Wrap to capture commands and return appropriate mock responses
6066 const capturingExecutor = async ( command : string [ ] , ...args : any [ ] ) => {
6167 capturedCommands . push ( command ) ;
62- return mockExecutor ( command , ...args ) ;
68+ const cmdStr = command . join ( ' ' ) ;
69+ // Return device list JSON for list command
70+ if ( cmdStr . includes ( 'simctl list devices' ) ) {
71+ return {
72+ success : true ,
73+ output : mockDeviceListJson ,
74+ error : undefined ,
75+ process : mockProcess ,
76+ } ;
77+ }
78+ // Return success for all other commands
79+ return { success : true , output : '' , error : undefined , process : mockProcess } ;
6380 } ;
6481
6582 const mockFileSystemExecutor = createMockFileSystemExecutor ( {
@@ -85,8 +102,8 @@ describe('screenshot plugin', () => {
85102 mockUuidDeps ,
86103 ) ;
87104
88- // Should execute both commands in sequence
89- expect ( capturedCommands ) . toHaveLength ( 2 ) ;
105+ // Should execute all commands in sequence: screenshot, list devices, orientation detection, optimization
106+ expect ( capturedCommands ) . toHaveLength ( 4 ) ;
90107
91108 // First command: xcrun simctl screenshot
92109 expect ( capturedCommands [ 0 ] ) . toEqual ( [
@@ -98,8 +115,17 @@ describe('screenshot plugin', () => {
98115 '/tmp/screenshot_mock-uuid-123.png' ,
99116 ] ) ;
100117
101- // Second command: sips optimization
102- expect ( capturedCommands [ 1 ] ) . toEqual ( [
118+ // Second command: xcrun simctl list devices (to get device name)
119+ expect ( capturedCommands [ 1 ] [ 0 ] ) . toBe ( 'xcrun' ) ;
120+ expect ( capturedCommands [ 1 ] [ 1 ] ) . toBe ( 'simctl' ) ;
121+ expect ( capturedCommands [ 1 ] [ 2 ] ) . toBe ( 'list' ) ;
122+
123+ // Third command: swift orientation detection
124+ expect ( capturedCommands [ 2 ] [ 0 ] ) . toBe ( 'swift' ) ;
125+ expect ( capturedCommands [ 2 ] [ 1 ] ) . toBe ( '-e' ) ;
126+
127+ // Fourth command: sips optimization
128+ expect ( capturedCommands [ 3 ] ) . toEqual ( [
103129 'sips' ,
104130 '-Z' ,
105131 '800' ,
@@ -118,15 +144,21 @@ describe('screenshot plugin', () => {
118144 it ( 'should generate correct path with different uuid' , async ( ) => {
119145 const capturedCommands : string [ ] [ ] = [ ] ;
120146
121- const mockExecutor = createCommandMatchingMockExecutor ( {
122- 'xcrun simctl' : { success : true , output : 'Screenshot saved' } ,
123- sips : { success : true , output : 'Image optimized' } ,
124- } ) ;
125-
126- // Wrap to capture both commands
147+ // Wrap to capture commands and return appropriate mock responses
127148 const capturingExecutor = async ( command : string [ ] , ...args : any [ ] ) => {
128149 capturedCommands . push ( command ) ;
129- return mockExecutor ( command , ...args ) ;
150+ const cmdStr = command . join ( ' ' ) ;
151+ // Return device list JSON for list command
152+ if ( cmdStr . includes ( 'simctl list devices' ) ) {
153+ return {
154+ success : true ,
155+ output : mockDeviceListJson ,
156+ error : undefined ,
157+ process : mockProcess ,
158+ } ;
159+ }
160+ // Return success for all other commands
161+ return { success : true , output : '' , error : undefined , process : mockProcess } ;
130162 } ;
131163
132164 const mockFileSystemExecutor = createMockFileSystemExecutor ( {
@@ -152,8 +184,8 @@ describe('screenshot plugin', () => {
152184 mockUuidDeps ,
153185 ) ;
154186
155- // Should execute both commands in sequence
156- expect ( capturedCommands ) . toHaveLength ( 2 ) ;
187+ // Should execute all commands in sequence: screenshot, list devices, orientation detection, optimization
188+ expect ( capturedCommands ) . toHaveLength ( 4 ) ;
157189
158190 // First command: xcrun simctl screenshot
159191 expect ( capturedCommands [ 0 ] ) . toEqual ( [
@@ -165,8 +197,17 @@ describe('screenshot plugin', () => {
165197 '/tmp/screenshot_different-uuid-456.png' ,
166198 ] ) ;
167199
168- // Second command: sips optimization
169- expect ( capturedCommands [ 1 ] ) . toEqual ( [
200+ // Second command: xcrun simctl list devices (to get device name)
201+ expect ( capturedCommands [ 1 ] [ 0 ] ) . toBe ( 'xcrun' ) ;
202+ expect ( capturedCommands [ 1 ] [ 1 ] ) . toBe ( 'simctl' ) ;
203+ expect ( capturedCommands [ 1 ] [ 2 ] ) . toBe ( 'list' ) ;
204+
205+ // Third command: swift orientation detection
206+ expect ( capturedCommands [ 2 ] [ 0 ] ) . toBe ( 'swift' ) ;
207+ expect ( capturedCommands [ 2 ] [ 1 ] ) . toBe ( '-e' ) ;
208+
209+ // Fourth command: sips optimization
210+ expect ( capturedCommands [ 3 ] ) . toEqual ( [
170211 'sips' ,
171212 '-Z' ,
172213 '800' ,
@@ -185,15 +226,21 @@ describe('screenshot plugin', () => {
185226 it ( 'should use default dependencies when not provided' , async ( ) => {
186227 const capturedCommands : string [ ] [ ] = [ ] ;
187228
188- const mockExecutor = createCommandMatchingMockExecutor ( {
189- 'xcrun simctl' : { success : true , output : 'Screenshot saved' } ,
190- sips : { success : true , output : 'Image optimized' } ,
191- } ) ;
192-
193- // Wrap to capture both commands
229+ // Wrap to capture commands and return appropriate mock responses
194230 const capturingExecutor = async ( command : string [ ] , ...args : any [ ] ) => {
195231 capturedCommands . push ( command ) ;
196- return mockExecutor ( command , ...args ) ;
232+ const cmdStr = command . join ( ' ' ) ;
233+ // Return device list JSON for list command
234+ if ( cmdStr . includes ( 'simctl list devices' ) ) {
235+ return {
236+ success : true ,
237+ output : mockDeviceListJson ,
238+ error : undefined ,
239+ process : mockProcess ,
240+ } ;
241+ }
242+ // Return success for all other commands
243+ return { success : true , output : '' , error : undefined , process : mockProcess } ;
197244 } ;
198245
199246 const mockFileSystemExecutor = createMockFileSystemExecutor ( {
@@ -208,8 +255,8 @@ describe('screenshot plugin', () => {
208255 mockFileSystemExecutor ,
209256 ) ;
210257
211- // Should execute both commands in sequence
212- expect ( capturedCommands ) . toHaveLength ( 2 ) ;
258+ // Should execute all commands in sequence: screenshot, list devices, orientation detection, optimization
259+ expect ( capturedCommands ) . toHaveLength ( 4 ) ;
213260
214261 // First command should be generated with real os.tmpdir, path.join, and uuidv4
215262 const firstCommand = capturedCommands [ 0 ] ;
@@ -221,14 +268,23 @@ describe('screenshot plugin', () => {
221268 expect ( firstCommand [ 4 ] ) . toBe ( 'screenshot' ) ;
222269 expect ( firstCommand [ 5 ] ) . toMatch ( / \/ .* \/ s c r e e n s h o t _ .* \. p n g / ) ;
223270
224- // Second command should be sips optimization
225- const secondCommand = capturedCommands [ 1 ] ;
226- expect ( secondCommand [ 0 ] ) . toBe ( 'sips' ) ;
227- expect ( secondCommand [ 1 ] ) . toBe ( '-Z' ) ;
228- expect ( secondCommand [ 2 ] ) . toBe ( '800' ) ;
271+ // Second command should be xcrun simctl list devices
272+ expect ( capturedCommands [ 1 ] [ 0 ] ) . toBe ( 'xcrun' ) ;
273+ expect ( capturedCommands [ 1 ] [ 1 ] ) . toBe ( 'simctl' ) ;
274+ expect ( capturedCommands [ 1 ] [ 2 ] ) . toBe ( 'list' ) ;
275+
276+ // Third command should be swift orientation detection
277+ expect ( capturedCommands [ 2 ] [ 0 ] ) . toBe ( 'swift' ) ;
278+ expect ( capturedCommands [ 2 ] [ 1 ] ) . toBe ( '-e' ) ;
279+
280+ // Fourth command should be sips optimization
281+ const thirdCommand = capturedCommands [ 3 ] ;
282+ expect ( thirdCommand [ 0 ] ) . toBe ( 'sips' ) ;
283+ expect ( thirdCommand [ 1 ] ) . toBe ( '-Z' ) ;
284+ expect ( thirdCommand [ 2 ] ) . toBe ( '800' ) ;
229285 // Should have proper PNG input and JPG output paths
230- expect ( secondCommand [ secondCommand . length - 3 ] ) . toMatch ( / \/ .* \/ s c r e e n s h o t _ .* \. p n g / ) ;
231- expect ( secondCommand [ secondCommand . length - 1 ] ) . toMatch ( / \/ .* \/ s c r e e n s h o t _ o p t i m i z e d _ .* \. j p g / ) ;
286+ expect ( thirdCommand [ thirdCommand . length - 3 ] ) . toMatch ( / \/ .* \/ s c r e e n s h o t _ .* \. p n g / ) ;
287+ expect ( thirdCommand [ thirdCommand . length - 1 ] ) . toMatch ( / \/ .* \/ s c r e e n s h o t _ o p t i m i z e d _ .* \. j p g / ) ;
232288 } ) ;
233289 } ) ;
234290
@@ -370,15 +426,31 @@ describe('screenshot plugin', () => {
370426 it ( 'should call correct command with direct execution' , async ( ) => {
371427 const capturedArgs : any [ ] [ ] = [ ] ;
372428
373- const mockExecutor = createCommandMatchingMockExecutor ( {
374- 'xcrun simctl' : { success : true , output : 'Screenshot saved' } ,
375- sips : { success : true , output : 'Image optimized' } ,
429+ // Mock device list JSON for proper device name lookup
430+ const mockDeviceListJson = JSON . stringify ( {
431+ devices : {
432+ 'com.apple.CoreSimulator.SimRuntime.iOS-17-2' : [
433+ { udid : 'test-uuid' , name : 'iPhone 15 Pro' , state : 'Booted' } ,
434+ ] ,
435+ } ,
376436 } ) ;
377437
378- // Wrap to capture both command executions
438+ // Capture all command executions and return appropriate mock responses
379439 const capturingExecutor : CommandExecutor = async ( ...args ) => {
380440 capturedArgs . push ( args ) ;
381- return mockExecutor ( ...args ) ;
441+ const command = args [ 0 ] as string [ ] ;
442+ const cmdStr = command . join ( ' ' ) ;
443+ // Return device list JSON for list command
444+ if ( cmdStr . includes ( 'simctl list devices' ) ) {
445+ return {
446+ success : true ,
447+ output : mockDeviceListJson ,
448+ error : undefined ,
449+ process : mockProcess ,
450+ } ;
451+ }
452+ // Return success for all other commands
453+ return { success : true , output : '' , error : undefined , process : mockProcess } ;
382454 } ;
383455
384456 const mockFileSystemExecutor = createMockFileSystemExecutor ( {
@@ -404,8 +476,8 @@ describe('screenshot plugin', () => {
404476 mockUuidDeps ,
405477 ) ;
406478
407- // Should capture both command executions
408- expect ( capturedArgs ) . toHaveLength ( 2 ) ;
479+ // Should capture all command executions: screenshot, list devices, orientation detection, optimization
480+ expect ( capturedArgs ) . toHaveLength ( 4 ) ;
409481
410482 // First call: xcrun simctl screenshot (3 args: command, logPrefix, useShell)
411483 expect ( capturedArgs [ 0 ] ) . toEqual ( [
@@ -414,8 +486,21 @@ describe('screenshot plugin', () => {
414486 false ,
415487 ] ) ;
416488
417- // Second call: sips optimization (3 args: command, logPrefix, useShell)
418- expect ( capturedArgs [ 1 ] ) . toEqual ( [
489+ // Second call: xcrun simctl list devices (to get device name)
490+ expect ( capturedArgs [ 1 ] [ 0 ] [ 0 ] ) . toBe ( 'xcrun' ) ;
491+ expect ( capturedArgs [ 1 ] [ 0 ] [ 1 ] ) . toBe ( 'simctl' ) ;
492+ expect ( capturedArgs [ 1 ] [ 0 ] [ 2 ] ) . toBe ( 'list' ) ;
493+ expect ( capturedArgs [ 1 ] [ 1 ] ) . toBe ( '[Screenshot]: list devices' ) ;
494+ expect ( capturedArgs [ 1 ] [ 2 ] ) . toBe ( false ) ;
495+
496+ // Third call: swift orientation detection
497+ expect ( capturedArgs [ 2 ] [ 0 ] [ 0 ] ) . toBe ( 'swift' ) ;
498+ expect ( capturedArgs [ 2 ] [ 0 ] [ 1 ] ) . toBe ( '-e' ) ;
499+ expect ( capturedArgs [ 2 ] [ 1 ] ) . toBe ( '[Screenshot]: detect orientation' ) ;
500+ expect ( capturedArgs [ 2 ] [ 2 ] ) . toBe ( false ) ;
501+
502+ // Fourth call: sips optimization (3 args: command, logPrefix, useShell)
503+ expect ( capturedArgs [ 3 ] ) . toEqual ( [
419504 [
420505 'sips' ,
421506 '-Z' ,
0 commit comments