|
1 | 1 | // tools/treeshake-check/src/lib/analysis.test.ts |
2 | 2 | import { describe, it, expect } from '@effect/vitest'; |
3 | | -import { detectCauses, buildModuleAnalysis, analyzePackageJsonHints } from './analysis.js'; |
| 3 | +import { |
| 4 | + detectCauses, |
| 5 | + buildModuleAnalysis, |
| 6 | + analyzePackageJsonHints, |
| 7 | + resolveEntry, |
| 8 | +} from './analysis.js'; |
4 | 9 |
|
5 | 10 | // ─── detectCauses ───────────────────────────────────────────────────────────── |
6 | 11 |
|
@@ -210,3 +215,73 @@ describe('analyzePackageJsonHints', () => { |
210 | 215 | expect(hints.recommendations).toHaveLength(0); |
211 | 216 | }); |
212 | 217 | }); |
| 218 | + |
| 219 | +// ─── resolveEntry ───────────────────────────────────────────────────────────── |
| 220 | + |
| 221 | +describe('resolveEntry', () => { |
| 222 | + // exports field — subpath map with conditions |
| 223 | + it('reads import condition from exports["."]]', () => { |
| 224 | + expect( |
| 225 | + resolveEntry({ |
| 226 | + exports: { '.': { import: './dist/esm/index.js', require: './dist/cjs/index.js' } }, |
| 227 | + }), |
| 228 | + ).toBe('./dist/esm/index.js'); |
| 229 | + }); |
| 230 | + |
| 231 | + it('reads module condition from exports["."] when import is absent', () => { |
| 232 | + expect( |
| 233 | + resolveEntry({ |
| 234 | + exports: { '.': { module: './dist/esm/index.js', require: './dist/cjs/index.js' } }, |
| 235 | + }), |
| 236 | + ).toBe('./dist/esm/index.js'); |
| 237 | + }); |
| 238 | + |
| 239 | + it('reads default condition from exports["."] when no esm-specific condition', () => { |
| 240 | + expect(resolveEntry({ exports: { '.': { default: './dist/index.js' } } })).toBe( |
| 241 | + './dist/index.js', |
| 242 | + ); |
| 243 | + }); |
| 244 | + |
| 245 | + // exports field — flat conditions (no subpath key) |
| 246 | + it('reads import condition from flat exports object', () => { |
| 247 | + expect( |
| 248 | + resolveEntry({ exports: { import: './dist/esm/index.js', require: './dist/cjs/index.js' } }), |
| 249 | + ).toBe('./dist/esm/index.js'); |
| 250 | + }); |
| 251 | + |
| 252 | + // exports field — bare string shorthand |
| 253 | + it('reads bare string exports field', () => { |
| 254 | + expect(resolveEntry({ exports: './dist/index.js' })).toBe('./dist/index.js'); |
| 255 | + }); |
| 256 | + |
| 257 | + // exports field takes priority over module/main |
| 258 | + it('prefers exports over module and main', () => { |
| 259 | + expect( |
| 260 | + resolveEntry({ |
| 261 | + exports: { '.': { import: './esm/index.js' } }, |
| 262 | + module: './module/index.js', |
| 263 | + main: './main/index.js', |
| 264 | + }), |
| 265 | + ).toBe('./esm/index.js'); |
| 266 | + }); |
| 267 | + |
| 268 | + // fallback chain |
| 269 | + it('falls back to module when no exports field', () => { |
| 270 | + expect(resolveEntry({ module: './dist/index.js', main: './dist/cjs/index.js' })).toBe( |
| 271 | + './dist/index.js', |
| 272 | + ); |
| 273 | + }); |
| 274 | + |
| 275 | + it('falls back to main when no exports or module field', () => { |
| 276 | + expect(resolveEntry({ main: './dist/index.js' })).toBe('./dist/index.js'); |
| 277 | + }); |
| 278 | + |
| 279 | + it('returns undefined when no entry can be resolved', () => { |
| 280 | + expect(resolveEntry({ name: 'no-entry' })).toBeUndefined(); |
| 281 | + }); |
| 282 | + |
| 283 | + // CJS-only exports should be skipped (require-only map with no default) |
| 284 | + it('returns undefined for require-only exports map with no default', () => { |
| 285 | + expect(resolveEntry({ exports: { '.': { require: './dist/cjs/index.js' } } })).toBeUndefined(); |
| 286 | + }); |
| 287 | +}); |
0 commit comments