@@ -28,6 +28,7 @@ import { getErrorMessage } from '../../utils/errors.js';
2828// Hoisted mocks - these survive vi.clearAllMocks()
2929const mockUninstallExtension = vi . hoisted ( ( ) => vi . fn ( ) ) ;
3030const mockLoadExtensions = vi . hoisted ( ( ) => vi . fn ( ) ) ;
31+ const mockGetExtensions = vi . hoisted ( ( ) => vi . fn ( ) ) ;
3132
3233// Mock dependencies with hoisted functions
3334vi . mock ( '../../config/extension-manager.js' , async ( importOriginal ) => {
@@ -38,6 +39,7 @@ vi.mock('../../config/extension-manager.js', async (importOriginal) => {
3839 ExtensionManager : vi . fn ( ) . mockImplementation ( ( ) => ( {
3940 uninstallExtension : mockUninstallExtension ,
4041 loadExtensions : mockLoadExtensions ,
42+ getExtensions : mockGetExtensions ,
4143 setRequestConsent : vi . fn ( ) ,
4244 setRequestSetting : vi . fn ( ) ,
4345 } ) ) ,
@@ -93,6 +95,7 @@ describe('extensions uninstall command', () => {
9395 afterEach ( ( ) => {
9496 mockLoadExtensions . mockClear ( ) ;
9597 mockUninstallExtension . mockClear ( ) ;
98+ mockGetExtensions . mockClear ( ) ;
9699 vi . clearAllMocks ( ) ;
97100 } ) ;
98101
@@ -145,6 +148,41 @@ describe('extensions uninstall command', () => {
145148 mockCwd . mockRestore ( ) ;
146149 } ) ;
147150
151+ it ( 'should uninstall all extensions when --all flag is used' , async ( ) => {
152+ mockLoadExtensions . mockResolvedValue ( undefined ) ;
153+ mockUninstallExtension . mockResolvedValue ( undefined ) ;
154+ mockGetExtensions . mockReturnValue ( [ { name : 'ext1' } , { name : 'ext2' } ] ) ;
155+ const mockCwd = vi . spyOn ( process , 'cwd' ) . mockReturnValue ( '/test/dir' ) ;
156+ await handleUninstall ( { all : true } ) ;
157+
158+ expect ( mockUninstallExtension ) . toHaveBeenCalledTimes ( 2 ) ;
159+ expect ( mockUninstallExtension ) . toHaveBeenCalledWith ( 'ext1' , false ) ;
160+ expect ( mockUninstallExtension ) . toHaveBeenCalledWith ( 'ext2' , false ) ;
161+ expect ( emitConsoleLog ) . toHaveBeenCalledWith (
162+ 'log' ,
163+ 'Extension "ext1" successfully uninstalled.' ,
164+ ) ;
165+ expect ( emitConsoleLog ) . toHaveBeenCalledWith (
166+ 'log' ,
167+ 'Extension "ext2" successfully uninstalled.' ,
168+ ) ;
169+ mockCwd . mockRestore ( ) ;
170+ } ) ;
171+
172+ it ( 'should log a message if no extensions are installed and --all flag is used' , async ( ) => {
173+ mockLoadExtensions . mockResolvedValue ( undefined ) ;
174+ mockGetExtensions . mockReturnValue ( [ ] ) ;
175+ const mockCwd = vi . spyOn ( process , 'cwd' ) . mockReturnValue ( '/test/dir' ) ;
176+ await handleUninstall ( { all : true } ) ;
177+
178+ expect ( mockUninstallExtension ) . not . toHaveBeenCalled ( ) ;
179+ expect ( emitConsoleLog ) . toHaveBeenCalledWith (
180+ 'log' ,
181+ 'No extensions currently installed.' ,
182+ ) ;
183+ mockCwd . mockRestore ( ) ;
184+ } ) ;
185+
148186 it ( 'should report errors for failed uninstalls but continue with others' , async ( ) => {
149187 mockLoadExtensions . mockResolvedValue ( undefined ) ;
150188 const mockCwd = vi . spyOn ( process , 'cwd' ) . mockReturnValue ( '/test/dir' ) ;
@@ -236,25 +274,27 @@ describe('extensions uninstall command', () => {
236274 const command = uninstallCommand ;
237275
238276 it ( 'should have correct command and describe' , ( ) => {
239- expect ( command . command ) . toBe ( 'uninstall < names..> ' ) ;
277+ expect ( command . command ) . toBe ( 'uninstall [ names..] ' ) ;
240278 expect ( command . describe ) . toBe ( 'Uninstalls one or more extensions.' ) ;
241279 } ) ;
242280
243281 describe ( 'builder' , ( ) => {
244282 interface MockYargs {
245283 positional : Mock ;
284+ option : Mock ;
246285 check : Mock ;
247286 }
248287
249288 let yargsMock : MockYargs ;
250289 beforeEach ( ( ) => {
251290 yargsMock = {
252291 positional : vi . fn ( ) . mockReturnThis ( ) ,
292+ option : vi . fn ( ) . mockReturnThis ( ) ,
253293 check : vi . fn ( ) . mockReturnThis ( ) ,
254294 } ;
255295 } ) ;
256296
257- it ( 'should configure positional argument ' , ( ) => {
297+ it ( 'should configure arguments and options ' , ( ) => {
258298 ( command . builder as ( yargs : Argv ) => Argv ) (
259299 yargsMock as unknown as Argv ,
260300 ) ;
@@ -264,17 +304,30 @@ describe('extensions uninstall command', () => {
264304 type : 'string' ,
265305 array : true ,
266306 } ) ;
307+ expect ( yargsMock . option ) . toHaveBeenCalledWith ( 'all' , {
308+ type : 'boolean' ,
309+ describe : 'Uninstall all installed extensions.' ,
310+ default : false ,
311+ } ) ;
267312 expect ( yargsMock . check ) . toHaveBeenCalled ( ) ;
268313 } ) ;
269314
270- it ( 'check function should throw for missing names' , ( ) => {
315+ it ( 'check function should throw for missing names and no --all flag ' , ( ) => {
271316 ( command . builder as ( yargs : Argv ) => Argv ) (
272317 yargsMock as unknown as Argv ,
273318 ) ;
274319 const checkCallback = yargsMock . check . mock . calls [ 0 ] [ 0 ] ;
275- expect ( ( ) => checkCallback ( { names : [ ] } ) ) . toThrow (
276- 'Please include at least one extension name to uninstall as a positional argument.' ,
320+ expect ( ( ) => checkCallback ( { names : [ ] , all : false } ) ) . toThrow (
321+ 'Please include at least one extension name to uninstall as a positional argument, or use the --all flag.' ,
322+ ) ;
323+ } ) ;
324+
325+ it ( 'check function should pass if --all flag is used even without names' , ( ) => {
326+ ( command . builder as ( yargs : Argv ) => Argv ) (
327+ yargsMock as unknown as Argv ,
277328 ) ;
329+ const checkCallback = yargsMock . check . mock . calls [ 0 ] [ 0 ] ;
330+ expect ( ( ) => checkCallback ( { names : [ ] , all : true } ) ) . not . toThrow ( ) ;
278331 } ) ;
279332 } ) ;
280333
@@ -283,10 +336,17 @@ describe('extensions uninstall command', () => {
283336 mockUninstallExtension . mockResolvedValue ( undefined ) ;
284337 const mockCwd = vi . spyOn ( process , 'cwd' ) . mockReturnValue ( '/test/dir' ) ;
285338 interface TestArgv {
286- names : string [ ] ;
287- [ key : string ] : unknown ;
339+ names ?: string [ ] ;
340+ all ?: boolean ;
341+ _ : string [ ] ;
342+ $0 : string ;
288343 }
289- const argv : TestArgv = { names : [ 'my-extension' ] , _ : [ ] , $0 : '' } ;
344+ const argv : TestArgv = {
345+ names : [ 'my-extension' ] ,
346+ all : false ,
347+ _ : [ ] ,
348+ $0 : '' ,
349+ } ;
290350 await ( command . handler as unknown as ( args : TestArgv ) => Promise < void > ) (
291351 argv ,
292352 ) ;
0 commit comments