Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/prompts/test/node/promptPathRepresentationService.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
6
import { beforeEach, describe, expect, it } from 'vitest';
7
import { Schemas } from '../../../../util/vs/base/common/network';
8
import { isWindows } from '../../../../util/vs/base/common/platform';
9
import { URI } from '../../../../util/vs/base/common/uri';
10
import { TestWorkspaceService } from '../../../test/node/testWorkspaceService';
11
import { PromptPathRepresentationService, TestPromptPathRepresentationService } from '../../common/promptPathRepresentationService';
12
13
/**
14
* Subclass that simulates a Windows environment for testing Windows-specific code paths.
15
*/
16
class WindowsPromptPathRepresentationService extends PromptPathRepresentationService {
17
protected override isWindows() {
18
return true;
19
}
20
}
21
22
describe('PromptPathRepresentationService', () => {
23
let workspaceService: TestWorkspaceService;
24
let service: PromptPathRepresentationService;
25
26
beforeEach(() => {
27
workspaceService = new TestWorkspaceService();
28
service = new PromptPathRepresentationService(workspaceService);
29
});
30
31
describe('getFilePath', () => {
32
it('returns fsPath for file scheme URIs', () => {
33
const uri = URI.file('/home/user/project/file.ts');
34
expect(service.getFilePath(uri)).toBe(uri.fsPath);
35
});
36
37
it('returns fsPath for vscode-remote scheme URIs', () => {
38
const uri = URI.from({ scheme: Schemas.vscodeRemote, path: '/home/user/project/file.ts', authority: 'ssh-remote+myhost' });
39
expect(service.getFilePath(uri)).toBe(uri.fsPath);
40
});
41
42
it('returns toString for other schemes', () => {
43
const uri = URI.from({ scheme: 'untitled', path: '/Untitled-1' });
44
expect(service.getFilePath(uri)).toBe(uri.toString());
45
});
46
47
it('returns toString for virtual filesystem schemes', () => {
48
const uri = URI.from({ scheme: 'vscode-vfs', authority: 'github', path: '/owner/repo/file.ts' });
49
expect(service.getFilePath(uri)).toBe(uri.toString());
50
});
51
});
52
53
describe('resolveFilePath', () => {
54
it('resolves posix absolute paths to file URIs', () => {
55
const result = service.resolveFilePath('/home/user/project/file.ts');
56
expect(result).toBeDefined();
57
expect(result!.scheme).toBe(Schemas.file);
58
expect(result!.path).toBe('/home/user/project/file.ts');
59
});
60
61
it('resolves posix paths with a custom predominant scheme', () => {
62
const result = service.resolveFilePath('/home/user/project/file.ts', Schemas.vscodeRemote);
63
expect(result).toBeDefined();
64
expect(result!.scheme).toBe(Schemas.vscodeRemote);
65
expect(result!.path).toBe('/home/user/project/file.ts');
66
});
67
68
it('parses valid URI strings', () => {
69
const result = service.resolveFilePath('https://example.com/path');
70
expect(result).toBeDefined();
71
expect(result!.scheme).toBe('https');
72
});
73
74
it('parses file:// URI strings', () => {
75
const result = service.resolveFilePath('file:///home/user/file.ts');
76
expect(result).toBeDefined();
77
expect(result!.scheme).toBe(Schemas.file);
78
expect(result!.path).toBe('/home/user/file.ts');
79
});
80
81
it('parses vscode-vfs URI strings', () => {
82
const result = service.resolveFilePath('vscode-vfs://github/owner/repo/file.ts');
83
expect(result).toBeDefined();
84
expect(result!.scheme).toBe('vscode-vfs');
85
expect(result!.path).toBe('/owner/repo/file.ts');
86
});
87
88
it('returns undefined for relative paths', () => {
89
expect(service.resolveFilePath('src/file.ts')).toBeUndefined();
90
});
91
92
it('returns undefined for empty strings', () => {
93
expect(service.resolveFilePath('')).toBeUndefined();
94
});
95
96
it('returns undefined for plain text without scheme', () => {
97
expect(service.resolveFilePath('just some text')).toBeUndefined();
98
});
99
100
it('roundtrips posix file URIs through getFilePath and resolveFilePath', () => {
101
const original = URI.file('/home/user/project/file.ts');
102
const filepath = service.getFilePath(original);
103
const resolved = service.resolveFilePath(filepath);
104
expect(resolved).toBeDefined();
105
expect(resolved!.path).toBe(original.path);
106
});
107
});
108
109
describe.skipIf(!isWindows)('resolveFilePath (Windows simulation)', () => {
110
let windowsService: WindowsPromptPathRepresentationService;
111
112
beforeEach(() => {
113
workspaceService = new TestWorkspaceService();
114
windowsService = new WindowsPromptPathRepresentationService(workspaceService);
115
});
116
117
it('resolves Windows drive-letter paths', () => {
118
const result = windowsService.resolveFilePath('C:\\Users\\user\\file.ts');
119
expect(result).toBeDefined();
120
expect(result!.scheme).toBe(Schemas.file);
121
expect(result!.path).toBe('/C:/Users/user/file.ts');
122
});
123
124
it('collapses double-escaped backslashes', () => {
125
const result = windowsService.resolveFilePath('C:\\\\Users\\\\user\\\\file.ts');
126
expect(result).toBeDefined();
127
expect(result!.path).toBe('/C:/Users/user/file.ts');
128
});
129
130
it('preserves UNC paths while collapsing extra backslashes', () => {
131
const result = windowsService.resolveFilePath('\\\\server\\share\\\\file.ts');
132
expect(result).toBeDefined();
133
// UNC paths get their leading \\ preserved
134
expect(result?.toString()).toContain('server');
135
expect(result?.toString()).toContain('share');
136
});
137
138
it('resolves backslash-only path as Windows path', () => {
139
const result = windowsService.resolveFilePath('\\Users\\file.ts');
140
expect(result).toBeDefined();
141
expect(result!.scheme).toBe(Schemas.file);
142
});
143
144
it('prepends drive letter for posix paths on Windows when workspace folders exist', () => {
145
const folderUri = URI.file('D:/Projects/myapp');
146
workspaceService = new TestWorkspaceService([folderUri]);
147
windowsService = new WindowsPromptPathRepresentationService(workspaceService);
148
149
const result = windowsService.resolveFilePath('/Projects/myapp/src/file.ts');
150
expect(result).toBeDefined();
151
expect(result!.scheme).toBe(Schemas.file);
152
// Should have prepended the drive letter from workspace folder
153
expect(result!.path).toMatch(/^\/d:/i);
154
});
155
156
it('does not prepend drive letter for posix paths on Windows when workspace folders don\'t exist', () => {
157
const folderUri = URI.file('D:/Projects/myapp2');
158
workspaceService = new TestWorkspaceService([folderUri]);
159
windowsService = new WindowsPromptPathRepresentationService(workspaceService);
160
161
const result = windowsService.resolveFilePath('/Projects/myapp/src/file.ts');
162
expect(result).toBeDefined();
163
expect(result!.scheme).toBe(Schemas.file);
164
// Should not have prepended the drive letter since workspace folders don't match
165
expect(result!.path).toBe('/Projects/myapp/src/file.ts');
166
});
167
168
it('does not prepend drive letter for posix paths when predominant scheme is not file', () => {
169
const folderUri = URI.file('C:/Projects');
170
workspaceService = new TestWorkspaceService([folderUri]);
171
windowsService = new WindowsPromptPathRepresentationService(workspaceService);
172
173
const result = windowsService.resolveFilePath('/Projects/file.ts', Schemas.vscodeRemote);
174
expect(result).toBeDefined();
175
expect(result!.scheme).toBe(Schemas.vscodeRemote);
176
// Should not have a drive letter since predominantScheme is not file
177
expect(result!.path).toBe('/Projects/file.ts');
178
});
179
180
it('resolves posix paths without drive letter prepended when no workspace folders', () => {
181
const result = windowsService.resolveFilePath('/home/user/file.ts');
182
expect(result).toBeDefined();
183
// No workspace folders, so no drive letter rectification
184
expect(result!.path).toBe('/home/user/file.ts');
185
});
186
});
187
188
describe('getExampleFilePath', () => {
189
it.skipIf(isWindows)('returns a posix-style file path on non-Windows', () => {
190
const result = service.getExampleFilePath('/workspace/src/file.ts');
191
expect(result).toContain('/workspace/src/file.ts');
192
});
193
194
it.skipIf(!isWindows)('returns a Windows-style path when on Windows', () => {
195
workspaceService = new TestWorkspaceService();
196
const windowsService = new WindowsPromptPathRepresentationService(workspaceService);
197
const result = windowsService.getExampleFilePath('/workspace/src/file.ts');
198
// On Windows, the example path should include c: drive letter (URI.file lowercases it)
199
expect(result.toLowerCase()).toContain('c:');
200
expect(result).toContain('workspace');
201
});
202
});
203
});
204
205
describe('TestPromptPathRepresentationService', () => {
206
let workspaceService: TestWorkspaceService;
207
let service: TestPromptPathRepresentationService;
208
209
beforeEach(() => {
210
workspaceService = new TestWorkspaceService();
211
service = new TestPromptPathRepresentationService(workspaceService);
212
});
213
214
describe('getFilePath', () => {
215
it('returns posix path for file scheme URIs (not fsPath)', () => {
216
const uri = URI.file('/home/user/project/file.ts');
217
expect(service.getFilePath(uri)).toBe(uri.path);
218
});
219
220
it('returns posix path for vscode-remote scheme URIs', () => {
221
const uri = URI.from({ scheme: Schemas.vscodeRemote, path: '/home/user/project/file.ts', authority: 'ssh-remote+myhost' });
222
expect(service.getFilePath(uri)).toBe(uri.path);
223
});
224
225
it('returns toString for other schemes', () => {
226
const uri = URI.from({ scheme: 'untitled', path: '/Untitled-1' });
227
expect(service.getFilePath(uri)).toBe(uri.toString());
228
});
229
});
230
231
describe('getExampleFilePath', () => {
232
it('always returns posix path regardless of platform', () => {
233
const result = service.getExampleFilePath('/workspace/src/file.ts');
234
expect(result).toBe('/workspace/src/file.ts');
235
});
236
});
237
});
238
239