Skip to content

Commit cefb471

Browse files
authored
fix(completions): resolve Windows compatibility issues in zsh-installer tests (#373)
- Fix canWriteFile to use fs.access with W_OK flag instead of Unix-style permission bits (stats.mode & 0o222) which don't work on Windows - Update test paths to use platform-specific invalid paths that fail on both Unix and Windows - Use regex for path separator matching in test assertions
1 parent 5e1cef3 commit cefb471

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

src/utils/file-system.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { promises as fs } from 'fs';
1+
import { promises as fs, constants as fsConstants } from 'fs';
22
import path from 'path';
33

44
function isMarkerOnOwnLine(content: string, markerIndex: number, markerLength: number): boolean {
@@ -93,10 +93,24 @@ export class FileSystemUtils {
9393
return true;
9494
}
9595

96-
return (stats.mode & 0o222) !== 0;
96+
// On Windows, stats.mode doesn't reliably indicate write permissions.
97+
// Use fs.access with W_OK to check actual write permissions cross-platform.
98+
try {
99+
await fs.access(filePath, fsConstants.W_OK);
100+
return true;
101+
} catch {
102+
return false;
103+
}
97104
} catch (error: any) {
98105
if (error.code === 'ENOENT') {
99-
return true;
106+
// File doesn't exist; check if we can write to the parent directory
107+
const parentDir = path.dirname(filePath);
108+
try {
109+
await fs.access(parentDir, fsConstants.W_OK);
110+
return true;
111+
} catch {
112+
return false;
113+
}
100114
}
101115

102116
console.debug(`Unable to determine write permissions for ${filePath}: ${error.message}`);

test/core/completions/installers/zsh-installer.test.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,11 @@ describe('ZshInstaller', () => {
195195

196196
it('should handle installation errors gracefully', async () => {
197197
// Create installer with non-existent/invalid home directory
198-
const invalidInstaller = new ZshInstaller('/root/invalid/nonexistent/path');
198+
// Use a path that will fail on both Unix and Windows
199+
const invalidPath = process.platform === 'win32'
200+
? 'Z:\\nonexistent\\invalid\\path' // Non-existent drive letter on Windows
201+
: '/root/invalid/nonexistent/path'; // Permission-denied path on Unix
202+
const invalidInstaller = new ZshInstaller(invalidPath);
199203

200204
const result = await invalidInstaller.install(testScript);
201205

@@ -503,7 +507,11 @@ describe('ZshInstaller', () => {
503507

504508
it('should handle write permission errors gracefully', async () => {
505509
// Create installer with path that can't be written
506-
const invalidInstaller = new ZshInstaller('/root/invalid/path');
510+
// Use a path that will fail on both Unix and Windows
511+
const invalidPath = process.platform === 'win32'
512+
? 'Z:\\nonexistent\\invalid\\path' // Non-existent drive letter on Windows
513+
: '/root/invalid/path'; // Permission-denied path on Unix
514+
const invalidInstaller = new ZshInstaller(invalidPath);
507515

508516
const result = await invalidInstaller.configureZshrc(completionsDir);
509517

@@ -641,7 +649,8 @@ describe('ZshInstaller', () => {
641649
if (exists) {
642650
const content = await fs.readFile(zshrcPath, 'utf-8');
643651
expect(content).toContain('fpath=');
644-
expect(content).toContain('custom/completions');
652+
// Check for custom/completions or custom\completions (Windows path separator)
653+
expect(content).toMatch(/custom[/\\]completions/);
645654
}
646655
});
647656

0 commit comments

Comments
 (0)