Skip to content

Commit 59d72f7

Browse files
author
Kartik Raj
committed
Add tests for the new API method
1 parent 25f6567 commit 59d72f7

File tree

2 files changed

+153
-35
lines changed

2 files changed

+153
-35
lines changed

src/client/common/interpreterPathService.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,15 @@ export class InterpreterPathService implements IInterpreterPathService {
139139

140140
public async copyOldInterpreterStorageValuesToNew(resource: Resource): Promise<void> {
141141
resource = PythonSettings.getSettingsUriAndTarget(resource, this.workspaceService).uri;
142-
const workspaceConfig = this.workspaceService.getConfiguration('python', resource);
143-
const oldSettings = workspaceConfig.inspect<string>('pythonPath')!;
142+
const oldSettings = this.workspaceService.getConfiguration('python', resource).inspect<string>('pythonPath')!;
143+
await Promise.all([
144+
this._copyWorkspaceFolderValueToNewStorage(resource, oldSettings.workspaceFolderValue),
145+
this._copyWorkspaceValueToNewStorage(resource, oldSettings.workspaceValue),
146+
this._moveGlobalSettingValueToNewStorage(oldSettings.globalValue)
147+
]);
148+
}
144149

150+
public async _copyWorkspaceFolderValueToNewStorage(resource: Resource, value: string | undefined): Promise<void> {
145151
// Copy workspace folder setting into the new storage if it hasn't been copied already
146152
const workspaceFolderKey = this.workspaceService.getWorkspaceFolderIdentifier(resource);
147153
const flaggedWorkspaceFolderKeysStorage = this.persistentStateFactory.createGlobalPersistentState<string[]>(
@@ -151,35 +157,44 @@ export class InterpreterPathService implements IInterpreterPathService {
151157
const flaggedWorkspaceFolderKeys = flaggedWorkspaceFolderKeysStorage.value;
152158
const shouldUpdateWorkspaceFolderSetting = !flaggedWorkspaceFolderKeys.includes(workspaceFolderKey);
153159
if (shouldUpdateWorkspaceFolderSetting) {
154-
await this.update(resource, ConfigurationTarget.WorkspaceFolder, oldSettings.workspaceFolderValue);
160+
await this.update(resource, ConfigurationTarget.WorkspaceFolder, value);
155161
await flaggedWorkspaceFolderKeysStorage.updateValue([workspaceFolderKey, ...flaggedWorkspaceFolderKeys]);
156162
}
163+
}
157164

165+
public async _copyWorkspaceValueToNewStorage(resource: Resource, value: string | undefined): Promise<void> {
158166
// Copy workspace setting into the new storage if it hasn't been copied already
159167
const workspaceKey = this.workspaceService.workspaceFile
160168
? this.fileSystemPaths.normCase(this.workspaceService.workspaceFile.fsPath)
161169
: undefined;
170+
if (!workspaceKey) {
171+
return;
172+
}
162173
const flaggedWorkspaceKeysStorage = this.persistentStateFactory.createGlobalPersistentState<string[]>(
163174
workspaceKeysForWhichTheCopyIsDone_Key,
164175
[]
165176
);
166177
const flaggedWorkspaceKeys = flaggedWorkspaceKeysStorage.value;
167-
const shouldUpdateWorkspaceSetting = workspaceKey && !flaggedWorkspaceKeys.includes(workspaceKey);
168-
if (workspaceKey && shouldUpdateWorkspaceSetting) {
169-
await this.update(resource, ConfigurationTarget.Workspace, oldSettings.workspaceValue);
178+
const shouldUpdateWorkspaceSetting = !flaggedWorkspaceKeys.includes(workspaceKey);
179+
if (shouldUpdateWorkspaceSetting) {
180+
await this.update(resource, ConfigurationTarget.Workspace, value);
170181
await flaggedWorkspaceKeysStorage.updateValue([workspaceKey, ...flaggedWorkspaceKeys]);
171182
}
183+
}
172184

185+
public async _moveGlobalSettingValueToNewStorage(value: string | undefined) {
173186
// Move global setting into the new storage if it hasn't been moved already
174187
const isGlobalSettingCopiedStorage = this.persistentStateFactory.createGlobalPersistentState<boolean>(
175188
isGlobalSettingCopiedKey,
176189
false
177190
);
178191
const shouldUpdateGlobalSetting = !isGlobalSettingCopiedStorage.value;
179192
if (shouldUpdateGlobalSetting) {
180-
await this.update(undefined, ConfigurationTarget.Global, oldSettings.globalValue);
193+
await this.update(undefined, ConfigurationTarget.Global, value);
181194
// Make sure to delete the original setting after copying it
182-
await workspaceConfig.update('pythonPath', undefined, ConfigurationTarget.Global);
195+
await this.workspaceService
196+
.getConfiguration('python')
197+
.update('pythonPath', undefined, ConfigurationTarget.Global);
183198
await isGlobalSettingCopiedStorage.updateValue(true);
184199
}
185200
}

src/test/common/interpreterPathService.unit.test.ts

Lines changed: 130 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ import { IWorkspaceService } from '../../client/common/application/types';
1818
import {
1919
defaultInterpreterPathSetting,
2020
InterpreterPathService,
21+
isGlobalSettingCopiedKey,
22+
workspaceFolderKeysForWhichTheCopyIsDone_Key,
2123
workspaceKeysForWhichTheCopyIsDone_Key
2224
} from '../../client/common/interpreterPathService';
2325
import { InterpreterConfigurationScope, IPersistentState, IPersistentStateFactory } from '../../client/common/types';
2426
import { createDeferred, sleep } from '../../client/common/utils/async';
2527

26-
suite('xInterpreter Path Service', async () => {
28+
suite('Interpreter Path Service', async () => {
2729
let interpreterPathService: InterpreterPathService;
2830
let persistentStateFactory: TypeMoq.IMock<IPersistentStateFactory>;
2931
let workspaceService: TypeMoq.IMock<IWorkspaceService>;
@@ -50,8 +52,19 @@ suite('xInterpreter Path Service', async () => {
5052
sinon.restore();
5153
});
5254

53-
test('If the one-off transfer to new storage has not happened yet for the workspace, do it and record the transfer', async () => {
54-
const update = sinon.stub(InterpreterPathService.prototype, 'update');
55+
test('Ensure execution of method copyOldInterpreterStorageValuesToNew() goes as expected', async () => {
56+
const _copyWorkspaceFolderValueToNewStorage = sinon.stub(
57+
InterpreterPathService.prototype,
58+
'_copyWorkspaceFolderValueToNewStorage'
59+
);
60+
const _copyWorkspaceValueToNewStorage = sinon.stub(
61+
InterpreterPathService.prototype,
62+
'_copyWorkspaceValueToNewStorage'
63+
);
64+
const _moveGlobalSettingValueToNewStorage = sinon.stub(
65+
InterpreterPathService.prototype,
66+
'_moveGlobalSettingValueToNewStorage'
67+
);
5568
const workspaceConfig = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
5669
workspaceService.setup((w) => w.getConfiguration('python', resource)).returns(() => workspaceConfig.object);
5770
workspaceConfig
@@ -65,54 +78,144 @@ suite('xInterpreter Path Service', async () => {
6578
// tslint:disable-next-line: no-any
6679
} as any)
6780
);
81+
82+
interpreterPathService = new InterpreterPathService(persistentStateFactory.object, workspaceService.object, []);
83+
await interpreterPathService.copyOldInterpreterStorageValuesToNew(resource);
84+
85+
assert(_copyWorkspaceFolderValueToNewStorage.calledWith(resource, 'workspaceFolderPythonPath'));
86+
assert(_copyWorkspaceValueToNewStorage.calledWith(resource, 'workspacePythonPath'));
87+
assert(_moveGlobalSettingValueToNewStorage.calledWith('globalPythonPath'));
88+
});
89+
90+
test('If the one-off transfer to new storage has not happened yet for the workspace folder, do it and record the transfer', async () => {
91+
const update = sinon.stub(InterpreterPathService.prototype, 'update');
92+
const persistentState = TypeMoq.Mock.ofType<IPersistentState<string[]>>();
93+
workspaceService.setup((w) => w.getWorkspaceFolderIdentifier(resource)).returns(() => resource.fsPath);
94+
persistentStateFactory
95+
.setup((p) => p.createGlobalPersistentState<string[]>(workspaceFolderKeysForWhichTheCopyIsDone_Key, []))
96+
.returns(() => persistentState.object);
97+
persistentState.setup((p) => p.value).returns(() => ['...storedWorkspaceFolderKeys']);
98+
persistentState
99+
.setup((p) => p.updateValue([resource.fsPath, '...storedWorkspaceFolderKeys']))
100+
.returns(() => Promise.resolve())
101+
.verifiable(TypeMoq.Times.once());
102+
103+
interpreterPathService = new InterpreterPathService(persistentStateFactory.object, workspaceService.object, []);
104+
await interpreterPathService._copyWorkspaceFolderValueToNewStorage(resource, 'workspaceFolderPythonPath');
105+
106+
assert(update.calledWith(resource, ConfigurationTarget.WorkspaceFolder, 'workspaceFolderPythonPath'));
107+
persistentState.verifyAll();
108+
});
109+
110+
test('If the one-off transfer to new storage has already happened for the workspace folder, do not update and simply return', async () => {
111+
const update = sinon.stub(InterpreterPathService.prototype, 'update');
68112
const persistentState = TypeMoq.Mock.ofType<IPersistentState<string[]>>();
69113
workspaceService.setup((w) => w.getWorkspaceFolderIdentifier(resource)).returns(() => resource.fsPath);
114+
persistentStateFactory
115+
.setup((p) => p.createGlobalPersistentState<string[]>(workspaceFolderKeysForWhichTheCopyIsDone_Key, []))
116+
.returns(() => persistentState.object);
117+
persistentState.setup((p) => p.value).returns(() => [resource.fsPath, '...storedWorkspaceKeys']);
118+
persistentState.setup((p) => p.updateValue(TypeMoq.It.isAny())).verifiable(TypeMoq.Times.never());
119+
120+
interpreterPathService = new InterpreterPathService(persistentStateFactory.object, workspaceService.object, []);
121+
await interpreterPathService._copyWorkspaceFolderValueToNewStorage(resource, 'workspaceFolderPythonPath');
122+
123+
assert(update.notCalled);
124+
persistentState.verifyAll();
125+
});
126+
127+
test('If the one-off transfer to new storage has not happened yet for the workspace, do it and record the transfer', async () => {
128+
const workspaceFileUri = Uri.parse('path/to/workspaceFile');
129+
const expectedWorkspaceKey = 'PATH\\TO\\WORKSPACEFILE';
130+
const update = sinon.stub(InterpreterPathService.prototype, 'update');
131+
const persistentState = TypeMoq.Mock.ofType<IPersistentState<string[]>>();
132+
workspaceService.setup((w) => w.workspaceFile).returns(() => workspaceFileUri);
70133
persistentStateFactory
71134
.setup((p) => p.createGlobalPersistentState<string[]>(workspaceKeysForWhichTheCopyIsDone_Key, []))
72135
.returns(() => persistentState.object);
73136
persistentState.setup((p) => p.value).returns(() => ['...storedWorkspaceKeys']);
74137
persistentState
75-
.setup((p) => p.updateValue([resource.fsPath, '...storedWorkspaceKeys']))
138+
.setup((p) => p.updateValue([expectedWorkspaceKey, '...storedWorkspaceKeys']))
76139
.returns(() => Promise.resolve())
77140
.verifiable(TypeMoq.Times.once());
78141

79142
interpreterPathService = new InterpreterPathService(persistentStateFactory.object, workspaceService.object, []);
80-
await interpreterPathService.copyOldInterpreterStorageValuesToNew(resource);
143+
await interpreterPathService._copyWorkspaceValueToNewStorage(resource, 'workspacePythonPath');
81144

82-
update.calledWith(resource, ConfigurationTarget.WorkspaceFolder, 'workspaceFolderPythonPath');
83-
update.calledWith(resource, ConfigurationTarget.Workspace, 'workspacePythonPath');
84-
update.calledWith(undefined, ConfigurationTarget.Global, 'globalPythonPath');
145+
assert(update.calledWith(resource, ConfigurationTarget.Workspace, 'workspacePythonPath'));
85146
persistentState.verifyAll();
86147
});
87148

88149
test('If the one-off transfer to new storage has already happened for the workspace, do not update and simply return', async () => {
150+
const workspaceFileUri = Uri.parse('path/to/workspaceFile');
151+
const expectedWorkspaceKey = 'PATH\\TO\\WORKSPACEFILE';
89152
const update = sinon.stub(InterpreterPathService.prototype, 'update');
90-
const workspaceConfig = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
91-
workspaceService.setup((w) => w.getConfiguration('python', resource)).returns(() => workspaceConfig.object);
92-
workspaceConfig
93-
.setup((w) => w.inspect<string>('pythonPath'))
94-
.returns(
95-
() =>
96-
({
97-
globalValue: 'globalPythonPath',
98-
workspaceFolderValue: 'workspaceFolderPythonPath',
99-
workspaceValue: 'workspacePythonPath'
100-
// tslint:disable-next-line: no-any
101-
} as any)
102-
);
103153
const persistentState = TypeMoq.Mock.ofType<IPersistentState<string[]>>();
104-
workspaceService.setup((w) => w.getWorkspaceFolderIdentifier(resource)).returns(() => resource.fsPath);
154+
workspaceService.setup((w) => w.workspaceFile).returns(() => workspaceFileUri);
105155
persistentStateFactory
106156
.setup((p) => p.createGlobalPersistentState<string[]>(workspaceKeysForWhichTheCopyIsDone_Key, []))
107157
.returns(() => persistentState.object);
108-
persistentState.setup((p) => p.value).returns(() => [resource.fsPath, '...storedWorkspaceKeys']);
109-
persistentState
110-
.setup((p) => p.updateValue(TypeMoq.It.isAny()))
158+
persistentState.setup((p) => p.value).returns(() => [expectedWorkspaceKey, '...storedWorkspaceKeys']);
159+
persistentState.setup((p) => p.updateValue(TypeMoq.It.isAny())).verifiable(TypeMoq.Times.never());
160+
161+
interpreterPathService = new InterpreterPathService(persistentStateFactory.object, workspaceService.object, []);
162+
await interpreterPathService._copyWorkspaceValueToNewStorage(resource, 'workspacePythonPath');
163+
164+
assert(update.notCalled);
165+
persistentState.verifyAll();
166+
});
167+
168+
test('Do not update workspace settings and if a folder is directly opened', async () => {
169+
const update = sinon.stub(InterpreterPathService.prototype, 'update');
170+
const persistentState = TypeMoq.Mock.ofType<IPersistentState<string[]>>();
171+
workspaceService.setup((w) => w.workspaceFile).returns(() => undefined);
172+
persistentStateFactory
173+
.setup((p) => p.createGlobalPersistentState<string[]>(workspaceKeysForWhichTheCopyIsDone_Key, []))
174+
.returns(() => persistentState.object);
175+
persistentState.setup((p) => p.value).verifiable(TypeMoq.Times.never());
176+
persistentState.setup((p) => p.updateValue(TypeMoq.It.isAny())).verifiable(TypeMoq.Times.never());
177+
178+
interpreterPathService = new InterpreterPathService(persistentStateFactory.object, workspaceService.object, []);
179+
await interpreterPathService._copyWorkspaceValueToNewStorage(resource, 'workspacePythonPath');
180+
181+
assert(update.notCalled);
182+
persistentState.verifyAll();
183+
});
184+
185+
test('If the one-off transfer to new storage has not happened yet for the user setting, do it, record the transfer and remove the original user setting', async () => {
186+
const update = sinon.stub(InterpreterPathService.prototype, 'update');
187+
const persistentState = TypeMoq.Mock.ofType<IPersistentState<boolean>>();
188+
persistentStateFactory
189+
.setup((p) => p.createGlobalPersistentState<boolean>(isGlobalSettingCopiedKey, false))
190+
.returns(() => persistentState.object);
191+
persistentState.setup((p) => p.value).returns(() => false);
192+
persistentState.setup((p) => p.updateValue(true)).verifiable(TypeMoq.Times.once());
193+
const workspaceConfig = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
194+
workspaceService.setup((w) => w.getConfiguration('python')).returns(() => workspaceConfig.object);
195+
workspaceConfig
196+
.setup((w) => w.update('pythonPath', undefined, ConfigurationTarget.Global))
111197
.returns(() => Promise.resolve())
112-
.verifiable(TypeMoq.Times.never());
198+
.verifiable(TypeMoq.Times.once());
113199

114200
interpreterPathService = new InterpreterPathService(persistentStateFactory.object, workspaceService.object, []);
115-
await interpreterPathService.copyOldInterpreterStorageValuesToNew(resource);
201+
await interpreterPathService._moveGlobalSettingValueToNewStorage('globalPythonPath');
202+
203+
assert(update.calledWith(undefined, ConfigurationTarget.Global, 'globalPythonPath'));
204+
persistentState.verifyAll();
205+
workspaceConfig.verifyAll();
206+
});
207+
208+
test('If the one-off transfer to new storage has already happened for the user setting, do not update and simply return', async () => {
209+
const update = sinon.stub(InterpreterPathService.prototype, 'update');
210+
const persistentState = TypeMoq.Mock.ofType<IPersistentState<boolean>>();
211+
persistentStateFactory
212+
.setup((p) => p.createGlobalPersistentState<boolean>(isGlobalSettingCopiedKey, false))
213+
.returns(() => persistentState.object);
214+
persistentState.setup((p) => p.value).returns(() => true);
215+
persistentState.setup((p) => p.updateValue(TypeMoq.It.isAny())).verifiable(TypeMoq.Times.never());
216+
217+
interpreterPathService = new InterpreterPathService(persistentStateFactory.object, workspaceService.object, []);
218+
await interpreterPathService._moveGlobalSettingValueToNewStorage('globalPythonPath');
116219

117220
assert(update.notCalled);
118221
persistentState.verifyAll();

0 commit comments

Comments
 (0)