@@ -61,6 +61,9 @@ suite('DdevUtils Test Suite', () => {
6161
6262 assert . strictEqual ( result , true ) ;
6363 assert . strictEqual ( execSyncStub . calledOnce , true ) ;
64+ // Verify it uses execDdev wrapper
65+ const callArgs = execSyncStub . firstCall . args ;
66+ assert . ok ( callArgs [ 0 ] . includes ( "bash -c 'XDEBUG_MODE=off echo \"test\"'" ) ) ;
6467 } ) ;
6568
6669 test ( 'isDdevRunning returns false when DDEV container is not running' , ( ) => {
@@ -78,6 +81,9 @@ suite('DdevUtils Test Suite', () => {
7881
7982 assert . strictEqual ( result , true ) ;
8083 assert . strictEqual ( execSyncStub . calledOnce , true ) ;
84+ // Verify it uses execDdev wrapper
85+ const callArgs = execSyncStub . firstCall . args ;
86+ assert . ok ( callArgs [ 0 ] . includes ( "bash -c 'XDEBUG_MODE=off phpmd --version'" ) ) ;
8187 } ) ;
8288
8389 test ( 'isToolInstalled returns false when tool is not available' , ( ) => {
@@ -113,19 +119,17 @@ suite('DdevUtils Test Suite', () => {
113119 test ( 'validateDdevTool returns error message for DDEV issues' , ( ) => {
114120 // First call (hasDdevProject) succeeds
115121 execSyncStub . onFirstCall ( ) . returns ( 'exists\n' ) ;
116- // Second call (tool version check) fails
117- execSyncStub . onSecondCall ( ) . throws ( new Error ( 'Tool not available' ) ) ;
118- // Third call (error details) returns error
119- execSyncStub . onThirdCall ( ) . throws ( {
120- message : 'DDEV project not currently running' ,
121- stderr : 'not currently running'
122- } ) ;
122+ // Second call (tool version check) fails with specific error
123+ const error = new Error ( 'DDEV project not currently running' ) as any ;
124+ error . stderr = 'not currently running' ;
125+ execSyncStub . onSecondCall ( ) . throws ( error ) ;
123126
124127 const result = DdevUtils . validateDdevTool ( 'phpmd' , '/test/workspace' ) ;
125128
126129 assert . strictEqual ( result . isValid , false ) ;
127130 assert . strictEqual ( result . errorType , 'unknown' ) ;
128131 assert . ok ( result . userMessage ?. includes ( 'PHPMD not available' ) ) ;
132+ assert . ok ( result . userMessage ?. includes ( 'DDEV appears to be stopped' ) ) ;
129133 } ) ;
130134
131135 test ( 'execDdev returns output when command succeeds' , ( ) => {
@@ -136,6 +140,9 @@ suite('DdevUtils Test Suite', () => {
136140
137141 assert . strictEqual ( result , expectedOutput ) ;
138142 assert . strictEqual ( execSyncStub . calledOnce , true ) ;
143+
144+ const callArgs = execSyncStub . firstCall . args ;
145+ assert . ok ( callArgs [ 0 ] . includes ( "bash -c 'XDEBUG_MODE=off phpmd test.php json cleancode'" ) ) ;
139146 } ) ;
140147
141148 test ( 'execDdev returns stdout when command fails but has output' , ( ) => {
@@ -156,4 +163,16 @@ suite('DdevUtils Test Suite', () => {
156163 DdevUtils . execDdev ( 'phpmd test.php json cleancode' , '/test/workspace' ) ;
157164 } , / C o m m a n d f a i l e d / ) ;
158165 } ) ;
166+
167+ test ( 'execDdev escapes single quotes in command' , ( ) => {
168+ execSyncStub . returns ( 'output' ) ;
169+
170+ DdevUtils . execDdev ( "echo 'hello'" , '/test/workspace' ) ;
171+
172+ assert . strictEqual ( execSyncStub . calledOnce , true ) ;
173+ const callArgs = execSyncStub . firstCall . args ;
174+ // echo 'hello' -> echo '\''hello'\''
175+ // wrapped: bash -c 'XDEBUG_MODE=off echo '\''hello'\'''
176+ assert . ok ( callArgs [ 0 ] . includes ( "echo '\\''hello'\\''" ) ) ;
177+ } ) ;
159178} ) ;
0 commit comments