@@ -2,9 +2,12 @@ import { assert, use } from 'chai';
22import chaiAsPromised from 'chai-as-promised' ;
33import { anything , instance , mock , when , verify , deepEqual } from 'ts-mockito' ;
44import { Uri } from 'vscode' ;
5+ import * as fs from 'fs' ;
6+ import * as os from 'os' ;
57import { DeepnoteEnvironmentManager } from './deepnoteEnvironmentManager.node' ;
68import { DeepnoteEnvironmentStorage } from './deepnoteEnvironmentStorage.node' ;
79import { IExtensionContext , IOutputChannel } from '../../../platform/common/types' ;
10+ import { IFileSystem } from '../../../platform/common/platform/types' ;
811import {
912 IDeepnoteServerStarter ,
1013 IDeepnoteToolkitInstaller ,
@@ -24,6 +27,8 @@ suite('DeepnoteEnvironmentManager', () => {
2427 let mockToolkitInstaller : IDeepnoteToolkitInstaller ;
2528 let mockServerStarter : IDeepnoteServerStarter ;
2629 let mockOutputChannel : IOutputChannel ;
30+ let mockFileSystem : IFileSystem ;
31+ let testGlobalStoragePath : string ;
2732
2833 const testInterpreter : PythonEnvironment = {
2934 id : 'test-python-id' ,
@@ -49,19 +54,40 @@ suite('DeepnoteEnvironmentManager', () => {
4954 mockToolkitInstaller = mock < IDeepnoteToolkitInstaller > ( ) ;
5055 mockServerStarter = mock < IDeepnoteServerStarter > ( ) ;
5156 mockOutputChannel = mock < IOutputChannel > ( ) ;
57+ mockFileSystem = mock < IFileSystem > ( ) ;
5258
53- when ( mockContext . globalStorageUri ) . thenReturn ( Uri . file ( '/global/storage' ) ) ;
59+ // Create a temporary directory for test storage
60+ testGlobalStoragePath = fs . mkdtempSync ( `${ os . tmpdir ( ) } /deepnote-test-` ) ;
61+
62+ when ( mockContext . globalStorageUri ) . thenReturn ( Uri . file ( testGlobalStoragePath ) ) ;
5463 when ( mockStorage . loadEnvironments ( ) ) . thenResolve ( [ ] ) ;
5564
65+ // Configure mockFileSystem to actually delete directories for testing
66+ when ( mockFileSystem . delete ( anything ( ) ) ) . thenCall ( ( uri : Uri ) => {
67+ const dirPath = uri . fsPath ;
68+ if ( fs . existsSync ( dirPath ) ) {
69+ fs . rmSync ( dirPath , { recursive : true , force : true } ) ;
70+ }
71+ return Promise . resolve ( ) ;
72+ } ) ;
73+
5674 manager = new DeepnoteEnvironmentManager (
5775 instance ( mockContext ) ,
5876 instance ( mockStorage ) ,
5977 instance ( mockToolkitInstaller ) ,
6078 instance ( mockServerStarter ) ,
61- instance ( mockOutputChannel )
79+ instance ( mockOutputChannel ) ,
80+ instance ( mockFileSystem )
6281 ) ;
6382 } ) ;
6483
84+ teardown ( ( ) => {
85+ // Clean up the temporary directory after each test
86+ if ( testGlobalStoragePath && fs . existsSync ( testGlobalStoragePath ) ) {
87+ fs . rmSync ( testGlobalStoragePath , { recursive : true , force : true } ) ;
88+ }
89+ } ) ;
90+
6591 suite ( 'activate' , ( ) => {
6692 test ( 'should load environments on activation' , async ( ) => {
6793 const existingConfigs = [
@@ -312,6 +338,33 @@ suite('DeepnoteEnvironmentManager', () => {
312338 test ( 'should throw error for non-existent environment' , async ( ) => {
313339 await assert . isRejected ( manager . deleteEnvironment ( 'non-existent' ) , 'Environment not found: non-existent' ) ;
314340 } ) ;
341+
342+ test ( 'should delete virtual environment directory from disk' , async ( ) => {
343+ when ( mockStorage . saveEnvironments ( anything ( ) ) ) . thenResolve ( ) ;
344+
345+ const config = await manager . createEnvironment ( {
346+ name : 'Test' ,
347+ pythonInterpreter : testInterpreter
348+ } ) ;
349+
350+ // Create the virtual environment directory to simulate it existing
351+ const venvDirPath = config . venvPath . fsPath ;
352+ fs . mkdirSync ( venvDirPath , { recursive : true } ) ;
353+
354+ // Create a dummy file inside to make it a "real" directory
355+ fs . writeFileSync ( `${ venvDirPath } /test.txt` , 'test content' ) ;
356+
357+ // Verify directory and file exist before deletion
358+ assert . isTrue ( fs . existsSync ( venvDirPath ) , 'Directory should exist before deletion' ) ;
359+ assert . isTrue ( fs . existsSync ( `${ venvDirPath } /test.txt` ) , 'File should exist before deletion' ) ;
360+
361+ // Delete the environment
362+ await manager . deleteEnvironment ( config . id ) ;
363+
364+ // Verify directory no longer exists (with a small delay to allow async operation)
365+ await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
366+ assert . isFalse ( fs . existsSync ( venvDirPath ) , 'Directory should not exist after deletion' ) ;
367+ } ) ;
315368 } ) ;
316369
317370 suite ( 'startServer' , ( ) => {
0 commit comments