Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/onboardDebug/test/node/debuggableCommandIdentifier.spec.ts
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
/* eslint-disable local/code-no-unused-expressions */
6
7
8
import { SinonStub, stub } from 'sinon';
9
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
10
import { ConfigKey, IConfigurationService } from '../../../../platform/configuration/common/configurationService';
11
import { ITestingServicesAccessor } from '../../../../platform/test/node/services';
12
import { TestWorkspaceService } from '../../../../platform/test/node/testWorkspaceService';
13
import { IWorkspaceService } from '../../../../platform/workspace/common/workspaceService';
14
import { CancellationToken } from '../../../../util/vs/base/common/cancellation';
15
import { basename } from '../../../../util/vs/base/common/path';
16
import { URI } from '../../../../util/vs/base/common/uri';
17
import { IInstantiationService } from '../../../../util/vs/platform/instantiation/common/instantiation';
18
import { createExtensionUnitTestingServices } from '../../../test/node/services';
19
import { DebuggableCommandIdentifier } from '../../node/debuggableCommandIdentifier';
20
import { ILanguageToolsProvider } from '../../node/languageToolsProvider';
21
22
describe('DebuggableCommandIdentifier', () => {
23
let accessor: ITestingServicesAccessor;
24
let debuggableCommandIdentifier: DebuggableCommandIdentifier;
25
let getToolsForLanguages: SinonStub;
26
27
const setConfigEnabled = (enabled: boolean) =>
28
accessor.get(IConfigurationService).setConfig(ConfigKey.TerminalToDebuggerEnabled, enabled);
29
30
beforeEach(() => {
31
getToolsForLanguages = stub().resolves({ ok: true, commands: ['mytool'] });
32
const testingServiceCollection = createExtensionUnitTestingServices();
33
testingServiceCollection.define(ILanguageToolsProvider, {
34
_serviceBrand: undefined,
35
getToolsForLanguages
36
});
37
accessor = testingServiceCollection.createTestingAccessor();
38
39
setConfigEnabled(true);
40
debuggableCommandIdentifier = accessor
41
.get(IInstantiationService)
42
.createInstance(DebuggableCommandIdentifier);
43
});
44
45
afterEach(() => {
46
debuggableCommandIdentifier.dispose();
47
});
48
49
it('should return false if globally disabled', async () => {
50
setConfigEnabled(false);
51
const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'node index.js', CancellationToken.None);
52
expect(result).to.be.false;
53
});
54
55
it('should return true for well-known commands', async () => {
56
const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'node index.js', CancellationToken.None);
57
expect(result).to.be.true;
58
});
59
60
it('should return false for unknown commands', async () => {
61
const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'mytool', CancellationToken.None);
62
expect(result).to.be.false;
63
expect(getToolsForLanguages.called).to.be.false;
64
});
65
66
it('should return true for locals', async () => {
67
const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'mytool', CancellationToken.None);
68
expect(result).to.be.false;
69
expect(getToolsForLanguages.called).to.be.false;
70
});
71
72
// todo@connor4312: these work on macos locally but fail in CI, look into it
73
it.skip('should return true if referencing an absolute path', async () => {
74
const result = await debuggableCommandIdentifier.isDebuggable(undefined, __filename, CancellationToken.None);
75
expect(result).to.be.true;
76
});
77
78
// todo@connor4312: these work on macos locally but fail in CI, look into it
79
it.skip('should return true if referencing a relative path in a cwd', async () => {
80
const result = await debuggableCommandIdentifier.isDebuggable(URI.file(__dirname), basename(__filename), CancellationToken.None);
81
expect(result).to.be.true;
82
});
83
84
it('should not call the model tools for known languages', async () => {
85
(accessor.get(IWorkspaceService) as TestWorkspaceService)
86
.didOpenTextDocumentEmitter.fire({ languageId: 'javascript' } as any);
87
88
const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'othertool hello', CancellationToken.None);
89
expect(result).to.be.false;
90
expect(getToolsForLanguages.callCount).to.equal(0);
91
});
92
93
it('should return true for model provided commands', async () => {
94
(accessor.get(IWorkspaceService) as TestWorkspaceService)
95
.didOpenTextDocumentEmitter.fire({ languageId: 'mylang' } as any);
96
const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'mytool hello', CancellationToken.None);
97
expect(result).to.be.true;
98
expect(getToolsForLanguages.calledWith(['mylang'])).to.be.true;
99
100
// should not call again because no new langauge was seen:
101
const result2 = await debuggableCommandIdentifier.isDebuggable(undefined, 'othertool hello', CancellationToken.None);
102
expect(result2).to.be.false;
103
expect(getToolsForLanguages.callCount).to.equal(1);
104
});
105
106
it('returns treatment value 1', async () => {
107
accessor.get(IConfigurationService).setConfig(ConfigKey.Advanced.TerminalToDebuggerPatterns, ['othert']);
108
const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'othert hello', CancellationToken.None);
109
expect(result).to.be.true;
110
});
111
112
it('return treatment value 2', async () => {
113
accessor.get(IConfigurationService).setConfig(ConfigKey.Advanced.TerminalToDebuggerPatterns, ['!mytool']);
114
const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'mytool hello', CancellationToken.None);
115
expect(result).to.be.false;
116
});
117
118
// it('should return true for commands matching specific treatment', async () => {
119
// (configurationService.getConfig as sinon.SinonStub).returns(['node']);
120
// const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'node index.js', CancellationToken.None);
121
// expect(result).to.be.true;
122
// });
123
124
// it('should return false for commands matching specific exclusion', async () => {
125
// (configurationService.getConfig as sinon.SinonStub).returns(['!node']);
126
// const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'node index.js', CancellationToken.None);
127
// expect(result).to.be.false;
128
// });
129
130
// it('should query language model for unknown commands', async () => {
131
// (context.globalState.get as sinon.SinonStub).returns({ languages: ['unknown'], commands: [] });
132
// (instantiationService.createInstance().getToolsForLanguages as sinon.SinonStub).resolves({ commands: ['unknowncommand'], ok: true });
133
// const result = await debuggableCommandIdentifier.isDebuggable(undefined, 'unknowncommand', CancellationToken.None);
134
// expect(result).to.be.true;
135
// });
136
});
137
138