|
2 | 2 | // Licensed under the MIT License. |
3 | 3 |
|
4 | 4 | import assert from 'node:assert'; |
| 5 | +import * as path from 'path'; |
| 6 | +import * as sinon from 'sinon'; |
5 | 7 | import { Uri } from 'vscode'; |
6 | 8 | import { PythonEnvironment } from '../../api'; |
| 9 | +import { Interpreter } from '../../common/localize'; |
| 10 | +import { pickEnvironment } from '../../common/pickers/environments'; |
| 11 | +import * as managerPicker from '../../common/pickers/managers'; |
| 12 | +import * as windowApis from '../../common/window.apis'; |
| 13 | +import * as workspaceApis from '../../common/workspace.apis'; |
| 14 | +import { createMockPythonEnvironment } from '../mocks/pythonEnvironment'; |
| 15 | + |
| 16 | +suite('Environment Picker Creation Availability', () => { |
| 17 | + const folder = { uri: Uri.file(process.cwd()), name: 'workspace', index: 0 }; |
| 18 | + |
| 19 | + teardown(() => { |
| 20 | + sinon.restore(); |
| 21 | + }); |
| 22 | + |
| 23 | + for (const { name, folders, canCreate } of [ |
| 24 | + { name: 'no workspace', folders: undefined, canCreate: false }, |
| 25 | + { name: 'an empty workspace', folders: [], canCreate: false }, |
| 26 | + { name: 'an open folder without detected projects', folders: [folder], canCreate: true }, |
| 27 | + { |
| 28 | + name: 'a multi-root workspace', |
| 29 | + folders: [folder, { uri: Uri.file(path.join(process.cwd(), 'second')), name: 'second', index: 1 }], |
| 30 | + canCreate: true, |
| 31 | + }, |
| 32 | + ]) { |
| 33 | + test(`only offers creation with an open folder: ${name}`, async () => { |
| 34 | + sinon.stub(workspaceApis, 'getWorkspaceFolders').returns(folders); |
| 35 | + const pickManager = sinon.stub(managerPicker, 'pickEnvironmentManager'); |
| 36 | + const picker = sinon.stub(windowApis, 'showQuickPickWithButtons').callsFake(async (items) => { |
| 37 | + assert.strictEqual( |
| 38 | + items.some((item) => item.label === Interpreter.createVirtualEnvironment), |
| 39 | + canCreate, |
| 40 | + ); |
| 41 | + assert.ok(items.some((item) => item.label === Interpreter.browsePath)); |
| 42 | + return undefined; |
| 43 | + }); |
| 44 | + |
| 45 | + assert.strictEqual(await pickEnvironment([], [], { projects: [] }), undefined); |
| 46 | + sinon.assert.calledOnce(picker); |
| 47 | + sinon.assert.notCalled(pickManager); |
| 48 | + }); |
| 49 | + } |
| 50 | + |
| 51 | + test('still selects an existing environment without an open folder', async () => { |
| 52 | + const environment = createMockPythonEnvironment({ envPath: path.join(process.cwd(), 'python') }); |
| 53 | + sinon.stub(workspaceApis, 'getWorkspaceFolders').returns(undefined); |
| 54 | + sinon |
| 55 | + .stub(windowApis, 'showQuickPickWithButtons') |
| 56 | + .callsFake(async (items) => items.find((item) => item.label === environment.displayName)); |
| 57 | + |
| 58 | + const selected = await pickEnvironment([], [], { projects: [], recommended: environment }); |
| 59 | + |
| 60 | + assert.strictEqual(selected, environment); |
| 61 | + }); |
| 62 | + |
| 63 | + test('still allows browsing for an interpreter without an open folder', async () => { |
| 64 | + sinon.stub(workspaceApis, 'getWorkspaceFolders').returns(undefined); |
| 65 | + sinon |
| 66 | + .stub(windowApis, 'showQuickPickWithButtons') |
| 67 | + .callsFake(async (items) => items.find((item) => item.label === Interpreter.browsePath)); |
| 68 | + const browse = sinon.stub(windowApis, 'showOpenDialog').resolves(undefined); |
| 69 | + |
| 70 | + assert.strictEqual(await pickEnvironment([], [], { projects: [] }), undefined); |
| 71 | + sinon.assert.calledOnce(browse); |
| 72 | + }); |
| 73 | +}); |
7 | 74 |
|
8 | 75 | /** |
9 | 76 | * Test the logic used in environment pickers to include interpreter paths in descriptions |
|
0 commit comments