Skip to content

Commit be5c096

Browse files
Copiloteleanorjboyd
andcommitted
Add tests for progress merge functionality
- Created unit tests to verify suppressProgress option works correctly - Tests confirm progress.report is called to update message - Tests verify suppressProgress:true is passed to managePackages - All 197 tests passing Co-authored-by: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com>
1 parent e201ef0 commit be5c096

1 file changed

Lines changed: 158 additions & 0 deletions

File tree

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import assert from 'assert';
2+
import * as sinon from 'sinon';
3+
import { CancellationToken, LogOutputChannel, Progress, Uri } from 'vscode';
4+
import { EnvironmentManager, PythonEnvironment } from '../../../api';
5+
import * as winapi from '../../../common/window.apis';
6+
import { createWithProgress } from '../../../managers/builtin/venvUtils';
7+
8+
suite('Venv Progress Merge Tests', () => {
9+
let mockWithProgress: sinon.SinonStub;
10+
let mockManagePackages: sinon.SinonStub;
11+
let mockNativeFinder: any;
12+
let mockApi: any;
13+
let mockLog: any;
14+
let mockManager: any;
15+
let mockBasePython: PythonEnvironment;
16+
let progressReportStub: sinon.SinonStub;
17+
18+
setup(() => {
19+
// Stub withProgress to capture the progress callback
20+
progressReportStub = sinon.stub();
21+
mockWithProgress = sinon.stub(winapi, 'withProgress');
22+
mockWithProgress.callsFake(async (_options: any, callback: Function) => {
23+
const mockProgress: Progress<{ message?: string; increment?: number }> = {
24+
report: progressReportStub,
25+
};
26+
const mockToken: CancellationToken = {
27+
isCancellationRequested: false,
28+
onCancellationRequested: sinon.stub(),
29+
};
30+
return await callback(mockProgress, mockToken);
31+
});
32+
33+
// Create minimal mocks
34+
mockNativeFinder = {
35+
resolve: sinon.stub().resolves({
36+
executable: '/test/venv/bin/python',
37+
version: '3.11.0',
38+
prefix: '/test/venv',
39+
kind: 'venv',
40+
}),
41+
};
42+
mockApi = {
43+
createPythonEnvironmentItem: sinon.stub().returns({
44+
envId: { id: 'new-env', managerId: 'test-manager' },
45+
name: 'New Venv',
46+
version: '3.11.0',
47+
environmentPath: Uri.file('/test/venv'),
48+
}),
49+
managePackages: sinon.stub().resolves(),
50+
};
51+
mockLog = {} as LogOutputChannel;
52+
mockManager = { log: mockLog } as EnvironmentManager;
53+
54+
// Mock base Python environment
55+
mockBasePython = {
56+
envId: { id: 'test-env', managerId: 'test-manager' },
57+
name: 'Test Python',
58+
version: '3.11.0',
59+
environmentPath: Uri.file('/test/python'),
60+
execInfo: {
61+
run: { executable: '/test/python/bin/python' },
62+
},
63+
} as PythonEnvironment;
64+
65+
// Mock managePackages - this is the key method we're testing
66+
mockManagePackages = mockApi.managePackages;
67+
});
68+
69+
teardown(() => {
70+
sinon.restore();
71+
});
72+
73+
test('should update progress message when installing packages', async () => {
74+
// Mock file system check
75+
const fsapi = require('fs-extra');
76+
sinon.stub(fsapi, 'pathExists').resolves(true);
77+
78+
// Mock the Python run function
79+
const helpers = require('../../../managers/builtin/helpers');
80+
sinon.stub(helpers, 'isUvInstalled').resolves(false);
81+
sinon.stub(helpers, 'runPython').resolves();
82+
83+
await createWithProgress(
84+
mockNativeFinder as any,
85+
mockApi as any,
86+
mockLog as any,
87+
mockManager as any,
88+
mockBasePython,
89+
Uri.file('/test'),
90+
'/test/venv',
91+
{ install: ['numpy', 'pandas'], uninstall: [] },
92+
);
93+
94+
// Verify the progress.report was called with the installing packages message
95+
assert(progressReportStub.called, 'progress.report should have been called');
96+
const reportCalls = progressReportStub.getCalls();
97+
const installingPackagesCall = reportCalls.find((call) =>
98+
call.args[0]?.message?.includes('Installing packages'),
99+
);
100+
assert(installingPackagesCall, 'progress.report should have been called with "Installing packages" message');
101+
});
102+
103+
test('should pass suppressProgress:true when calling managePackages', async () => {
104+
// Mock file system check
105+
const fsapi = require('fs-extra');
106+
sinon.stub(fsapi, 'pathExists').resolves(true);
107+
108+
// Mock the Python run function
109+
const helpers = require('../../../managers/builtin/helpers');
110+
sinon.stub(helpers, 'isUvInstalled').resolves(false);
111+
sinon.stub(helpers, 'runPython').resolves();
112+
113+
await createWithProgress(
114+
mockNativeFinder as any,
115+
mockApi as any,
116+
mockLog as any,
117+
mockManager as any,
118+
mockBasePython,
119+
Uri.file('/test'),
120+
'/test/venv',
121+
{ install: ['numpy'], uninstall: [] },
122+
);
123+
124+
// Verify managePackages was called with suppressProgress:true
125+
assert(mockManagePackages.called, 'managePackages should have been called');
126+
const managePackagesCall = mockManagePackages.getCall(0);
127+
assert.strictEqual(
128+
managePackagesCall.args[1].suppressProgress,
129+
true,
130+
'managePackages should be called with suppressProgress:true',
131+
);
132+
});
133+
134+
test('should not call managePackages when no packages to install', async () => {
135+
// Mock file system check
136+
const fsapi = require('fs-extra');
137+
sinon.stub(fsapi, 'pathExists').resolves(true);
138+
139+
// Mock the Python run function
140+
const helpers = require('../../../managers/builtin/helpers');
141+
sinon.stub(helpers, 'isUvInstalled').resolves(false);
142+
sinon.stub(helpers, 'runPython').resolves();
143+
144+
await createWithProgress(
145+
mockNativeFinder as any,
146+
mockApi as any,
147+
mockLog as any,
148+
mockManager as any,
149+
mockBasePython,
150+
Uri.file('/test'),
151+
'/test/venv',
152+
{ install: [], uninstall: [] },
153+
);
154+
155+
// Verify managePackages was NOT called when there are no packages
156+
assert(!mockManagePackages.called, 'managePackages should not be called when no packages to install');
157+
});
158+
});

0 commit comments

Comments
 (0)