@@ -6,7 +6,15 @@ import { expect } from 'chai';
6
6
import * as path from 'path' ;
7
7
import * as sinon from 'sinon' ;
8
8
import * as TypeMoq from 'typemoq' ;
9
- import { ConfigurationTarget , OpenDialogOptions , QuickPick , QuickPickItem , QuickPickItemKind , Uri } from 'vscode' ;
9
+ import {
10
+ ConfigurationTarget ,
11
+ OpenDialogOptions ,
12
+ QuickPick ,
13
+ QuickPickItem ,
14
+ QuickPickItemKind ,
15
+ Uri ,
16
+ WorkspaceFolder ,
17
+ } from 'vscode' ;
10
18
import { cloneDeep } from 'lodash' ;
11
19
import { instance , mock , verify , when } from 'ts-mockito' ;
12
20
import { IApplicationShell , ICommandManager , IWorkspaceService } from '../../../../client/common/application/types' ;
@@ -127,6 +135,7 @@ suite('Set Interpreter Command', () => {
127
135
alwaysShow : true ,
128
136
} ;
129
137
const currentPythonPath = 'python' ;
138
+ const workspacePath = 'path/to/workspace' ;
130
139
131
140
setup ( ( ) => {
132
141
_enterOrBrowseInterpreterPath = sinon . stub (
@@ -161,6 +170,10 @@ suite('Set Interpreter Command', () => {
161
170
} ) ,
162
171
) ;
163
172
173
+ workspace
174
+ . setup ( ( w ) => w . getWorkspaceFolder ( TypeMoq . It . isAny ( ) ) )
175
+ . returns ( ( ) => ( ( { uri : { fsPath : workspacePath } } as unknown ) as WorkspaceFolder ) ) ;
176
+
164
177
setInterpreterCommand = new SetInterpreterCommand (
165
178
appShell . object ,
166
179
new PathUtils ( false ) ,
@@ -233,6 +246,108 @@ suite('Set Interpreter Command', () => {
233
246
assert . deepStrictEqual ( actualParameters , expectedParameters , 'Params not equal' ) ;
234
247
} ) ;
235
248
249
+ test ( 'Items displayed should be grouped if no refresh is going on' , async ( ) => {
250
+ const state : InterpreterStateArgs = { path : 'some path' , workspace : undefined } ;
251
+ const multiStepInput = TypeMoq . Mock . ofType < IMultiStepInput < InterpreterStateArgs > > ( ) ;
252
+ const interpreterItems : IInterpreterQuickPickItem [ ] = [
253
+ {
254
+ description : `${ workspacePath } /interpreterPath1` ,
255
+ detail : '' ,
256
+ label : 'This is the selected Python path' ,
257
+ path : `${ workspacePath } /interpreterPath1` ,
258
+ interpreter : {
259
+ path : `${ workspacePath } /interpreterPath1` ,
260
+ envType : EnvironmentType . Venv ,
261
+ } as PythonEnvironment ,
262
+ } ,
263
+ {
264
+ description : 'interpreterPath2' ,
265
+ detail : '' ,
266
+ label : 'This is the selected Python path' ,
267
+ path : 'interpreterPath2' ,
268
+ interpreter : {
269
+ path : 'interpreterPath2' ,
270
+ envType : EnvironmentType . VirtualEnvWrapper ,
271
+ } as PythonEnvironment ,
272
+ } ,
273
+ {
274
+ description : 'interpreterPath3' ,
275
+ detail : '' ,
276
+ label : 'This is the selected Python path' ,
277
+ path : 'interpreterPath3' ,
278
+ interpreter : {
279
+ path : 'interpreterPath3' ,
280
+ envType : EnvironmentType . VirtualEnvWrapper ,
281
+ } as PythonEnvironment ,
282
+ } ,
283
+ {
284
+ description : 'interpreterPath4' ,
285
+ detail : '' ,
286
+ label : 'This is the selected Python path' ,
287
+ path : 'interpreterPath4' ,
288
+ interpreter : { path : 'interpreterPath4' , envType : EnvironmentType . Conda } as PythonEnvironment ,
289
+ } ,
290
+ item ,
291
+ {
292
+ description : 'interpreterPath5' ,
293
+ detail : '' ,
294
+ label : 'This is the selected Python path' ,
295
+ path : 'interpreterPath5' ,
296
+ interpreter : { path : 'interpreterPath5' , envType : EnvironmentType . Global } as PythonEnvironment ,
297
+ } ,
298
+ ] ;
299
+ interpreterSelector . reset ( ) ;
300
+ interpreterSelector
301
+ . setup ( ( i ) => i . getSuggestions ( TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) ) )
302
+ . returns ( ( ) => interpreterItems ) ;
303
+ interpreterSelector
304
+ . setup ( ( i ) => i . getRecommendedSuggestion ( TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) ) )
305
+ . returns ( ( ) => item ) ;
306
+ const recommended = cloneDeep ( item ) ;
307
+ recommended . label = `${ Octicons . Star } ${ item . label } ` ;
308
+ recommended . description = `${ interpreterPath } - ${ Common . recommended ( ) } ` ;
309
+ const suggestions = [
310
+ expectedEnterInterpreterPathSuggestion ,
311
+ defaultInterpreterPathSuggestion ,
312
+ { label : EnvGroups . Workspace , kind : QuickPickItemKind . Separator } ,
313
+ interpreterItems [ 0 ] ,
314
+ { label : EnvGroups . VirtualEnvWrapper , kind : QuickPickItemKind . Separator } ,
315
+ interpreterItems [ 1 ] ,
316
+ interpreterItems [ 2 ] ,
317
+ { label : EnvGroups . Conda , kind : QuickPickItemKind . Separator } ,
318
+ interpreterItems [ 3 ] ,
319
+ recommended ,
320
+ { label : EnvGroups . Global , kind : QuickPickItemKind . Separator } ,
321
+ interpreterItems [ 5 ] ,
322
+ ] ;
323
+ const expectedParameters : IQuickPickParameters < QuickPickItem > = {
324
+ placeholder : InterpreterQuickPickList . quickPickListPlaceholder ( ) . format ( currentPythonPath ) ,
325
+ items : suggestions ,
326
+ activeItem : recommended ,
327
+ matchOnDetail : true ,
328
+ matchOnDescription : true ,
329
+ title : InterpreterQuickPickList . browsePath . openButtonLabel ( ) ,
330
+ sortByLabel : true ,
331
+ keepScrollPosition : true ,
332
+ } ;
333
+ let actualParameters : IQuickPickParameters < QuickPickItem > | undefined ;
334
+ multiStepInput
335
+ . setup ( ( i ) => i . showQuickPick ( TypeMoq . It . isAny ( ) ) )
336
+ . callback ( ( options ) => {
337
+ actualParameters = options ;
338
+ } )
339
+ . returns ( ( ) => Promise . resolve ( ( undefined as unknown ) as QuickPickItem ) ) ;
340
+
341
+ await setInterpreterCommand . _pickInterpreter ( multiStepInput . object , state ) ;
342
+
343
+ expect ( actualParameters ) . to . not . equal ( undefined , 'Parameters not set' ) ;
344
+ const refreshButtonCallback = actualParameters ! . customButtonSetup ?. callback ;
345
+ expect ( refreshButtonCallback ) . to . not . equal ( undefined , 'Callback not set' ) ;
346
+ delete actualParameters ! . customButtonSetup ;
347
+ delete actualParameters ! . onChangeItem ;
348
+ assert . deepStrictEqual ( actualParameters ?. items , expectedParameters . items , 'Params not equal' ) ;
349
+ } ) ;
350
+
236
351
test ( 'If system variables are used in the default interpreter path, make sure they are resolved when the path is displayed' , async ( ) => {
237
352
// Create a SetInterpreterCommand instance from scratch, and use a different defaultInterpreterPath from the rest of the tests.
238
353
const workspaceDefaultInterpreterPath = '${workspaceFolder}/defaultInterpreterPath' ;
0 commit comments