@holoscript/std 7.0.0 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/README.md +8 -0
  2. package/dist/chunk-DGUM43GV.js +11 -0
  3. package/dist/{chunk-PFX2JM4X.js → chunk-FAMOLKH3.js} +2 -1
  4. package/dist/{chunk-PFX2JM4X.js.map → chunk-FAMOLKH3.js.map} +1 -1
  5. package/dist/{chunk-DZHAVOCH.js → chunk-SOKH6FJ7.js} +31 -6
  6. package/dist/chunk-SOKH6FJ7.js.map +1 -0
  7. package/dist/collections.cjs +1 -0
  8. package/dist/collections.cjs.map +1 -1
  9. package/dist/collections.js +2 -2
  10. package/dist/fs/fs.d.ts.map +1 -1
  11. package/dist/fs/index.cjs +221 -8510
  12. package/dist/fs/index.cjs.map +1 -1
  13. package/dist/fs/index.js +832 -118
  14. package/dist/fs/index.js.map +1 -1
  15. package/dist/fs/sandbox.d.ts +49 -0
  16. package/dist/fs/sandbox.d.ts.map +1 -0
  17. package/dist/index.cjs +3494 -12672
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +0 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +17 -7
  22. package/dist/index.js.map +1 -1
  23. package/dist/math.cjs +18 -3
  24. package/dist/math.cjs.map +1 -1
  25. package/dist/math.js +2 -2
  26. package/dist/string.js +1 -1
  27. package/dist/time.js +1 -1
  28. package/dist/traits/EconomicPrimitives.js +1 -1
  29. package/dist/traits/EconomicTraits.js +1 -1
  30. package/dist/types.d.ts.map +1 -1
  31. package/package.json +19 -9
  32. package/dist/__tests__/EconomicPrimitives.test.d.ts +0 -2
  33. package/dist/__tests__/EconomicPrimitives.test.d.ts.map +0 -1
  34. package/dist/__tests__/EconomicTraits.test.d.ts +0 -2
  35. package/dist/__tests__/EconomicTraits.test.d.ts.map +0 -1
  36. package/dist/__tests__/SimulationLabPrimitives.test.d.ts +0 -2
  37. package/dist/__tests__/SimulationLabPrimitives.test.d.ts.map +0 -1
  38. package/dist/__tests__/collections.test.d.ts +0 -2
  39. package/dist/__tests__/collections.test.d.ts.map +0 -1
  40. package/dist/__tests__/events.test.d.ts +0 -2
  41. package/dist/__tests__/events.test.d.ts.map +0 -1
  42. package/dist/__tests__/index.test.d.ts +0 -2
  43. package/dist/__tests__/index.test.d.ts.map +0 -1
  44. package/dist/__tests__/materials.test.d.ts +0 -2
  45. package/dist/__tests__/materials.test.d.ts.map +0 -1
  46. package/dist/__tests__/math.test.d.ts +0 -2
  47. package/dist/__tests__/math.test.d.ts.map +0 -1
  48. package/dist/__tests__/physics.test.d.ts +0 -2
  49. package/dist/__tests__/physics.test.d.ts.map +0 -1
  50. package/dist/__tests__/spatial.test.d.ts +0 -2
  51. package/dist/__tests__/spatial.test.d.ts.map +0 -1
  52. package/dist/__tests__/standard-library-fundamentals.test.d.ts +0 -2
  53. package/dist/__tests__/standard-library-fundamentals.test.d.ts.map +0 -1
  54. package/dist/__tests__/string-and-time-utilities.test.d.ts +0 -2
  55. package/dist/__tests__/string-and-time-utilities.test.d.ts.map +0 -1
  56. package/dist/__tests__/string-decoupled.test.d.ts +0 -2
  57. package/dist/__tests__/string-decoupled.test.d.ts.map +0 -1
  58. package/dist/__tests__/string.test.d.ts +0 -2
  59. package/dist/__tests__/string.test.d.ts.map +0 -1
  60. package/dist/__tests__/time.test.d.ts +0 -2
  61. package/dist/__tests__/time.test.d.ts.map +0 -1
  62. package/dist/chunk-DZHAVOCH.js.map +0 -1
  63. package/dist/chunk-PR4QN5HX.js +0 -43
  64. package/dist/chunk-XBA4ARST.js +0 -9313
  65. package/dist/chunk-XBA4ARST.js.map +0 -1
  66. package/dist/fs/__tests__/file-watch-system.test.d.ts +0 -2
  67. package/dist/fs/__tests__/file-watch-system.test.d.ts.map +0 -1
  68. package/dist/fs/__tests__/path-utilities.test.d.ts +0 -2
  69. package/dist/fs/__tests__/path-utilities.test.d.ts.map +0 -1
  70. package/dist/fs/__tests__/path.test.d.ts +0 -2
  71. package/dist/fs/__tests__/path.test.d.ts.map +0 -1
  72. package/dist/string.basic.test.d.ts +0 -5
  73. package/dist/string.basic.test.d.ts.map +0 -1
  74. package/dist/string.test.d.ts +0 -5
  75. package/dist/string.test.d.ts.map +0 -1
  76. package/dist/traits/__tests__/ARTraits.test.d.ts +0 -2
  77. package/dist/traits/__tests__/ARTraits.test.d.ts.map +0 -1
  78. package/dist/traits/__tests__/EconomicPrimitives.test.d.ts +0 -2
  79. package/dist/traits/__tests__/EconomicPrimitives.test.d.ts.map +0 -1
  80. package/dist/traits/__tests__/EconomicTraits.test.d.ts +0 -2
  81. package/dist/traits/__tests__/EconomicTraits.test.d.ts.map +0 -1
  82. package/error-utf8.log +0 -6
  83. package/error.log +0 -0
  84. package/src/__tests__/EconomicPrimitives.test.ts +0 -690
  85. package/src/__tests__/EconomicTraits.test.ts +0 -425
  86. package/src/__tests__/SimulationLabPrimitives.test.ts +0 -415
  87. package/src/__tests__/collections.test.ts +0 -182
  88. package/src/__tests__/events.test.ts +0 -135
  89. package/src/__tests__/index.test.ts +0 -14
  90. package/src/__tests__/materials.test.ts +0 -84
  91. package/src/__tests__/math.test.ts +0 -246
  92. package/src/__tests__/physics.test.ts +0 -83
  93. package/src/__tests__/spatial.test.ts +0 -333
  94. package/src/__tests__/standard-library-fundamentals.test.ts +0 -1318
  95. package/src/__tests__/string-and-time-utilities.test.ts +0 -1070
  96. package/src/__tests__/string-decoupled.test.ts +0 -13
  97. package/src/__tests__/string.test.ts +0 -164
  98. package/src/__tests__/time.test.ts +0 -110
  99. package/src/collections.ts +0 -850
  100. package/src/events.ts +0 -88
  101. package/src/fs/__tests__/file-watch-system.test.ts +0 -675
  102. package/src/fs/__tests__/path-utilities.test.ts +0 -375
  103. package/src/fs/__tests__/path.test.ts +0 -287
  104. package/src/fs/fs.ts +0 -692
  105. package/src/fs/index.ts +0 -194
  106. package/src/fs/path.ts +0 -310
  107. package/src/fs/watch.ts +0 -413
  108. package/src/index.ts +0 -476
  109. package/src/materials.ts +0 -109
  110. package/src/math.ts +0 -674
  111. package/src/physics.ts +0 -141
  112. package/src/spatial.ts +0 -320
  113. package/src/string.basic.test.ts +0 -14
  114. package/src/string.test.ts +0 -335
  115. package/src/string.ts +0 -531
  116. package/src/time.ts +0 -621
  117. package/src/traits/ARTraits.ts +0 -103
  118. package/src/traits/EconomicPrimitives.ts +0 -755
  119. package/src/traits/EconomicTraits.ts +0 -552
  120. package/src/traits/IoTTraits.ts +0 -102
  121. package/src/traits/SimulationLabPrimitives.ts +0 -650
  122. package/src/traits/SimulationLabTraits.ts +0 -191
  123. package/src/traits/VRRTraits.ts +0 -326
  124. package/src/traits/__tests__/ARTraits.test.ts +0 -8
  125. package/src/traits/__tests__/EconomicPrimitives.test.ts +0 -14
  126. package/src/traits/__tests__/EconomicTraits.test.ts +0 -16
  127. package/src/types.ts +0 -418
  128. package/std_error.log +0 -5
  129. package/tsconfig.json +0 -18
  130. package/tsup.config.ts +0 -20
  131. package/vitest.config.ts +0 -10
  132. /package/dist/{chunk-PR4QN5HX.js.map → chunk-DGUM43GV.js.map} +0 -0
