File size: 5,047 Bytes
07af8f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Test for CLI path handling functionality
import path from 'path';
import { pathToFileURL } from 'url';

describe('CLI Path Handling', () => {
  describe('Cross-platform ESM URL conversion', () => {
    it('should convert Unix-style absolute path to file:// URL', () => {
      const unixPath = '/home/user/project/dist/index.js';
      const fileUrl = pathToFileURL(unixPath).href;
      
      expect(fileUrl).toMatch(/^file:\/\//);
      expect(fileUrl).toContain('index.js');
    });

    it('should handle relative paths correctly', () => {
      const relativePath = path.join(process.cwd(), 'dist', 'index.js');
      const fileUrl = pathToFileURL(relativePath).href;
      
      expect(fileUrl).toMatch(/^file:\/\//);
      expect(fileUrl).toContain('dist');
      expect(fileUrl).toContain('index.js');
    });

    it('should produce valid URL format', () => {
      const testPath = path.join(process.cwd(), 'test', 'file.js');
      const fileUrl = pathToFileURL(testPath).href;
      
      // Should be a valid URL
      expect(() => new URL(fileUrl)).not.toThrow();
      
      // Should start with file://
      expect(fileUrl.startsWith('file://')).toBe(true);
    });

    it('should handle paths with spaces', () => {
      const pathWithSpaces = path.join(process.cwd(), 'my folder', 'dist', 'index.js');
      const fileUrl = pathToFileURL(pathWithSpaces).href;
      
      expect(fileUrl).toMatch(/^file:\/\//);
      expect(fileUrl).toContain('index.js');
      // Spaces should be URL-encoded
      expect(fileUrl).toContain('%20');
    });

    it('should handle paths with special characters', () => {
      const pathWithSpecialChars = path.join(process.cwd(), 'test@dir', 'file#1.js');
      const fileUrl = pathToFileURL(pathWithSpecialChars).href;
      
      expect(fileUrl).toMatch(/^file:\/\//);
      // Special characters should be URL-encoded
      expect(() => new URL(fileUrl)).not.toThrow();
    });

    // Windows-specific path handling simulation
    it('should handle Windows-style paths correctly', () => {
      // Simulate a Windows path structure
      // Note: On non-Windows systems, this creates a relative path,
      // but the test verifies the conversion mechanism works
      const mockWindowsPath = 'C:\\Users\\User\\project\\dist\\index.js';
      
      // On Windows, pathToFileURL would convert C:\ to file:///C:/
      // On Unix, it treats it as a relative path, but the conversion still works
      const fileUrl = pathToFileURL(mockWindowsPath).href;
      
      expect(fileUrl).toMatch(/^file:\/\//);
      expect(fileUrl).toContain('index.js');
    });
  });

  describe('Path normalization', () => {
    it('should normalize path separators', () => {
      const mixedPath = path.join('dist', 'index.js');
      const fileUrl = pathToFileURL(path.resolve(mixedPath)).href;
      
      expect(fileUrl).toMatch(/^file:\/\//);
      // All separators should be forward slashes in URL
      expect(fileUrl.split('file://')[1]).not.toContain('\\');
    });

    it('should handle multiple consecutive slashes', () => {
      const messyPath = path.normalize('/dist//index.js');
      const fileUrl = pathToFileURL(path.resolve(messyPath)).href;
      
      expect(fileUrl).toMatch(/^file:\/\//);
      expect(() => new URL(fileUrl)).not.toThrow();
    });
  });

  describe('Path resolution for CLI use case', () => {
    it('should convert package root path to valid import URL', () => {
      const packageRoot = process.cwd();
      const entryPath = path.join(packageRoot, 'dist', 'index.js');
      const entryUrl = pathToFileURL(entryPath).href;
      
      expect(entryUrl).toMatch(/^file:\/\//);
      expect(entryUrl).toContain('dist');
      expect(entryUrl).toContain('index.js');
      expect(() => new URL(entryUrl)).not.toThrow();
    });

    it('should handle nested directory structures', () => {
      const deepPath = path.join(process.cwd(), 'a', 'b', 'c', 'd', 'file.js');
      const fileUrl = pathToFileURL(deepPath).href;
      
      expect(fileUrl).toMatch(/^file:\/\//);
      expect(fileUrl).toContain('file.js');
      expect(() => new URL(fileUrl)).not.toThrow();
    });

    it('should produce URL compatible with dynamic import()', () => {
      // This test verifies the exact pattern used in bin/cli.js
      const projectRoot = process.cwd();
      const entryPath = path.join(projectRoot, 'dist', 'index.js');
      const entryUrl = pathToFileURL(entryPath).href;
      
      // The URL should be valid for import()
      expect(entryUrl).toMatch(/^file:\/\//);
      expect(typeof entryUrl).toBe('string');
      
      // Verify the URL format is valid
      const urlObj = new URL(entryUrl);
      expect(urlObj.protocol).toBe('file:');
      expect(urlObj.href).toBe(entryUrl);
      
      // On Windows, pathToFileURL converts 'C:\path' to 'file:///C:/path'
      // On Unix, it converts '/path' to 'file:///path'
      // Both formats are valid for dynamic import()
      expect(entryUrl).toContain('index.js');
    });
  });
});