Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests for PYTHONSTARTUP setting #24145

Merged
merged 14 commits into from
Sep 23, 2024
Merged
2 changes: 1 addition & 1 deletion src/test/repl/variableProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { IVariableDescription } from '../../client/repl/variables/types';
import { VariablesProvider } from '../../client/repl/variables/variablesProvider';
import { VariableRequester } from '../../client/repl/variables/variableRequester';

suite.only('ReplVariablesProvider', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a hygiene rule in core to prevent this slipping in

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea and I've made item on this: #24161
I see "local/code-no-test-only": "error", from vscode. Not sure if that local/code is something vscode repository specific, but I think something like:

{
  "plugins": ["mocha"],
  "rules": {
    "mocha/no-exclusive-tests": "error"
  }
}

works too

suite('ReplVariablesProvider', () => {
let provider: VariablesProvider;
let varRequester: TypeMoq.IMock<VariableRequester>;
let notebook: TypeMoq.IMock<NotebookDocument>;
Expand Down
3 changes: 3 additions & 0 deletions src/test/terminals/codeExecution/smartSend.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import * as TypeMoq from 'typemoq';
import * as path from 'path';
import { TextEditor, Selection, Position, TextDocument, Uri } from 'vscode';
Expand Down
125 changes: 125 additions & 0 deletions src/test/terminals/shellIntegration/pythonStartup.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import * as sinon from 'sinon';
import * as TypeMoq from 'typemoq';
import { GlobalEnvironmentVariableCollection, Uri, WorkspaceConfiguration } from 'vscode';
import * as workspaceApis from '../../../client/common/vscodeApis/workspaceApis';
import { registerPythonStartup } from '../../../client/terminals/pythonStartup';
import { IExtensionContext } from '../../../client/common/types';

suite('Terminal - Shell Integration with PYTHONSTARTUP', () => {
let getConfigurationStub: sinon.SinonStub;
let pythonConfig: TypeMoq.IMock<WorkspaceConfiguration>;
let editorConfig: TypeMoq.IMock<WorkspaceConfiguration>;
let context: TypeMoq.IMock<IExtensionContext>;
let createDirectoryStub: sinon.SinonStub;
let copyStub: sinon.SinonStub;
let globalEnvironmentVariableCollection: TypeMoq.IMock<GlobalEnvironmentVariableCollection>;

setup(() => {
context = TypeMoq.Mock.ofType<IExtensionContext>();
globalEnvironmentVariableCollection = TypeMoq.Mock.ofType<GlobalEnvironmentVariableCollection>();

// Question: Why do we have to set up environmentVariableCollection and globalEnvironmentVariableCollection in this flip-flop way?
// Reference: /vscode-python/src/test/interpreters/activation/terminalEnvVarCollectionService.unit.test.ts
context.setup((c) => c.environmentVariableCollection).returns(() => globalEnvironmentVariableCollection.object);
context.setup((c) => c.storageUri).returns(() => Uri.parse('a'));

globalEnvironmentVariableCollection
.setup((c) => c.replace(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.returns(() => Promise.resolve());

globalEnvironmentVariableCollection.setup((c) => c.delete(TypeMoq.It.isAny())).returns(() => Promise.resolve());

getConfigurationStub = sinon.stub(workspaceApis, 'getConfiguration');
createDirectoryStub = sinon.stub(workspaceApis, 'createDirectory');
copyStub = sinon.stub(workspaceApis, 'copy');

pythonConfig = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
editorConfig = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
getConfigurationStub.callsFake((section: string) => {
if (section === 'python') {
return pythonConfig.object;
}
return editorConfig.object;
});

createDirectoryStub.callsFake((_) => Promise.resolve());
copyStub.callsFake((_, __, ___) => Promise.resolve());
});

teardown(() => {
sinon.restore();
});

test('Verify createDirectory is called when shell integration is enabled', async () => {
pythonConfig.setup((p) => p.get('REPL.enableShellIntegration')).returns(() => true);

await registerPythonStartup(context.object);

sinon.assert.calledOnce(createDirectoryStub);
});

test('Verify createDirectory is not called when shell integration is disabled', async () => {
pythonConfig.setup((p) => p.get('REPL.enableShellIntegration')).returns(() => false);

await registerPythonStartup(context.object);

sinon.assert.notCalled(createDirectoryStub);
});

test('Verify copy is called when shell integration is enabled', async () => {
pythonConfig.setup((p) => p.get('REPL.enableShellIntegration')).returns(() => true);

await registerPythonStartup(context.object);

sinon.assert.calledOnce(copyStub);
});

test('Verify copy is not called when shell integration is disabled', async () => {
pythonConfig.setup((p) => p.get('REPL.enableShellIntegration')).returns(() => false);

await registerPythonStartup(context.object);

sinon.assert.notCalled(copyStub);
});

test('PYTHONSTARTUP is set when enableShellIntegration setting is true', async () => {
pythonConfig.setup((p) => p.get('REPL.enableShellIntegration')).returns(() => true);

await registerPythonStartup(context.object);

globalEnvironmentVariableCollection.verify(
(c) => c.replace('PYTHONSTARTUP', TypeMoq.It.isAny(), TypeMoq.It.isAny()),
TypeMoq.Times.once(),
);
});

test('environmentCollection should not remove PYTHONSTARTUP when enableShellIntegration setting is true', async () => {
pythonConfig.setup((p) => p.get('REPL.enableShellIntegration')).returns(() => true);

await registerPythonStartup(context.object);

globalEnvironmentVariableCollection.verify((c) => c.delete('PYTHONSTARTUP'), TypeMoq.Times.never());
});

test('PYTHONSTARTUP is not set when enableShellIntegration setting is false', async () => {
pythonConfig.setup((p) => p.get('REPL.enableShellIntegration')).returns(() => false);

await registerPythonStartup(context.object);

globalEnvironmentVariableCollection.verify(
(c) => c.replace('PYTHONSTARTUP', TypeMoq.It.isAny(), TypeMoq.It.isAny()),
TypeMoq.Times.never(),
);
});

test('PYTHONSTARTUP is deleted when enableShellIntegration setting is false', async () => {
pythonConfig.setup((p) => p.get('REPL.enableShellIntegration')).returns(() => false);

await registerPythonStartup(context.object);

globalEnvironmentVariableCollection.verify((c) => c.delete('PYTHONSTARTUP'), TypeMoq.Times.once());
});
});
Loading