forked from microsoft/vscode-python-environments
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunctional.smoke.test.ts
More file actions
293 lines (233 loc) · 11.6 KB
/
Copy pathfunctional.smoke.test.ts
File metadata and controls
293 lines (233 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
/**
* Smoke Test: Functional Checks
*
* PURPOSE:
* Verify that core extension features actually work, not just that they're registered.
* These tests require Python to be installed and may have side effects.
*
* WHAT THIS TESTS:
* 1. Environment discovery returns results
* 2. Projects API works correctly
* 3. Environment variables API works
* 4. Settings are not polluted on activation
*/
import * as assert from 'assert';
import * as vscode from 'vscode';
import { PythonEnvironmentApi } from '../../api';
import { ENVS_EXTENSION_ID, MAX_EXTENSION_ACTIVATION_TIME } from '../constants';
import { waitForApiReady, waitForCondition } from '../testUtils';
suite('Smoke: Functional Checks', function () {
this.timeout(MAX_EXTENSION_ACTIVATION_TIME);
let api: PythonEnvironmentApi;
let managersReady = false;
suiteSetup(async function () {
const extension = vscode.extensions.getExtension<PythonEnvironmentApi>(ENVS_EXTENSION_ID);
assert.ok(extension, `Extension ${ENVS_EXTENSION_ID} not found`);
if (!extension.isActive) {
await extension.activate();
await waitForCondition(() => extension.isActive, 30_000, 'Extension did not activate');
}
api = extension.exports;
assert.ok(api, 'API not exported');
// Wait for environment managers to register (happens async in setImmediate)
// This may fail in CI if the pet binary is not available
const result = await waitForApiReady(api, 45_000);
managersReady = result.ready;
if (!result.ready) {
console.log(`[WARN] Managers not ready: ${result.error}`);
console.log('[WARN] Tests requiring managers will be skipped');
}
});
// =========================================================================
// ENVIRONMENT DISCOVERY - Core feature must work
// =========================================================================
test('getEnvironments returns an array', async function () {
// Skip if managers aren't ready (e.g., pet binary not available in CI)
if (!managersReady) {
this.skip();
return;
}
// This test verifies discovery machinery works
// Even if no Python is installed, it should return an empty array, not throw
const environments = await api.getEnvironments('all');
assert.ok(Array.isArray(environments), 'getEnvironments("all") should return an array');
});
test('getEnvironments finds Python installations when available', async function () {
// Skip if managers aren't ready (e.g., pet binary not available in CI)
if (!managersReady) {
this.skip();
return;
}
// Skip this test if no Python is expected (CI without Python)
if (process.env.SKIP_PYTHON_TESTS) {
this.skip();
return;
}
const environments = await api.getEnvironments('all');
// On a typical dev machine, we expect at least one Python
// This test may need to be conditional based on CI environment
if (environments.length === 0) {
console.log('[WARN] No Python environments found - is Python installed?');
// Don't fail - just warn. CI may not have Python.
return;
}
// Verify environment structure
const env = environments[0];
assert.ok(env.envId, 'Environment should have envId');
assert.ok(env.envId.id, 'envId.id should be defined');
assert.ok(env.envId.managerId, 'envId.managerId should be defined');
assert.ok(env.name, 'Environment should have a name');
assert.ok(env.version, 'Environment should have a version');
assert.ok(env.environmentPath, 'Environment should have environmentPath');
});
test('getEnvironments with scope "global" returns global interpreters', async function () {
// Skip if managers aren't ready (e.g., pet binary not available in CI)
if (!managersReady) {
this.skip();
return;
}
const globalEnvs = await api.getEnvironments('global');
assert.ok(Array.isArray(globalEnvs), 'getEnvironments("global") should return an array');
// Global environments are system Python installations
// They should be a subset of 'all' environments
const allEnvs = await api.getEnvironments('all');
assert.ok(globalEnvs.length <= allEnvs.length, 'Global environments should be a subset of all environments');
});
test('refreshEnvironments completes without error', async function () {
// Skip if managers aren't ready (e.g., pet binary not available in CI)
if (!managersReady) {
this.skip();
return;
}
// This should not throw
await api.refreshEnvironments(undefined);
// Verify we can still get environments after refresh
const environments = await api.getEnvironments('all');
assert.ok(Array.isArray(environments), 'Should be able to get environments after refresh');
});
// =========================================================================
// PROJECTS - Core project management features
// =========================================================================
test('getPythonProjects returns workspace folders by default', function () {
const projects = api.getPythonProjects();
assert.ok(Array.isArray(projects), 'getPythonProjects should return an array');
// By default, workspace folders are treated as projects
const workspaceFolders = vscode.workspace.workspaceFolders;
if (workspaceFolders && workspaceFolders.length > 0) {
assert.ok(projects.length > 0, 'With workspace folders open, there should be at least one project');
// Verify project structure
const project = projects[0];
assert.ok(project.name, 'Project should have a name');
assert.ok(project.uri, 'Project should have a uri');
}
});
test('getPythonProject returns undefined for non-existent path', function () {
const fakeUri = vscode.Uri.file('/this/path/does/not/exist/anywhere');
const project = api.getPythonProject(fakeUri);
// Should return undefined, not throw
assert.strictEqual(project, undefined, 'getPythonProject should return undefined for non-existent path');
});
// =========================================================================
// ENVIRONMENT SELECTION - Get/Set environment
// =========================================================================
test('getEnvironment returns undefined or a valid environment', async function () {
// Skip if managers aren't ready (e.g., pet binary not available in CI)
if (!managersReady) {
this.skip();
return;
}
// With no explicit selection, may return undefined or auto-selected env
const env = await api.getEnvironment(undefined);
if (env !== undefined) {
// If an environment is returned, verify its structure
assert.ok(env.envId, 'Returned environment should have envId');
assert.ok(env.name, 'Returned environment should have name');
}
// undefined is also valid - no environment selected
});
// =========================================================================
// ENVIRONMENT VARIABLES - .env file support
// =========================================================================
test('getEnvironmentVariables returns an object', async function () {
const envVars = await api.getEnvironmentVariables(undefined);
assert.ok(envVars !== null, 'getEnvironmentVariables should not return null');
assert.ok(typeof envVars === 'object', 'getEnvironmentVariables should return an object');
// Should at least contain PATH or similar system variables
// (merged from process.env by default)
const hasKeys = Object.keys(envVars).length > 0;
assert.ok(hasKeys, 'Environment variables object should have some entries');
});
test('getEnvironmentVariables with workspace uri works', async function () {
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders || workspaceFolders.length === 0) {
this.skip();
return;
}
const workspaceUri = workspaceFolders[0].uri;
const envVars = await api.getEnvironmentVariables(workspaceUri);
assert.ok(envVars !== null, 'getEnvironmentVariables with workspace uri should not return null');
assert.ok(typeof envVars === 'object', 'Should return an object');
});
// =========================================================================
// RESOLVE ENVIRONMENT - Detailed environment info
// =========================================================================
test('resolveEnvironment handles invalid path gracefully', async function () {
// Skip if managers aren't ready (e.g., pet binary not available in CI)
if (!managersReady) {
this.skip();
return;
}
const fakeUri = vscode.Uri.file('/this/is/not/a/python/installation');
// Should return undefined, not throw
const resolved = await api.resolveEnvironment(fakeUri);
assert.strictEqual(resolved, undefined, 'resolveEnvironment should return undefined for invalid path');
});
test('resolveEnvironment returns full details for valid environment', async function () {
// Skip if managers aren't ready (e.g., pet binary not available in CI)
if (!managersReady) {
this.skip();
return;
}
const environments = await api.getEnvironments('all');
if (environments.length === 0) {
this.skip();
return;
}
// Try to resolve the first environment's path
const env = environments[0];
const resolved = await api.resolveEnvironment(env.environmentPath);
if (resolved) {
// Verify resolved environment has execution info
assert.ok(resolved.execInfo, 'Resolved environment should have execInfo');
assert.ok(resolved.execInfo.run, 'execInfo should have run configuration');
assert.ok(resolved.execInfo.run.executable, 'run should have executable path');
}
});
// =========================================================================
// PACKAGES - Package listing (read-only)
// =========================================================================
test('getPackages returns array or undefined for valid environment', async function () {
// Skip if managers aren't ready (e.g., pet binary not available in CI)
if (!managersReady) {
this.skip();
return;
}
const environments = await api.getEnvironments('all');
if (environments.length === 0) {
this.skip();
return;
}
const env = environments[0];
const packages = await api.getPackages(env);
// Should return array or undefined, not throw
assert.ok(packages === undefined || Array.isArray(packages), 'getPackages should return undefined or an array');
// If packages exist, verify structure
if (packages && packages.length > 0) {
const pkg = packages[0];
assert.ok(pkg.pkgId, 'Package should have pkgId');
assert.ok(pkg.name, 'Package should have name');
}
});
});