Initial commit
This commit is contained in:
603
skills/windows-git-bash-testing.md
Normal file
603
skills/windows-git-bash-testing.md
Normal file
@@ -0,0 +1,603 @@
|
||||
## 🚨 CRITICAL GUIDELINES
|
||||
|
||||
### Windows File Path Requirements
|
||||
|
||||
**MANDATORY: Always Use Backslashes on Windows for File Paths**
|
||||
|
||||
When using Edit or Write tools on Windows, you MUST use backslashes (`\`) in file paths, NOT forward slashes (`/`).
|
||||
|
||||
**Examples:**
|
||||
- ❌ WRONG: `D:/repos/project/file.tsx`
|
||||
- ✅ CORRECT: `D:\repos\project\file.tsx`
|
||||
|
||||
This applies to:
|
||||
- Edit tool file_path parameter
|
||||
- Write tool file_path parameter
|
||||
- All file operations on Windows systems
|
||||
|
||||
### Documentation Guidelines
|
||||
|
||||
**NEVER create new documentation files unless explicitly requested by the user.**
|
||||
|
||||
- **Priority**: Update existing README.md files rather than creating new documentation
|
||||
- **Repository cleanliness**: Keep repository root clean - only README.md unless user requests otherwise
|
||||
- **Style**: Documentation should be concise, direct, and professional - avoid AI-generated tone
|
||||
- **User preference**: Only create additional .md files when user specifically asks for documentation
|
||||
|
||||
---
|
||||
|
||||
# Windows and Git Bash Testing Compatibility Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This guide provides essential knowledge for running Vitest, Playwright, and MSW tests on Windows, particularly in Git Bash/MINGW environments. It addresses common path conversion issues, shell detection, and cross-platform test execution patterns.
|
||||
|
||||
## Shell Detection in Test Environments
|
||||
|
||||
### Detecting Git Bash/MINGW
|
||||
|
||||
When running tests in Git Bash or MINGW environments, use these detection methods:
|
||||
|
||||
**Method 1: Environment Variable (Most Reliable)**
|
||||
```javascript
|
||||
// Detect Git Bash/MINGW in Node.js test setup
|
||||
function isGitBash() {
|
||||
return !!(process.env.MSYSTEM); // MINGW64, MINGW32, MSYS
|
||||
}
|
||||
|
||||
function isWindows() {
|
||||
return process.platform === 'win32';
|
||||
}
|
||||
|
||||
function needsPathConversion() {
|
||||
return isWindows() && isGitBash();
|
||||
}
|
||||
```
|
||||
|
||||
**Method 2: Using uname in Setup Scripts**
|
||||
```bash
|
||||
# In bash test setup scripts
|
||||
case "$(uname -s)" in
|
||||
MINGW64*|MINGW32*|MSYS_NT*)
|
||||
# Git Bash/MINGW environment
|
||||
export TEST_ENV="mingw"
|
||||
;;
|
||||
CYGWIN*)
|
||||
# Cygwin environment
|
||||
export TEST_ENV="cygwin"
|
||||
;;
|
||||
Linux*)
|
||||
export TEST_ENV="linux"
|
||||
;;
|
||||
Darwin*)
|
||||
export TEST_ENV="macos"
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
**Method 3: Combined Detection for Test Configuration**
|
||||
```javascript
|
||||
// vitest.config.js or test setup
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
function detectShell() {
|
||||
// Check MSYSTEM first (most reliable for Git Bash)
|
||||
if (process.env.MSYSTEM) {
|
||||
return { type: 'mingw', subsystem: process.env.MSYSTEM };
|
||||
}
|
||||
|
||||
// Try uname if available
|
||||
try {
|
||||
const uname = execSync('uname -s', { encoding: 'utf8' }).trim();
|
||||
if (uname.startsWith('MINGW')) return { type: 'mingw' };
|
||||
if (uname.startsWith('CYGWIN')) return { type: 'cygwin' };
|
||||
if (uname === 'Darwin') return { type: 'macos' };
|
||||
if (uname === 'Linux') return { type: 'linux' };
|
||||
} catch {
|
||||
// uname not available (likely Windows cmd/PowerShell)
|
||||
}
|
||||
|
||||
return { type: 'unknown', platform: process.platform };
|
||||
}
|
||||
|
||||
const shell = detectShell();
|
||||
console.log('Running tests in:', shell.type);
|
||||
```
|
||||
|
||||
## Path Conversion Issues and Solutions
|
||||
|
||||
### Common Path Conversion Problems
|
||||
|
||||
Git Bash automatically converts Unix-style paths to Windows paths, which can cause issues with test file paths, module imports, and test configuration.
|
||||
|
||||
**Problem Examples:**
|
||||
```bash
|
||||
# Git Bash converts these automatically:
|
||||
/foo → C:/Program Files/Git/usr/foo
|
||||
/foo:/bar → C:\msys64\foo;C:\msys64\bar
|
||||
--dir=/foo → --dir=C:/msys64/foo
|
||||
```
|
||||
|
||||
### Solution 1: Disable Path Conversion
|
||||
|
||||
For test commands where path conversion causes issues:
|
||||
|
||||
```bash
|
||||
# Disable all path conversion for a single command
|
||||
MSYS_NO_PATHCONV=1 vitest run
|
||||
|
||||
# Disable for specific patterns
|
||||
export MSYS2_ARG_CONV_EXCL="--coverage.reporter"
|
||||
vitest run --coverage.reporter=html
|
||||
|
||||
# Disable for entire test session
|
||||
export MSYS_NO_PATHCONV=1
|
||||
npm test
|
||||
```
|
||||
|
||||
### Solution 2: Use Native Windows Paths in Configuration
|
||||
|
||||
When specifying test file paths in configuration, use Windows-style paths:
|
||||
|
||||
```javascript
|
||||
// vitest.config.js - Windows-compatible
|
||||
export default defineConfig({
|
||||
test: {
|
||||
include: [
|
||||
'tests/unit/**/*.test.js', // Relative paths work best
|
||||
'tests/integration/**/*.test.js'
|
||||
],
|
||||
// Avoid absolute paths starting with /c/ or C:
|
||||
setupFiles: ['./tests/setup.js'], // Use relative paths
|
||||
coverage: {
|
||||
reportsDirectory: './coverage' // Relative, not absolute
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Solution 3: Path Conversion Helper for Test Utilities
|
||||
|
||||
Create a helper for converting paths in test utilities:
|
||||
|
||||
```javascript
|
||||
// tests/helpers/paths.js
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
/**
|
||||
* Convert Windows path to Unix path for Git Bash compatibility
|
||||
*/
|
||||
export function toUnixPath(windowsPath) {
|
||||
if (!needsPathConversion()) return windowsPath;
|
||||
|
||||
try {
|
||||
// Use cygpath if available
|
||||
return execSync(`cygpath -u "${windowsPath}"`, {
|
||||
encoding: 'utf8'
|
||||
}).trim();
|
||||
} catch {
|
||||
// Fallback: manual conversion
|
||||
// C:\Users\foo → /c/Users/foo
|
||||
return windowsPath
|
||||
.replace(/\\/g, '/')
|
||||
.replace(/^([A-Z]):/, (_, drive) => `/${drive.toLowerCase()}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Unix path to Windows path
|
||||
*/
|
||||
export function toWindowsPath(unixPath) {
|
||||
if (!needsPathConversion()) return unixPath;
|
||||
|
||||
try {
|
||||
return execSync(`cygpath -w "${unixPath}"`, {
|
||||
encoding: 'utf8'
|
||||
}).trim();
|
||||
} catch {
|
||||
// Fallback: manual conversion
|
||||
// /c/Users/foo → C:\Users\foo
|
||||
return unixPath
|
||||
.replace(/^\/([a-z])\//, (_, drive) => `${drive.toUpperCase()}:\\`)
|
||||
.replace(/\//g, '\\');
|
||||
}
|
||||
}
|
||||
|
||||
function needsPathConversion() {
|
||||
return !!(process.env.MSYSTEM ||
|
||||
(process.platform === 'win32' && process.env.TERM === 'cygwin'));
|
||||
}
|
||||
```
|
||||
|
||||
**Usage in Tests:**
|
||||
```javascript
|
||||
import { toUnixPath, toWindowsPath } from '../helpers/paths.js';
|
||||
|
||||
test('loads config file', () => {
|
||||
const configPath = toWindowsPath('/c/project/config.json');
|
||||
const config = loadConfig(configPath);
|
||||
expect(config).toBeDefined();
|
||||
});
|
||||
```
|
||||
|
||||
## Test Execution Best Practices for Windows/Git Bash
|
||||
|
||||
### 1. NPM Scripts for Cross-Platform Compatibility
|
||||
|
||||
Define test scripts in package.json that work across all environments:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:unit": "vitest run tests/unit",
|
||||
"test:integration": "vitest run tests/integration",
|
||||
"test:watch": "vitest watch",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:headed": "playwright test --headed",
|
||||
"test:debug": "vitest run --reporter=verbose"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Always use npm scripts rather than direct vitest/playwright commands** - this ensures consistent behavior across shells.
|
||||
|
||||
### 2. Relative Path Imports
|
||||
|
||||
Use relative paths in test files to avoid path conversion issues:
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Relative paths work everywhere
|
||||
import { myFunction } from '../../src/utils.js';
|
||||
import { server } from '../mocks/server.js';
|
||||
|
||||
// ❌ Bad - Absolute paths can cause issues in Git Bash
|
||||
import { myFunction } from '/c/project/src/utils.js';
|
||||
```
|
||||
|
||||
### 3. Test File Discovery
|
||||
|
||||
Vitest and Playwright handle file patterns differently in Git Bash:
|
||||
|
||||
```javascript
|
||||
// vitest.config.js - Use glob patterns, not absolute paths
|
||||
export default defineConfig({
|
||||
test: {
|
||||
// ✅ Good - Glob patterns work cross-platform
|
||||
include: ['tests/**/*.test.js', 'src/**/*.test.js'],
|
||||
|
||||
// ❌ Bad - Absolute paths problematic in Git Bash
|
||||
include: ['/c/project/tests/**/*.test.js']
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// playwright.config.js - Relative directory paths
|
||||
export default defineConfig({
|
||||
// ✅ Good
|
||||
testDir: './tests/e2e',
|
||||
|
||||
// ❌ Bad
|
||||
testDir: '/c/project/tests/e2e'
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Temporary File Handling
|
||||
|
||||
Git Bash uses Unix-style temp directories, which can cause issues:
|
||||
|
||||
```javascript
|
||||
// tests/setup.js - Cross-platform temp file handling
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
function getTempDir() {
|
||||
const tmpdir = os.tmpdir();
|
||||
|
||||
// In Git Bash, os.tmpdir() may return Windows path
|
||||
// Ensure it's usable by your test framework
|
||||
if (process.env.MSYSTEM && !tmpdir.startsWith('/')) {
|
||||
// Convert Windows temp path if needed
|
||||
return tmpdir.replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
return tmpdir;
|
||||
}
|
||||
|
||||
// Use in tests
|
||||
const testTempDir = path.join(getTempDir(), 'my-tests');
|
||||
```
|
||||
|
||||
## Playwright-Specific Windows/Git Bash Considerations
|
||||
|
||||
### 1. Browser Installation in Git Bash
|
||||
|
||||
```bash
|
||||
# Use npx to ensure correct path handling
|
||||
npx playwright install
|
||||
|
||||
# If issues occur, use Windows-native command prompt instead
|
||||
# Then run tests from Git Bash
|
||||
```
|
||||
|
||||
### 2. Headed Mode in MINGW
|
||||
|
||||
When running headed tests in Git Bash, ensure DISPLAY variables are not set:
|
||||
|
||||
```bash
|
||||
# Unset DISPLAY if set (can interfere with Windows GUI)
|
||||
unset DISPLAY
|
||||
|
||||
# Run headed tests
|
||||
npx playwright test --headed
|
||||
```
|
||||
|
||||
### 3. Screenshot and Video Paths
|
||||
|
||||
Use relative paths for artifacts:
|
||||
|
||||
```javascript
|
||||
// playwright.config.js
|
||||
export default defineConfig({
|
||||
use: {
|
||||
// ✅ Good - Relative paths
|
||||
screenshot: 'only-on-failure',
|
||||
video: 'retain-on-failure',
|
||||
},
|
||||
// Output directory with relative path
|
||||
outputDir: './test-results',
|
||||
});
|
||||
```
|
||||
|
||||
## MSW (Mock Service Worker) in Git Bash
|
||||
|
||||
MSW generally works without issues in Git Bash, but be aware of:
|
||||
|
||||
### 1. Handler File Imports
|
||||
|
||||
Use relative imports in MSW setup:
|
||||
|
||||
```javascript
|
||||
// tests/mocks/server.js
|
||||
// ✅ Good
|
||||
import { handlers } from './handlers.js';
|
||||
|
||||
// ❌ Bad - Avoid absolute paths
|
||||
import { handlers } from '/c/project/tests/mocks/handlers.js';
|
||||
```
|
||||
|
||||
### 2. Fetch Polyfill (Node.js)
|
||||
|
||||
Ensure Node.js version 18+ for native Fetch API support:
|
||||
|
||||
```bash
|
||||
# Check Node version
|
||||
node --version # Should be 18+
|
||||
|
||||
# If using older Node, MSW 2.x won't work properly
|
||||
```
|
||||
|
||||
## Common Windows/Git Bash Test Errors and Fixes
|
||||
|
||||
### Error 1: "No such file or directory" in Git Bash
|
||||
|
||||
**Symptom:**
|
||||
```
|
||||
Error: /usr/bin/bash: line 1: C:UsersUsername...No such file
|
||||
```
|
||||
|
||||
**Cause:** Path conversion issue, often with temp directories.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Option 1: Disable path conversion
|
||||
MSYS_NO_PATHCONV=1 npm test
|
||||
|
||||
# Option 2: Use Claude Code's Git Bash path variable
|
||||
export CLAUDE_CODE_GIT_BASH_PATH="C:\\Program Files\\git\\bin\\bash.exe"
|
||||
|
||||
# Option 3: Run via npm scripts (recommended)
|
||||
npm test # npm handles path issues automatically
|
||||
```
|
||||
|
||||
### Error 2: Module Import Failures
|
||||
|
||||
**Symptom:**
|
||||
```
|
||||
Error: Cannot find module '../src/utils'
|
||||
```
|
||||
|
||||
**Cause:** Path separator confusion (backslash vs forward slash).
|
||||
|
||||
**Fix:**
|
||||
```javascript
|
||||
// Use path.join() or path.resolve() for cross-platform paths
|
||||
import path from 'path';
|
||||
|
||||
const utilsPath = path.resolve(__dirname, '../src/utils.js');
|
||||
const utils = await import(utilsPath);
|
||||
```
|
||||
|
||||
### Error 3: Playwright Browser Launch Failure
|
||||
|
||||
**Symptom:**
|
||||
```
|
||||
Error: Failed to launch browser
|
||||
```
|
||||
|
||||
**Cause:** Git Bash environment variables interfering with browser launch.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Clear problematic environment variables
|
||||
unset DISPLAY
|
||||
unset BROWSER
|
||||
|
||||
# Run Playwright tests
|
||||
npx playwright test
|
||||
```
|
||||
|
||||
### Error 4: Coverage Report Path Issues
|
||||
|
||||
**Symptom:**
|
||||
```
|
||||
Error: Failed to write coverage to /c/project/coverage
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
```javascript
|
||||
// vitest.config.js - Use relative paths
|
||||
export default defineConfig({
|
||||
test: {
|
||||
coverage: {
|
||||
// ✅ Good
|
||||
reportsDirectory: './coverage',
|
||||
|
||||
// ❌ Bad
|
||||
reportsDirectory: '/c/project/coverage'
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Testing Strategy for Multi-Platform Support
|
||||
|
||||
### 1. CI/CD Configuration
|
||||
|
||||
Test on multiple platforms in CI/CD:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/test.yml
|
||||
name: Tests
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node: [18, 20, 22]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
- run: npm run test:e2e
|
||||
if: matrix.os == 'ubuntu-latest' # Run E2E on Linux only
|
||||
```
|
||||
|
||||
### 2. Shell-Specific Test Setup
|
||||
|
||||
Create shell-specific setup if needed:
|
||||
|
||||
```javascript
|
||||
// tests/setup.js
|
||||
import { detectShell } from './helpers/shell-detect.js';
|
||||
|
||||
const shell = detectShell();
|
||||
|
||||
// Apply shell-specific configuration
|
||||
if (shell.type === 'mingw') {
|
||||
console.log('Running in Git Bash/MINGW environment');
|
||||
// Apply MINGW-specific test setup
|
||||
process.env.FORCE_COLOR = '1'; // Enable colors in Git Bash
|
||||
}
|
||||
|
||||
// Standard setup continues...
|
||||
```
|
||||
|
||||
### 3. Path-Safe Test Utilities
|
||||
|
||||
Create test utilities that work across all platforms:
|
||||
|
||||
```javascript
|
||||
// tests/helpers/test-utils.js
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname } from 'path';
|
||||
|
||||
// Get __dirname equivalent in ESM
|
||||
export function getCurrentDir(importMetaUrl) {
|
||||
return dirname(fileURLToPath(importMetaUrl));
|
||||
}
|
||||
|
||||
// Cross-platform path joining
|
||||
export function testPath(...segments) {
|
||||
return path.join(...segments).replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
// Usage in test file:
|
||||
// const __dirname = getCurrentDir(import.meta.url);
|
||||
// const fixturePath = testPath(__dirname, 'fixtures', 'data.json');
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Shell Detection Commands
|
||||
|
||||
```bash
|
||||
# Check if running in Git Bash
|
||||
echo $MSYSTEM # MINGW64, MINGW32, or empty
|
||||
|
||||
# Check OS type
|
||||
uname -s # MINGW64_NT-* for Git Bash
|
||||
|
||||
# Check platform in Node
|
||||
node -p process.platform # win32 on Windows
|
||||
```
|
||||
|
||||
### Path Conversion Quick Fixes
|
||||
|
||||
```bash
|
||||
# Disable for single command
|
||||
MSYS_NO_PATHCONV=1 vitest run
|
||||
|
||||
# Disable for session
|
||||
export MSYS_NO_PATHCONV=1
|
||||
|
||||
# Convert path manually
|
||||
cygpath -u "C:\path" # Windows → Unix
|
||||
cygpath -w "/c/path" # Unix → Windows
|
||||
```
|
||||
|
||||
### Recommended Test Execution (Git Bash on Windows)
|
||||
|
||||
```bash
|
||||
# ✅ Best - Use npm scripts
|
||||
npm test
|
||||
npm run test:e2e
|
||||
|
||||
# ✅ Good - With path conversion disabled
|
||||
MSYS_NO_PATHCONV=1 vitest run
|
||||
|
||||
# ⚠️ Caution - Direct vitest command may have issues
|
||||
vitest run # May encounter path conversion issues
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [Git Bash Path Conversion](https://www.msys2.org/docs/filesystem-paths/)
|
||||
- [Vitest Configuration](https://vitest.dev/config/)
|
||||
- [Playwright on Windows](https://playwright.dev/docs/browsers#install-system-requirements)
|
||||
- [MSW Node.js Integration](https://mswjs.io/docs/integrations/node)
|
||||
|
||||
## Summary
|
||||
|
||||
When running tests on Windows with Git Bash:
|
||||
|
||||
1. **Use npm scripts** for all test execution (most reliable)
|
||||
2. **Use relative paths** in configuration and imports
|
||||
3. **Detect shell environment** when needed for conditional setup
|
||||
4. **Disable path conversion** (MSYS_NO_PATHCONV=1) if issues occur
|
||||
5. **Test on multiple platforms** in CI/CD to catch platform-specific issues
|
||||
6. **Avoid absolute paths** starting with /c/ or C:\ in test files
|
||||
7. **Use path.join()** for programmatic path construction
|
||||
|
||||
Following these practices ensures tests run reliably across Windows Command Prompt, PowerShell, Git Bash, and Unix-like environments.
|
||||
Reference in New Issue
Block a user