Skip to content

Commit 5deb4b8

Browse files
committed
Add smoke tests for functional checks and registration verification
1 parent dab7bc9 commit 5deb4b8

File tree

2 files changed

+518
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)