@@ -171,4 +171,179 @@ describe('SentryCli helper', () => {
171171 ] ) ;
172172 } ) ;
173173 } ) ;
174+
175+ describe ( 'silentLogs functionality' , ( ) => {
176+ let consoleInfoSpy ;
177+ let consoleErrorSpy ;
178+
179+ beforeEach ( ( ) => {
180+ consoleInfoSpy = jest . spyOn ( console , 'info' ) . mockImplementation ( ) ;
181+ consoleErrorSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ) ;
182+ } ) ;
183+
184+ afterEach ( ( ) => {
185+ consoleInfoSpy . mockRestore ( ) ;
186+ consoleErrorSpy . mockRestore ( ) ;
187+ } ) ;
188+
189+ test ( 'determineSuccessMessage returns correct message for releases new' , ( ) => {
190+ const args = [ 'releases' , 'new' , 'v1.0.0' ] ;
191+ const message = helper . determineSuccessMessage ( args ) ;
192+ expect ( message ) . toBe ( '✓ Release v1.0.0 created' ) ;
193+ } ) ;
194+
195+ test ( 'determineSuccessMessage returns correct message for sourcemaps upload' , ( ) => {
196+ const args = [ 'sourcemaps' , 'upload' ] ;
197+ const message = helper . determineSuccessMessage ( args ) ;
198+ expect ( message ) . toBe ( '✓ Source maps uploaded' ) ;
199+ } ) ;
200+
201+ test ( 'determineSuccessMessage returns null for version check' , ( ) => {
202+ const args = [ '--version' ] ;
203+ const message = helper . determineSuccessMessage ( args ) ;
204+ expect ( message ) . toBe ( null ) ;
205+ } ) ;
206+
207+ test ( 'determineSuccessMessage handles empty args' , ( ) => {
208+ const message = helper . determineSuccessMessage ( [ ] ) ;
209+ expect ( message ) . toBe ( null ) ;
210+ } ) ;
211+
212+ test ( 'determineSuccessMessage handles null args' , ( ) => {
213+ const message = helper . determineSuccessMessage ( null ) ;
214+ expect ( message ) . toBe ( null ) ;
215+ } ) ;
216+
217+ test ( 'execute with silent=true takes precedence over silentLogs=true' , async ( ) => {
218+ const result = await helper . execute ( [ '--version' ] , false , true , true ) ;
219+
220+ expect ( result ) . toBe ( '' ) ;
221+ expect ( consoleInfoSpy ) . not . toHaveBeenCalled ( ) ;
222+ } ) ;
223+ } ) ;
224+
225+ describe ( 'command type coverage' , ( ) => {
226+ test ( 'determineSuccessMessage handles supported high-impact commands' , ( ) => {
227+ const testCases = [
228+ { args : [ 'releases' , 'new' , 'v1.0.0' ] , expected : '✓ Release v1.0.0 created' } ,
229+ { args : [ 'releases' , 'finalize' , 'v1.0.0' ] , expected : '✓ Release v1.0.0 finalized' } ,
230+ {
231+ args : [ 'releases' , 'files' , 'v1.0.0' , 'upload-sourcemaps' ] ,
232+ expected : '✓ Source maps uploaded to release v1.0.0' ,
233+ } ,
234+ { args : [ 'sourcemaps' , 'upload' ] , expected : '✓ Source maps uploaded' } ,
235+ { args : [ 'sourcemaps' , 'inject' ] , expected : '✓ Source maps injected' } ,
236+ { args : [ 'debug-files' , 'upload' ] , expected : '✓ Debug files uploaded' } ,
237+ { args : [ 'upload-proguard' ] , expected : '✓ ProGuard mappings uploaded' } ,
238+ { args : [ 'upload-dif' ] , expected : '✓ Debug information files uploaded' } ,
239+ { args : [ 'upload-dsym' ] , expected : '✓ dSYM files uploaded' } ,
240+ { args : [ 'deploys' , 'new' ] , expected : '✓ Deploy created' } ,
241+ { args : [ 'mobile-app' , 'upload' ] , expected : '✓ Mobile app uploaded' } ,
242+ { args : [ 'send-event' ] , expected : '✓ Event sent' } ,
243+ { args : [ 'send-envelope' ] , expected : '✓ Envelope sent' } ,
244+ { args : [ 'send-metric' ] , expected : '✓ Metric sent' } ,
245+ ] ;
246+
247+ testCases . forEach ( ( { args, expected } ) => {
248+ const message = helper . determineSuccessMessage ( args ) ;
249+ expect ( message ) . toBe ( expected ) ;
250+ } ) ;
251+ } ) ;
252+
253+ test ( 'determineSuccessMessage returns null for info/list operations and utility commands' , ( ) => {
254+ const testCases = [
255+ [ '--help' ] ,
256+ [ '--version' ] ,
257+ [ 'info' ] ,
258+ [ 'login' ] ,
259+ [ 'organizations' , 'list' ] ,
260+ [ 'projects' , 'list' ] ,
261+ [ 'issues' , 'list' ] ,
262+ [ 'events' , 'list' ] ,
263+ [ 'files' , 'list' ] ,
264+ [ 'deploys' , 'list' ] ,
265+ [ 'monitors' , 'list' ] ,
266+ [ 'releases' , 'list' ] ,
267+ [ 'releases' , 'delete' , 'v1.0.0' ] ,
268+ [ 'unknown-command' ] ,
269+ ] ;
270+
271+ testCases . forEach ( ( args ) => {
272+ const message = helper . determineSuccessMessage ( args ) ;
273+ expect ( message ) . toBe ( null ) ;
274+ } ) ;
275+ } ) ;
276+ } ) ;
277+
278+ describe ( 'Promise resolution scenarios' , ( ) => {
279+ let consoleInfoSpy ;
280+
281+ beforeEach ( ( ) => {
282+ consoleInfoSpy = jest . spyOn ( console , 'info' ) . mockImplementation ( ) ;
283+ } ) ;
284+
285+ afterEach ( ( ) => {
286+ consoleInfoSpy . mockRestore ( ) ;
287+ } ) ;
288+
289+ test ( 'execute with live=true, silentLogs=true uses stdio piping and resolves with undefined' , async ( ) => {
290+ const result = await helper . execute ( [ '--version' ] , true , false , true ) ;
291+
292+ expect ( result ) . toBeUndefined ( ) ;
293+ expect ( consoleInfoSpy ) . not . toHaveBeenCalled ( ) ; // --version doesn't have success message
294+ } ) ;
295+
296+ test ( 'execute with live=true, silentLogs=true shows success message for supported commands' , async ( ) => {
297+ const result = await helper . execute ( [ 'sourcemaps' , 'upload' ] , true , false , true ) ;
298+
299+ expect ( result ) . toBeUndefined ( ) ;
300+ expect ( consoleInfoSpy ) . toHaveBeenCalledWith ( '✓ Source maps uploaded' ) ;
301+ } ) ;
302+
303+ test ( 'execute with live=false, silentLogs=true uses callback mode and resolves with empty string' , async ( ) => {
304+ const result = await helper . execute ( [ '--version' ] , false , false , true ) ;
305+
306+ expect ( result ) . toBe ( '' ) ;
307+ expect ( consoleInfoSpy ) . not . toHaveBeenCalled ( ) ;
308+ } ) ;
309+
310+ test ( 'execute with live=false, silentLogs=true shows success message and returns empty string' , async ( ) => {
311+ const result = await helper . execute ( [ 'sourcemaps' , 'upload' ] , false , false , true ) ;
312+
313+ expect ( result ) . toBe ( '' ) ;
314+ expect ( consoleInfoSpy ) . toHaveBeenCalledWith ( '✓ Source maps uploaded' ) ;
315+ } ) ;
316+
317+ test ( 'execute with normal mode (live=false, silent=false, silentLogs=false) returns actual stdout' , async ( ) => {
318+ const result = await helper . execute ( [ '--version' ] , false , false , false ) ;
319+
320+ expect ( result . trim ( ) ) . toBe ( 'sentry-cli DEV' ) ;
321+ expect ( consoleInfoSpy ) . not . toHaveBeenCalled ( ) ;
322+ } ) ;
323+
324+ test ( 'execute with silent=true suppresses output and messages' , async ( ) => {
325+ // Test with live=true - uses stdio piping, resolves with undefined
326+ const result1 = await helper . execute ( [ '--version' ] , true , true , false ) ;
327+ expect ( result1 ) . toBeUndefined ( ) ;
328+
329+ // Test with live=false - uses callback mode, resolves with empty string
330+ const result2 = await helper . execute ( [ '--version' ] , false , true , false ) ;
331+ expect ( result2 ) . toBe ( '' ) ;
332+
333+ // Test with silentLogs=true (should be ignored when silent=true)
334+ const result3 = await helper . execute ( [ 'sourcemaps' , 'upload' ] , false , true , true ) ;
335+ expect ( result3 ) . toBe ( '' ) ;
336+
337+ // No success messages should be shown when silent=true
338+ expect ( consoleInfoSpy ) . not . toHaveBeenCalled ( ) ;
339+ } ) ;
340+
341+ test ( 'execute with live=true and normal mode uses stdio inherit and resolves with undefined' , async ( ) => {
342+ const result = await helper . execute ( [ '--version' ] , true , false , false ) ;
343+
344+ // Should resolve with undefined (stdio inherit mode)
345+ expect ( result ) . toBeUndefined ( ) ;
346+ expect ( consoleInfoSpy ) . not . toHaveBeenCalled ( ) ;
347+ } ) ;
348+ } ) ;
174349} ) ;
0 commit comments