fix(core): handle URI-encoded workspace paths in IdeClient (#17476)

Co-authored-by: Shreya Keshive <shreyakeshive@google.com>
This commit is contained in:
Dongjun Shin
2026-01-27 02:09:43 +09:00
committed by GitHub
parent 93c62a2bdc
commit 4827333c48
4 changed files with 186 additions and 19 deletions
+56 -2
View File
@@ -4,8 +4,23 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { escapePath, unescapePath, isSubpath, shortenPath } from './paths.js';
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
import * as fs from 'node:fs';
import {
escapePath,
unescapePath,
isSubpath,
shortenPath,
resolveToRealPath,
} from './paths.js';
vi.mock('node:fs', async (importOriginal) => {
const actual = await importOriginal<typeof fs>();
return {
...(actual as object),
realpathSync: (p: string) => p,
};
});
describe('escapePath', () => {
it.each([
@@ -472,3 +487,42 @@ describe('shortenPath', () => {
});
});
});
describe('resolveToRealPath', () => {
it.each([
{
description:
'should return path as-is if no special characters or protocol',
input: '/simple/path',
expected: '/simple/path',
},
{
description: 'should remove file:// protocol',
input: 'file:///path/to/file',
expected: '/path/to/file',
},
{
description: 'should decode URI components',
input: '/path/to/some%20folder',
expected: '/path/to/some folder',
},
{
description: 'should handle both file protocol and encoding',
input: 'file:///path/to/My%20Project',
expected: '/path/to/My Project',
},
])('$description', ({ input, expected }) => {
expect(resolveToRealPath(input)).toBe(expected);
});
it('should return decoded path even if fs.realpathSync fails', () => {
vi.spyOn(fs, 'realpathSync').mockImplementationOnce(() => {
throw new Error('File not found');
});
const input = 'file:///path/to/New%20Project';
const expected = '/path/to/New Project';
expect(resolveToRealPath(input)).toBe(expected);
});
});