1import { spawnPromisified } from '../common/index.mjs';
2import * as fixtures from '../common/fixtures.mjs';
3import { match, strictEqual } from 'node:assert';
4import { execPath } from 'node:process';
5import { describe, it } from 'node:test';
6
7
8describe('ESM: specifier-resolution=node', { concurrency: true }, () => {
9  it(async () => {
10    const { code, stderr, stdout } = await spawnPromisified(execPath, [
11      '--no-warnings',
12      '--experimental-specifier-resolution=node',
13      '--input-type=module',
14      '--eval',
15      [
16        'import { strictEqual } from "node:assert";',
17        // CommonJS index.js
18        `import commonjs from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-commonjs'))};`,
19        // ESM index.js
20        `import module from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-module'))};`,
21        // Directory entry with main.js
22        `import main from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/dir-with-main'))};`,
23        // Notice the trailing slash
24        `import success, { explicit, implicit, implicitModule } from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/'))};`,
25        'strictEqual(commonjs, "commonjs");',
26        'strictEqual(module, "module");',
27        'strictEqual(main, "main");',
28        'strictEqual(success, "success");',
29        'strictEqual(explicit, "esm");',
30        'strictEqual(implicit, "cjs");',
31        'strictEqual(implicitModule, "cjs");',
32      ].join('\n'),
33    ]);
34
35    strictEqual(stderr, '');
36    strictEqual(stdout, '');
37    strictEqual(code, 0);
38  });
39  it('should work with --preserve-symlinks', async () => {
40    const { code, stderr, stdout } = await spawnPromisified(execPath, [
41      '--no-warnings',
42      '--experimental-specifier-resolution=node',
43      '--preserve-symlinks',
44      '--input-type=module',
45      '--eval',
46      [
47        'import { strictEqual } from "node:assert";',
48        // CommonJS index.js
49        `import commonjs from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-commonjs'))};`,
50        // ESM index.js
51        `import module from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-module'))};`,
52        // Directory entry with main.js
53        `import main from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/dir-with-main'))};`,
54        // Notice the trailing slash
55        `import success, { explicit, implicit, implicitModule } from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/'))};`,
56        'strictEqual(commonjs, "commonjs");',
57        'strictEqual(module, "module");',
58        'strictEqual(main, "main");',
59        'strictEqual(success, "success");',
60        'strictEqual(explicit, "esm");',
61        'strictEqual(implicit, "cjs");',
62        'strictEqual(implicitModule, "cjs");',
63      ].join('\n'),
64    ]);
65
66    strictEqual(stderr, '');
67    strictEqual(stdout, '');
68    strictEqual(code, 0);
69  });
70
71  it('should throw when the file doesn\'t exist', async () => {
72    const { code, stderr, stdout } = await spawnPromisified(execPath, [
73      '--no-warnings',
74      fixtures.path('es-module-specifiers/do-not-exist.js'),
75    ]);
76
77    match(stderr, /Cannot find module/);
78    strictEqual(stdout, '');
79    strictEqual(code, 1);
80  });
81
82  it('should throw when the omitted file extension is .mjs (legacy loader doesn\'t support it)', async () => {
83    const { code, stderr, stdout } = await spawnPromisified(execPath, [
84      '--no-warnings',
85      '--experimental-specifier-resolution=node',
86      '--input-type=module',
87      '--eval',
88      `import whatever from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/implicit-main-type-commonjs'))};`,
89    ]);
90
91    match(stderr, /ERR_MODULE_NOT_FOUND/);
92    strictEqual(stdout, '');
93    strictEqual(code, 1);
94  });
95
96  for (
97    const item of [
98      'package-type-commonjs',
99      'package-type-module',
100      '/',
101      '/index',
102    ]
103  ) it('should ', async () => {
104    const { code } = await spawnPromisified(execPath, [
105      '--no-warnings',
106      '--experimental-specifier-resolution=node',
107      '--es-module-specifier-resolution=node',
108      fixtures.path('es-module-specifiers', item),
109    ]);
110
111    strictEqual(code, 0);
112  });
113});
114