@@ -1,375 +0,0 @@
1
- /**
2
- * @holoscript/fs acceptance tests
3
- * Covers: sanitize(), matchesPattern(), expandHome(), PathBuilder,
4
- * formatSize(), and the uncovered path utilities
5
- * (relative, resolve, addSuffix, isChildOf, commonBase)
6
- */
7
- import { describe, it, expect } from 'vitest';
8
- import {
9
- sanitize,
10
- matchesPattern,
11
- expandHome,
12
- PathBuilder,
13
- path,
14
- relative,
15
- resolve,
16
- addSuffix,
17
- isChildOf,
18
- commonBase,
19
- } from '../path.js';
20
- import { formatSize } from '../fs.js';
21
-
22
- // ═══════════════════════════════════════════════
23
- // sanitize
24
- // ═══════════════════════════════════════════════
25
- describe('sanitize', () => {
26
- it('is a function', () => {
27
- expect(typeof sanitize).toBe('function');
28
- });
29
-
30
- it('returns the input unchanged when safe', () => {
31
- expect(sanitize('hello-world')).toBe('hello-world');
32
- });
33
-
34
- it('replaces forward slash', () => {
35
- expect(sanitize('foo/bar')).toBe('foo_bar');
36
- });
37
-
38
- it('replaces backslash', () => {
39
- expect(sanitize('foo\\bar')).toBe('foo_bar');
40
- });
41
-
42
- it('replaces colon', () => {
43
- expect(sanitize('C:file')).toBe('C_file');
44
- });
45
-
46
- it('replaces angle brackets', () => {
47
- expect(sanitize('a<b>c')).toBe('a_b_c');
48
- });
49
-
50
- it('replaces quotes and pipe', () => {
51
- expect(sanitize('file"name|pipe')).toBe('file_name_pipe');
52
- });
53
-
54
- it('replaces question mark and asterisk', () => {
55
- expect(sanitize('what?ever*.ts')).toBe('what_ever_.ts');
56
- });
57
-
58
- it('replaces leading dots', () => {
59
- expect(sanitize('...hidden')).toBe('_hidden');
60
- });
61
-
62
- it('replaces trailing dots', () => {
63
- expect(sanitize('file...')).toBe('file_');
64
- });
65
-
66
- it('truncates to 255 characters', () => {
67
- const long = 'a'.repeat(300);
68
- expect(sanitize(long).length).toBe(255);
69
- });
70
-
71
- it('handles empty string', () => {
72
- expect(sanitize('')).toBe('');
73
- });
74
- });
75
-
76
- // ═══════════════════════════════════════════════
77
- // matchesPattern
78
- // ═══════════════════════════════════════════════
79
- describe('matchesPattern', () => {
80
- it('is a function', () => {
81
- expect(typeof matchesPattern).toBe('function');
82
- });
83
-
84
- it('matches exact filename', () => {
85
- expect(matchesPattern('file.ts', 'file.ts')).toBe(true);
86
- });
87
-
88
- it('* wildcard matches any characters', () => {
89
- expect(matchesPattern('file.ts', '*.ts')).toBe(true);
90
- });
91
-
92
- it('* wildcard does not match a different extension', () => {
93
- expect(matchesPattern('file.js', '*.ts')).toBe(false);
94
- });
95
-
96
- it('? matches single character', () => {
97
- expect(matchesPattern('file.ts', 'file.t?')).toBe(true);
98
- });
99
-
100
- it('? does not match zero characters', () => {
101
- expect(matchesPattern('file.t', 'file.t?')).toBe(false);
102
- });
103
-
104
- it('* matches empty prefix', () => {
105
- expect(matchesPattern('index.ts', '*.ts')).toBe(true);
106
- });
107
-
108
- it('returns false for complete mismatch', () => {
109
- expect(matchesPattern('image.png', '*.ts')).toBe(false);
110
- });
111
-
112
- it('matches *.test.ts pattern', () => {
113
- expect(matchesPattern('Sprint53.test.ts', '*.test.ts')).toBe(true);
114
- });
115
- });
116
-
117
- // ═══════════════════════════════════════════════
118
- // expandHome
119
- // ═══════════════════════════════════════════════
120
- describe('expandHome', () => {
121
- it('is a function', () => {
122
- expect(typeof expandHome).toBe('function');
123
- });
124
-
125
- it('returns non-tilde paths unchanged', () => {
126
- expect(expandHome('/absolute/path')).toBe('/absolute/path');
127
- expect(expandHome('relative/path')).toBe('relative/path');
128
- });
129
-
130
- it('expands ~ to the home directory', () => {
131
- const result = expandHome('~/docs');
132
- const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
133
- expect(result.includes('docs')).toBe(true);
134
- if (home) {
135
- expect(result.startsWith(home)).toBe(true);
136
- }
137
- });
138
-
139
- it('expands ~ alone', () => {
140
- const result = expandHome('~');
141
- const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
142
- if (home) {
143
- expect(result).toContain(home.replace(/\\/g, '/').split('/').pop()!);
144
- } else {
145
- expect(typeof result).toBe('string');
146
- }
147
- });
148
- });
149
-
150
- // ═══════════════════════════════════════════════
151
- // PathBuilder
152
- // ═══════════════════════════════════════════════
153
- describe('PathBuilder', () => {
154
- it('PathBuilder.from creates an instance', () => {
155
- const pb = PathBuilder.from('/home/user');
156
- expect(pb).toBeInstanceOf(PathBuilder);
157
- });
158
-
159
- it('PathBuilder.cwd creates an instance rooted at cwd', () => {
160
- const pb = PathBuilder.cwd();
161
- expect(pb).toBeInstanceOf(PathBuilder);
162
- expect(pb.toString()).toBe(resolve(process.cwd()));
163
- });
164
-
165
- it('join appends segments', () => {
166
- const pb = PathBuilder.from('/home/user').join('projects', 'holo');
167
- expect(pb.toString().replace(/\\/g, '/')).toContain('home/user/projects/holo');
168
- });
169
-
170
- it('parent navigates up', () => {
171
- const pb = PathBuilder.from('/home/user/file.ts').parent();
172
- expect(pb.toString().replace(/\\/g, '/')).toContain('/home/user');
173
- });
174
-
175
- it('sibling replaces last segment', () => {
176
- const pb = PathBuilder.from('/home/user/a.ts').sibling('b.ts');
177
- expect(pb.toString().replace(/\\/g, '/')).toContain('/home/user/b.ts');
178
- });
179
-
180
- it('withExtension changes extension', () => {
181
- const pb = PathBuilder.from('/path/to/file.ts').withExtension('.js');
182
- expect(pb.toString()).toMatch(/file\.js$/);
183
- });
184
-
185
- it('withSuffix adds suffix before extension', () => {
186
- const pb = PathBuilder.from('/path/to/file.ts').withSuffix('.test');
187
- expect(pb.toString()).toMatch(/file\.test\.ts$/);
188
- });
189
-
190
- it('normalize resolves dot segments', () => {
191
- const pb = PathBuilder.from('/path/to/../to/file.ts').normalize();
192
- expect(pb.toString().replace(/\\/g, '/')).toContain('/path/to/file.ts');
193
- });
194
-
195
- it('value getter returns the path string', () => {
196
- const pb = PathBuilder.from('/home/user');
197
- expect(pb.value).toBe(pb.toString());
198
- });
199
-
200
- it('dirname getter returns parent directory', () => {
201
- const pb = PathBuilder.from('/home/user/file.ts');
202
- expect(pb.dirname.replace(/\\/g, '/')).toContain('/home/user');
203
- });
204
-
205
- it('basename getter returns filename', () => {
206
- const pb = PathBuilder.from('/home/user/file.ts');
207
- expect(pb.basename).toBe('file.ts');
208
- });
209
-
210
- it('extname getter returns extension', () => {
211
- const pb = PathBuilder.from('/home/user/file.ts');
212
- expect(pb.extname).toBe('.ts');
213
- });
214
-
215
- it('name getter returns stem without extension', () => {
216
- const pb = PathBuilder.from('/home/user/file.ts');
217
- expect(pb.name).toBe('file');
218
- });
219
-
220
- it('fluent API chains work together', () => {
221
- const result = PathBuilder.from('/root')
222
- .join('src')
223
- .join('index.ts')
224
- .withSuffix('.test')
225
- .toString();
226
- expect(result).toMatch(/index\.test\.ts$/);
227
- });
228
-
229
- it('path() convenience function returns PathBuilder', () => {
230
- const pb = path('/home/user');
231
- expect(pb).toBeInstanceOf(PathBuilder);
232
- });
233
- });
234
-
235
- // ═══════════════════════════════════════════════
236
- // relative
237
- // ═══════════════════════════════════════════════
238
- describe('relative', () => {
239
- it('is a function', () => {
240
- expect(typeof relative).toBe('function');
241
- });
242
-
243
- it('returns relative path between two absolute paths', () => {
244
- const rel = relative('/foo/bar', '/foo/bar/baz/file.ts');
245
- expect(rel.replace(/\\/g, '/')).toBe('baz/file.ts');
246
- });
247
-
248
- it('returns .. for parent navigation', () => {
249
- const rel = relative('/foo/bar/baz', '/foo/bar');
250
- expect(rel).toBe('..');
251
- });
252
-
253
- it('returns empty string for same path', () => {
254
- const rel = relative('/foo/bar', '/foo/bar');
255
- expect(rel).toBe('');
256
- });
257
- });
258
-
259
- // ═══════════════════════════════════════════════
260
- // addSuffix
261
- // ═══════════════════════════════════════════════
262
- describe('addSuffix', () => {
263
- it('is a function', () => {
264
- expect(typeof addSuffix).toBe('function');
265
- });
266
-
267
- it('adds suffix before extension', () => {
268
- expect(addSuffix('component.tsx', '.test')).toBe('component.test.tsx');
269
- });
270
-
271
- it('works with full paths', () => {
272
- const result = addSuffix('/src/app.ts', '.spec');
273
- expect(result.replace(/\\/g, '/')).toMatch(/\/src\/app\.spec\.ts$/);
274
- });
275
-
276
- it('works with multiple dots in name', () => {
277
- const result = addSuffix('file.min.js', '.bundle');
278
- expect(result).toMatch(/file\.min\.bundle\.js$/);
279
- });
280
- });
281
-
282
- // ═══════════════════════════════════════════════
283
- // isChildOf
284
- // ═══════════════════════════════════════════════
285
- describe('isChildOf', () => {
286
- it('is a function', () => {
287
- expect(typeof isChildOf).toBe('function');
288
- });
289
-
290
- it('returns true for a child path', () => {
291
- expect(isChildOf('/foo/bar/baz', '/foo/bar')).toBe(true);
292
- });
293
-
294
- it('returns true for direct child', () => {
295
- expect(isChildOf('/foo/bar', '/foo')).toBe(true);
296
- });
297
-
298
- it('returns false for unrelated path', () => {
299
- expect(isChildOf('/other/path', '/foo')).toBe(false);
300
- });
301
-
302
- it('returns true for same path', () => {
303
- expect(isChildOf('/foo/bar', '/foo/bar')).toBe(true);
304
- });
305
-
306
- it('returns false for parent of parent', () => {
307
- expect(isChildOf('/foo', '/foo/bar')).toBe(false);
308
- });
309
- });
310
-
311
- // ═══════════════════════════════════════════════
312
- // commonBase
313
- // ═══════════════════════════════════════════════
314
- describe('commonBase', () => {
315
- it('is a function', () => {
316
- expect(typeof commonBase).toBe('function');
317
- });
318
-
319
- it('returns empty string for zero paths', () => {
320
- expect(commonBase()).toBe('');
321
- });
322
-
323
- it('returns dirname of single path', () => {
324
- const result = commonBase('/foo/bar/file.ts');
325
- expect(result.replace(/\\/g, '/')).toContain('foo/bar');
326
- });
327
-
328
- it('finds common directory for siblings', () => {
329
- const result = commonBase('/foo/bar/a.ts', '/foo/bar/b.ts');
330
- expect(result.replace(/\\/g, '/')).toContain('foo/bar');
331
- });
332
- });
333
-
334
- // ═══════════════════════════════════════════════
335
- // formatSize (from fs.ts)
336
- // ═══════════════════════════════════════════════
337
- describe('formatSize', () => {
338
- it('is a function', () => {
339
- expect(typeof formatSize).toBe('function');
340
- });
341
-
342
- it('returns "0 B" for 0 bytes', () => {
343
- expect(formatSize(0)).toBe('0 B');
344
- });
345
-
346
- it('formats bytes', () => {
347
- expect(formatSize(512)).toContain('B');
348
- });
349
-
350
- it('formats kilobytes', () => {
351
- expect(formatSize(1024)).toContain('KB');
352
- });
353
-
354
- it('formats megabytes', () => {
355
- expect(formatSize(1024 * 1024)).toContain('MB');
356
- });
357
-
358
- it('formats gigabytes', () => {
359
- expect(formatSize(1024 * 1024 * 1024)).toContain('GB');
360
- });
361
-
362
- it('respects decimal places', () => {
363
- const result = formatSize(1536, 1); // 1.5 KB
364
- expect(result).toBe('1.5 KB');
365
- });
366
-
367
- it('default decimals is 2', () => {
368
- const result = formatSize(1536); // 1.50 KB
369
- expect(result).toBe('1.5 KB');
370
- });
371
-
372
- it('1 KB formats correctly', () => {
373
- expect(formatSize(1024, 0)).toBe('1 KB');
374
- });
375
- });
@@ -1,287 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- join,
4
- resolve,
5
- relative,
6
- normalize,
7
- isAbsolute,
8
- dirname,
9
- basename,
10
- extname,
11
- parse,
12
- format,
13
- toPosix,
14
- toWindows,
15
- parent,
16
- segments,
17
- hasExtension,
18
- changeExtension,
19
- removeExtension,
20
- addSuffix,
21
- isChildOf,
22
- commonBase,
23
- sep,
24
- } from '../path.js';
25
-
26
- describe('Path Utilities', () => {
27
- describe('join', () => {
28
- it('should join path segments', () => {
29
- const result = join('foo', 'bar', 'baz');
30
- expect(result).toMatch(/foo[/\\]bar[/\\]baz/);
31
- });
32
-
33
- it('should handle empty segments', () => {
34
- const result = join('foo', '', 'bar');
35
- expect(result).toMatch(/foo[/\\]bar/);
36
- });
37
-
38
- it('should normalize separators', () => {
39
- const result = join('foo/', '/bar');
40
- expect(result).toMatch(/foo[/\\]bar/);
41
- });
42
- });
43
-
44
- describe('dirname', () => {
45
- it('should get directory of a file path', () => {
46
- const result = dirname('/foo/bar/baz.txt');
47
- expect(result).toBe('/foo/bar');
48
- });
49
-
50
- it('should handle file in root', () => {
51
- const result = dirname('/file.txt');
52
- expect(result).toBe('/');
53
- });
54
- });
55
-
56
- describe('basename', () => {
57
- it('should get file name from path', () => {
58
- expect(basename('/foo/bar/baz.txt')).toBe('baz.txt');
59
- });
60
-
61
- it('should strip extension when provided', () => {
62
- expect(basename('/foo/bar/baz.txt', '.txt')).toBe('baz');
63
- });
64
-
65
- it('should handle paths ending with separator', () => {
66
- expect(basename('/foo/bar/')).toBe('bar');
67
- });
68
- });
69
-
70
- describe('extname', () => {
71
- it('should get extension from file name', () => {
72
- expect(extname('file.txt')).toBe('.txt');
73
- });
74
-
75
- it('should get extension from full path', () => {
76
- expect(extname('/path/to/file.json')).toBe('.json');
77
- });
78
-
79
- it('should return empty string for no extension', () => {
80
- expect(extname('file')).toBe('');
81
- });
82
-
83
- it('should handle dotfiles', () => {
84
- expect(extname('.gitignore')).toBe('');
85
- });
86
-
87
- it('should handle multiple dots', () => {
88
- expect(extname('file.test.ts')).toBe('.ts');
89
- });
90
- });
91
-
92
- describe('parse', () => {
93
- it('should parse a complete path', () => {
94
- const result = parse('/home/user/file.txt');
95
- expect(result.root).toBe('/');
96
- expect(result.dir).toBe('/home/user');
97
- expect(result.base).toBe('file.txt');
98
- expect(result.ext).toBe('.txt');
99
- expect(result.name).toBe('file');
100
- });
101
-
102
- it('should parse file without extension', () => {
103
- const result = parse('/path/to/README');
104
- expect(result.ext).toBe('');
105
- expect(result.name).toBe('README');
106
- });
107
- });
108
-
109
- describe('format', () => {
110
- it('should format parsed path back to string', () => {
111
- const parsed = { dir: '/home/user', name: 'file', ext: '.txt' };
112
- const result = format(parsed);
113
- expect(result).toMatch(/[/\\]home[/\\]user[/\\]file\.txt/);
114
- });
115
- });
116
-
117
- describe('isAbsolute', () => {
118
- it('should return true for absolute Unix paths', () => {
119
- expect(isAbsolute('/foo/bar')).toBe(true);
120
- });
121
-
122
- it('should return false for relative paths', () => {
123
- expect(isAbsolute('foo/bar')).toBe(false);
124
- expect(isAbsolute('./foo')).toBe(false);
125
- expect(isAbsolute('../foo')).toBe(false);
126
- });
127
- });
128
-
129
- describe('normalize', () => {
130
- it('should resolve . segments', () => {
131
- const result = normalize('/foo/./bar');
132
- // normalize uses native path module, so separator depends on OS
133
- expect(result.replace(/\\/g, '/')).toBe('/foo/bar');
134
- });
135
-
136
- it('should resolve .. segments', () => {
137
- const result = normalize('/foo/bar/../baz');
138
- expect(result.replace(/\\/g, '/')).toBe('/foo/baz');
139
- });
140
-
141
- it('should normalize multiple separators', () => {
142
- const result = normalize('/foo//bar///baz');
143
- expect(result.replace(/\\/g, '/')).toBe('/foo/bar/baz');
144
- });
145
- });
146
-
147
- describe('toPosix', () => {
148
- it('should convert backslashes to forward slashes', () => {
149
- expect(toPosix('foo\\bar\\baz')).toBe('foo/bar/baz');
150
- });
151
-
152
- it('should keep forward slashes unchanged', () => {
153
- expect(toPosix('foo/bar/baz')).toBe('foo/bar/baz');
154
- });
155
-
156
- it('should handle mixed separators', () => {
157
- expect(toPosix('foo\\bar/baz')).toBe('foo/bar/baz');
158
- });
159
- });
160
-
161
- describe('toWindows', () => {
162
- it('should convert forward slashes to backslashes', () => {
163
- expect(toWindows('foo/bar/baz')).toBe('foo\\bar\\baz');
164
- });
165
-
166
- it('should keep backslashes unchanged', () => {
167
- expect(toWindows('foo\\bar\\baz')).toBe('foo\\bar\\baz');
168
- });
169
- });
170
-
171
- describe('parent', () => {
172
- it('should return parent directory', () => {
173
- expect(parent('/foo/bar/baz')).toBe('/foo/bar');
174
- });
175
-
176
- it('should be alias for dirname', () => {
177
- expect(parent('/foo/bar')).toBe(dirname('/foo/bar'));
178
- });
179
- });
180
-
181
- describe('segments', () => {
182
- it('should split path into segments', () => {
183
- const result = segments('/foo/bar/baz');
184
- expect(result).toEqual(['foo', 'bar', 'baz']);
185
- });
186
-
187
- it('should filter empty segments', () => {
188
- const result = segments('/foo//bar/');
189
- expect(result).toEqual(['foo', 'bar']);
190
- });
191
- });
192
-
193
- describe('hasExtension', () => {
194
- it('should return true for matching extension', () => {
195
- expect(hasExtension('file.txt', '.txt')).toBe(true);
196
- expect(hasExtension('file.txt', 'txt')).toBe(true);
197
- });
198
-
199
- it('should return false for non-matching extension', () => {
200
- expect(hasExtension('file.txt', '.json')).toBe(false);
201
- });
202
-
203
- it('should be case-insensitive', () => {
204
- expect(hasExtension('file.TXT', '.txt')).toBe(true);
205
- expect(hasExtension('file.txt', '.TXT')).toBe(true);
206
- });
207
- });
208
-
209
- describe('changeExtension', () => {
210
- it('should change file extension', () => {
211
- const result = changeExtension('file.txt', '.md');
212
- expect(result).toBe('file.md');
213
- });
214
-
215
- it('should handle extension without dot', () => {
216
- const result = changeExtension('file.txt', 'json');
217
- expect(result).toBe('file.json');
218
- });
219
-
220
- it('should work with full paths', () => {
221
- const result = changeExtension('/path/to/file.ts', '.js');
222
- expect(result).toMatch(/[/\\]path[/\\]to[/\\]file\.js/);
223
- });
224
- });
225
-
226
- describe('removeExtension', () => {
227
- it('should remove extension from filename', () => {
228
- const result = removeExtension('file.txt');
229
- expect(result).toBe('file');
230
- });
231
-
232
- it('should work with paths', () => {
233
- const result = removeExtension('/path/to/file.ts');
234
- expect(result).toMatch(/[/\\]path[/\\]to[/\\]file$/);
235
- });
236
- });
237
-
238
- describe('addSuffix', () => {
239
- it('should add suffix before extension', () => {
240
- const result = addSuffix('file.ts', '.test');
241
- expect(result).toBe('file.test.ts');
242
- });
243
-
244
- it('should work with paths', () => {
245
- const result = addSuffix('/path/to/component.tsx', '.spec');
246
- expect(result).toMatch(/component\.spec\.tsx$/);
247
- });
248
- });
249
-
250
- describe('isChildOf', () => {
251
- it('should return true for child paths', () => {
252
- expect(isChildOf('/foo/bar/baz', '/foo')).toBe(true);
253
- expect(isChildOf('/foo/bar', '/foo')).toBe(true);
254
- });
255
-
256
- it('should return false for non-child paths', () => {
257
- expect(isChildOf('/other/path', '/foo')).toBe(false);
258
- });
259
-
260
- it('should return true for same path', () => {
261
- expect(isChildOf('/foo/bar', '/foo/bar')).toBe(true);
262
- });
263
- });
264
-
265
- describe('commonBase', () => {
266
- it('should find common base of multiple paths', () => {
267
- const result = commonBase('/foo/bar/a.txt', '/foo/bar/b.txt', '/foo/bar/c/d.txt');
268
- expect(result).toMatch(/foo[/\\]bar/);
269
- });
270
-
271
- it('should return empty for no common base', () => {
272
- // On Windows this might differ, so check if it's different roots
273
- const result = commonBase('/foo/bar', '/baz/qux');
274
- // Result depends on how deep they diverge
275
- expect(result).toBeDefined();
276
- });
277
-
278
- it('should handle single path', () => {
279
- const result = commonBase('/foo/bar/file.txt');
280
- expect(result).toMatch(/foo[/\\]bar/);
281
- });
282
-
283
- it('should handle empty array', () => {
284
- expect(commonBase()).toBe('');
285
- });
286
- });
287
- });