From 54031b90f668c5012b1e4e7394086aeedc407072 Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Fri, 19 Dec 2025 23:31:31 +1100 Subject: [PATCH] fix(completions): resolve Windows compatibility issues in zsh-installer tests - 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 --- src/utils/file-system.ts | 20 ++++++++++++++++--- .../installers/zsh-installer.test.ts | 15 +++++++++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/utils/file-system.ts b/src/utils/file-system.ts index fc892a11..364b5cda 100644 --- a/src/utils/file-system.ts +++ b/src/utils/file-system.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs'; +import { promises as fs, constants as fsConstants } from 'fs'; import path from 'path'; function isMarkerOnOwnLine(content: string, markerIndex: number, markerLength: number): boolean { @@ -93,10 +93,24 @@ export class FileSystemUtils { return true; } - return (stats.mode & 0o222) !== 0; + // On Windows, stats.mode doesn't reliably indicate write permissions. + // Use fs.access with W_OK to check actual write permissions cross-platform. + try { + await fs.access(filePath, fsConstants.W_OK); + return true; + } catch { + return false; + } } catch (error: any) { if (error.code === 'ENOENT') { - return true; + // File doesn't exist; check if we can write to the parent directory + const parentDir = path.dirname(filePath); + try { + await fs.access(parentDir, fsConstants.W_OK); + return true; + } catch { + return false; + } } console.debug(`Unable to determine write permissions for ${filePath}: ${error.message}`); diff --git a/test/core/completions/installers/zsh-installer.test.ts b/test/core/completions/installers/zsh-installer.test.ts index 8055f1b1..a6827f4b 100644 --- a/test/core/completions/installers/zsh-installer.test.ts +++ b/test/core/completions/installers/zsh-installer.test.ts @@ -195,7 +195,11 @@ describe('ZshInstaller', () => { it('should handle installation errors gracefully', async () => { // Create installer with non-existent/invalid home directory - const invalidInstaller = new ZshInstaller('/root/invalid/nonexistent/path'); + // Use a path that will fail on both Unix and Windows + const invalidPath = process.platform === 'win32' + ? 'Z:\\nonexistent\\invalid\\path' // Non-existent drive letter on Windows + : '/root/invalid/nonexistent/path'; // Permission-denied path on Unix + const invalidInstaller = new ZshInstaller(invalidPath); const result = await invalidInstaller.install(testScript); @@ -503,7 +507,11 @@ describe('ZshInstaller', () => { it('should handle write permission errors gracefully', async () => { // Create installer with path that can't be written - const invalidInstaller = new ZshInstaller('/root/invalid/path'); + // Use a path that will fail on both Unix and Windows + const invalidPath = process.platform === 'win32' + ? 'Z:\\nonexistent\\invalid\\path' // Non-existent drive letter on Windows + : '/root/invalid/path'; // Permission-denied path on Unix + const invalidInstaller = new ZshInstaller(invalidPath); const result = await invalidInstaller.configureZshrc(completionsDir); @@ -641,7 +649,8 @@ describe('ZshInstaller', () => { if (exists) { const content = await fs.readFile(zshrcPath, 'utf-8'); expect(content).toContain('fpath='); - expect(content).toContain('custom/completions'); + // Check for custom/completions or custom\completions (Windows path separator) + expect(content).toMatch(/custom[/\\]completions/); } });