Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/services/dialogs/test/browser/simpleFileDialog.test.ts
13406 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 assert from 'assert';
7
import { URI } from '../../../../../base/common/uri.js';
8
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
9
import { AGENT_HOST_SCHEME, AGENT_HOST_LABEL_FORMATTER, agentHostAuthority } from '../../../../../platform/agentHost/common/agentHostUri.js';
10
import { agentHostUri } from '../../../../../platform/agentHost/common/agentHostFileSystemProvider.js';
11
12
/**
13
* Tests for the scoped path prefix logic used by SimpleFileDialog.
14
*
15
* SimpleFileDialog is tightly coupled to many services and difficult to
16
* instantiate in isolation. Instead of mocking the full dialog, we test
17
* the underlying data transformations that drive the fix:
18
*
19
* 1. computeScopedPathPrefix - derived from comparing the raw URI path
20
* with the label-service-formatted output.
21
* 2. pathFromUri - stripping the prefix from the raw path.
22
* 3. remoteUriFrom - re-adding the prefix to user input.
23
*/
24
suite('SimpleFileDialog - scoped path prefix', () => {
25
26
ensureNoDisposablesAreLeakedInTestSuite();
27
28
/**
29
* Replicates the stripPathSegments logic from the label service to
30
* produce the display path that the label formatter would return.
31
*/
32
function labelFormatterDisplay(path: string, stripSegments: number): string {
33
let pos = 0;
34
for (let i = 0; i < stripSegments; i++) {
35
const next = path.indexOf('/', pos + 1);
36
if (next === -1) {
37
break;
38
}
39
pos = next;
40
}
41
return path.substring(pos);
42
}
43
44
/**
45
* Replicates SimpleFileDialog.computeScopedPathPrefix:
46
* compares raw URI path with formatted display path to find the prefix.
47
*/
48
function computeScopedPathPrefix(uri: URI, displayPath: string): string {
49
const fullPath = uri.path;
50
if (displayPath && fullPath.endsWith(displayPath)) {
51
return fullPath.substring(0, fullPath.length - displayPath.length);
52
}
53
return '';
54
}
55
56
/**
57
* Replicates the scoped branch of SimpleFileDialog.pathFromUri:
58
* strips the prefix from the raw URI path.
59
*/
60
function pathFromUri(uri: URI, prefix: string, endWithSeparator: boolean = false): string {
61
let path = uri.path;
62
if (prefix && path.startsWith(prefix)) {
63
path = path.substring(prefix.length);
64
}
65
let result = path.replace(/\n/g, '');
66
result = result.replace(/\\/g, '/');
67
if (endWithSeparator && !result.endsWith('/')) {
68
result = result + '/';
69
}
70
return result;
71
}
72
73
/**
74
* Replicates the scoped branch of SimpleFileDialog.remoteUriFrom:
75
* re-adds the prefix to construct a proper URI.
76
*/
77
function remoteUriFrom(path: string, scheme: string, authority: string, prefix: string): URI {
78
return URI.from({ scheme, authority, path: prefix + path });
79
}
80
81
test('computeScopedPathPrefix extracts prefix for agent host URI', () => {
82
const authority = agentHostAuthority('localhost:8089');
83
const uri = agentHostUri(authority, '/Users/roblou/code');
84
85
const displayPath = labelFormatterDisplay(uri.path, AGENT_HOST_LABEL_FORMATTER.formatting.stripPathSegments!);
86
const prefix = computeScopedPathPrefix(uri, displayPath);
87
88
assert.strictEqual(prefix, '/file/-');
89
assert.strictEqual(displayPath, '/Users/roblou/code');
90
});
91
92
test('computeScopedPathPrefix works for URI with original authority', () => {
93
const authority = agentHostAuthority('localhost:8089');
94
const originalUri = URI.from({ scheme: 'agenthost-content', authority: 'session1', path: '/snap/before' });
95
const uri = URI.from({
96
scheme: AGENT_HOST_SCHEME,
97
authority,
98
path: `/${originalUri.scheme}/${originalUri.authority}${originalUri.path}`,
99
});
100
101
const displayPath = labelFormatterDisplay(uri.path, AGENT_HOST_LABEL_FORMATTER.formatting.stripPathSegments!);
102
const prefix = computeScopedPathPrefix(uri, displayPath);
103
104
assert.strictEqual(prefix, '/agenthost-content/session1');
105
assert.strictEqual(displayPath, '/snap/before');
106
});
107
108
test('computeScopedPathPrefix returns empty for scheme without stripping', () => {
109
const uri = URI.from({ scheme: 'file', path: '/Users/roblou/code' });
110
// If display matches the full path, prefix is empty
111
const prefix = computeScopedPathPrefix(uri, '/Users/roblou/code');
112
assert.strictEqual(prefix, '');
113
});
114
115
test('pathFromUri strips prefix to show clean path', () => {
116
const authority = agentHostAuthority('localhost:8089');
117
const uri = agentHostUri(authority, '/Users/roblou/code');
118
const prefix = '/file/-';
119
120
assert.strictEqual(pathFromUri(uri, prefix), '/Users/roblou/code');
121
});
122
123
test('pathFromUri with trailing separator', () => {
124
const authority = agentHostAuthority('localhost:8089');
125
const uri = agentHostUri(authority, '/Users/roblou/code');
126
const prefix = '/file/-';
127
128
assert.strictEqual(pathFromUri(uri, prefix, true), '/Users/roblou/code/');
129
});
130
131
test('pathFromUri without prefix returns raw path', () => {
132
const uri = URI.from({ scheme: 'file', path: '/Users/roblou/code' });
133
assert.strictEqual(pathFromUri(uri, ''), '/Users/roblou/code');
134
});
135
136
test('remoteUriFrom re-adds prefix to reconstruct encoded URI', () => {
137
const authority = agentHostAuthority('localhost:8089');
138
const prefix = '/file/-';
139
const cleanPath = '/Users/roblou/code';
140
141
const result = remoteUriFrom(cleanPath, AGENT_HOST_SCHEME, authority, prefix);
142
143
assert.strictEqual(result.scheme, AGENT_HOST_SCHEME);
144
assert.strictEqual(result.authority, authority);
145
assert.strictEqual(result.path, '/file/-/Users/roblou/code');
146
});
147
148
test('full round-trip: URI -> pathFromUri -> remoteUriFrom -> same URI', () => {
149
const authority = agentHostAuthority('localhost:8089');
150
const originalPath = '/Users/roblou/code/vscode';
151
const uri = agentHostUri(authority, originalPath);
152
153
// Compute prefix
154
const displayPath = labelFormatterDisplay(uri.path, AGENT_HOST_LABEL_FORMATTER.formatting.stripPathSegments!);
155
const prefix = computeScopedPathPrefix(uri, displayPath);
156
157
// pathFromUri extracts clean path
158
const cleanPath = pathFromUri(uri, prefix);
159
assert.strictEqual(cleanPath, originalPath);
160
161
// remoteUriFrom reconstructs the original URI
162
const reconstructed = remoteUriFrom(cleanPath, AGENT_HOST_SCHEME, authority, prefix);
163
assert.strictEqual(reconstructed.path, uri.path);
164
assert.strictEqual(reconstructed.scheme, uri.scheme);
165
assert.strictEqual(reconstructed.authority, uri.authority);
166
});
167
168
test('createBackItem root detection with prefix', () => {
169
const authority = agentHostAuthority('localhost:8089');
170
const prefix = '/file/-';
171
172
// Simulate root folder: path = prefix + '/'
173
const rootUri = URI.from({ scheme: AGENT_HOST_SCHEME, authority, path: prefix + '/' });
174
const pathAfterPrefix = rootUri.path.substring(prefix.length);
175
assert.strictEqual(pathAfterPrefix === '/' || pathAfterPrefix === '', true, 'root should be detected');
176
177
// Simulate non-root folder
178
const subUri = URI.from({ scheme: AGENT_HOST_SCHEME, authority, path: prefix + '/Users/roblou' });
179
const subPathAfterPrefix = subUri.path.substring(prefix.length);
180
assert.notStrictEqual(subPathAfterPrefix, '/');
181
assert.notStrictEqual(subPathAfterPrefix, '');
182
});
183
});
184
185