Skip to content

Commit 49dfa8f

Browse files
committed
Refactor tests
1 parent eef2bbf commit 49dfa8f

9 files changed

Lines changed: 335 additions & 403 deletions
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Test that package maps resolve direct, subpath, and transitive dependencies.
2+
import '../common/index.mjs';
3+
import { spawnSyncAndAssert } from '../common/child_process.js';
4+
import * as fixtures from '../common/fixtures.mjs';
5+
6+
const packageMapPath = fixtures.path('package-map/package-map.json');
7+
const cwd = fixtures.path('package-map/root');
8+
9+
// Resolves a direct dependency.
10+
spawnSyncAndAssert(process.execPath, [
11+
'--no-warnings',
12+
'--experimental-package-map', packageMapPath,
13+
'--input-type=module',
14+
'--eval', `import dep from 'dep-a'; console.log(dep);`,
15+
], { cwd }, { stdout: /dep-a-value/, trim: true });
16+
17+
// Resolves a subpath export.
18+
spawnSyncAndAssert(process.execPath, [
19+
'--no-warnings',
20+
'--experimental-package-map', packageMapPath,
21+
'--input-type=module',
22+
'--eval', `import util from 'dep-a/lib/util'; console.log(util);`,
23+
], { cwd }, { stdout: /dep-a-util/, trim: true });
24+
25+
// Resolves transitive dependency from allowed package.
26+
spawnSyncAndAssert(process.execPath, [
27+
'--no-warnings',
28+
'--experimental-package-map', packageMapPath,
29+
'--input-type=module',
30+
'--eval', `import depB from 'dep-b'; console.log(depB);`,
31+
], { cwd }, { stdout: /dep-b using dep-a-value/, trim: true });
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Test that package maps fall back for builtins and reject files outside mapped packages.
2+
import '../common/index.mjs';
3+
import { spawnSyncAndAssert, spawnSyncAndExit } from '../common/child_process.js';
4+
import * as fixtures from '../common/fixtures.mjs';
5+
import tmpdir from '../common/tmpdir.js';
6+
7+
tmpdir.refresh();
8+
9+
const packageMapPath = fixtures.path('package-map/package-map.json');
10+
const cwd = fixtures.path('package-map/root');
11+
12+
// Falls back for builtin modules.
13+
spawnSyncAndAssert(process.execPath, [
14+
'--no-warnings',
15+
'--experimental-package-map', packageMapPath,
16+
'--input-type=module',
17+
'--eval', `import fs from 'node:fs'; console.log(typeof fs.readFileSync);`,
18+
], { cwd }, { stdout: /function/, trim: true });
19+
20+
// Throws when parent not in map.
21+
spawnSyncAndExit(process.execPath, [
22+
'--no-warnings',
23+
'--experimental-package-map', packageMapPath,
24+
'--input-type=module',
25+
'--eval', `import dep from 'dep-a'; console.log(dep);`,
26+
], { cwd: tmpdir.path }, {
27+
status: 1,
28+
signal: null,
29+
stderr: /ERR_PACKAGE_MAP_EXTERNAL_FILE/,
30+
});
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Test package map error handling: invalid JSON, missing fields, bad URLs, duplicates.
2+
import '../common/index.mjs';
3+
import assert from 'node:assert';
4+
import { spawnSyncAndAssert, spawnSyncAndExit } from '../common/child_process.js';
5+
import * as fixtures from '../common/fixtures.mjs';
6+
import tmpdir from '../common/tmpdir.js';
7+
import { writeFileSync } from 'node:fs';
8+
import { pathToFileURL } from 'node:url';
9+
10+
tmpdir.refresh();
11+
12+
const cwd = fixtures.path('package-map/root');
13+
14+
// Throws ERR_PACKAGE_MAP_INVALID for invalid JSON.
15+
spawnSyncAndExit(process.execPath, [
16+
'--no-warnings',
17+
'--experimental-package-map',
18+
fixtures.path('package-map/package-map-invalid-syntax.json'),
19+
'--input-type=module',
20+
'--eval', `import x from 'dep-a';`,
21+
], { cwd }, {
22+
status: 1,
23+
signal: null,
24+
stderr: /ERR_PACKAGE_MAP_INVALID/,
25+
});
26+
27+
// Throws ERR_PACKAGE_MAP_INVALID for missing packages field.
28+
spawnSyncAndExit(process.execPath, [
29+
'--no-warnings',
30+
'--experimental-package-map',
31+
fixtures.path('package-map/package-map-invalid-schema.json'),
32+
'--input-type=module',
33+
'--eval', `import x from 'dep-a';`,
34+
], { cwd }, {
35+
status: 1,
36+
signal: null,
37+
stderr(output) {
38+
assert.match(output, /ERR_PACKAGE_MAP_INVALID/);
39+
assert.match(output, /packages/);
40+
},
41+
});
42+
43+
// Throws ERR_PACKAGE_MAP_KEY_NOT_FOUND for undefined dependency key.
44+
spawnSyncAndExit(process.execPath, [
45+
'--no-warnings',
46+
'--experimental-package-map',
47+
fixtures.path('package-map/package-map-missing-dep.json'),
48+
'--input-type=module',
49+
'--eval', `import x from 'nonexistent';`,
50+
], { cwd }, {
51+
status: 1,
52+
signal: null,
53+
stderr: /ERR_PACKAGE_MAP_KEY_NOT_FOUND/,
54+
});
55+
56+
// Throws for non-existent map file.
57+
spawnSyncAndExit(process.execPath, [
58+
'--no-warnings',
59+
'--experimental-package-map', '/nonexistent/package-map.json',
60+
'--input-type=module',
61+
'--eval', `import x from 'dep-a';`,
62+
], { cwd }, {
63+
status: 1,
64+
signal: null,
65+
stderr(output) {
66+
assert.match(output, /ERR_PACKAGE_MAP_INVALID/);
67+
assert.match(output, /no such file or directory/);
68+
},
69+
});
70+
71+
// Throws ERR_PACKAGE_MAP_INVALID for unsupported URL scheme in path.
72+
spawnSyncAndExit(process.execPath, [
73+
'--no-warnings',
74+
'--experimental-package-map',
75+
fixtures.path('package-map/package-map-https-path.json'),
76+
'--input-type=module',
77+
'--eval', `import x from 'dep-a';`,
78+
], { cwd }, {
79+
status: 1,
80+
signal: null,
81+
stderr(output) {
82+
assert.match(output, /ERR_PACKAGE_MAP_INVALID/);
83+
assert.match(output, /unsupported URL scheme/);
84+
assert.match(output, /https:\/\//);
85+
},
86+
});
87+
88+
// Accepts file:// URLs in path.
89+
{
90+
const fileUrlFixturePath = tmpdir.resolve('package-map-file-url.json');
91+
writeFileSync(fileUrlFixturePath, JSON.stringify({
92+
packages: {
93+
'root': {
94+
path: pathToFileURL(fixtures.path('package-map/root')).href,
95+
dependencies: { 'dep-a': 'dep-a' },
96+
},
97+
'dep-a': {
98+
path: pathToFileURL(fixtures.path('package-map/dep-a')).href,
99+
dependencies: {},
100+
},
101+
},
102+
}));
103+
104+
spawnSyncAndAssert(process.execPath, [
105+
'--no-warnings',
106+
'--experimental-package-map', fileUrlFixturePath,
107+
'--input-type=module',
108+
'--eval', `import dep from 'dep-a'; console.log(dep);`,
109+
], { cwd }, { stdout: /dep-a-value/, trim: true });
110+
}
111+
112+
// Throws ERR_PACKAGE_MAP_INVALID for duplicate package paths.
113+
spawnSyncAndExit(process.execPath, [
114+
'--no-warnings',
115+
'--experimental-package-map',
116+
fixtures.path('package-map/package-map-duplicate-path.json'),
117+
'--input-type=module',
118+
'--eval', `import x from 'dep-a';`,
119+
], { cwd }, {
120+
status: 1,
121+
signal: null,
122+
stderr(output) {
123+
assert.match(output, /ERR_PACKAGE_MAP_INVALID/);
124+
assert.match(output, /pkg-a/);
125+
assert.match(output, /pkg-b/);
126+
},
127+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Test that package maps respect package.json conditional and pattern exports.
2+
import '../common/index.mjs';
3+
import { spawnSyncAndAssert } from '../common/child_process.js';
4+
import * as fixtures from '../common/fixtures.mjs';
5+
6+
const packageMapPath = fixtures.path('package-map/package-map.json');
7+
const cwd = fixtures.path('package-map/root');
8+
9+
// Respects conditional exports (import).
10+
spawnSyncAndAssert(process.execPath, [
11+
'--no-warnings',
12+
'--experimental-package-map', packageMapPath,
13+
'--input-type=module',
14+
'--eval', `import { format } from 'dep-a'; console.log(format);`,
15+
], { cwd }, { stdout: /esm/, trim: true });
16+
17+
// Respects pattern exports.
18+
spawnSyncAndAssert(process.execPath, [
19+
'--no-warnings',
20+
'--experimental-package-map', packageMapPath,
21+
'--input-type=module',
22+
'--eval', `import util from 'dep-a/lib/util'; console.log(util);`,
23+
], { cwd }, { stdout: /dep-a-util/, trim: true });
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Test that the package map flag has no impact when not set and emits a warning when used.
2+
import '../common/index.mjs';
3+
import assert from 'node:assert';
4+
import { spawnSyncAndAssert } from '../common/child_process.js';
5+
import * as fixtures from '../common/fixtures.mjs';
6+
7+
const packageMapPath = fixtures.path('package-map/package-map.json');
8+
9+
// No impact when flag not set.
10+
spawnSyncAndAssert(process.execPath, [
11+
'--no-warnings',
12+
'--input-type=module',
13+
'--eval', `import fs from 'node:fs'; console.log('ok');`,
14+
], { stdout: /ok/, trim: true });
15+
16+
// Emits experimental warning on first use.
17+
spawnSyncAndAssert(process.execPath, [
18+
'--experimental-package-map', packageMapPath,
19+
'--input-type=module',
20+
'--eval', `import dep from 'dep-a';`,
21+
], { cwd: fixtures.path('package-map/root') }, {
22+
stderr(output) {
23+
assert.match(output, /ExperimentalWarning/);
24+
assert.match(output, /Package map/i);
25+
},
26+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Test package map path handling: containment, external paths, longest-path-wins.
2+
import '../common/index.mjs';
3+
import { spawnSyncAndAssert, spawnSyncAndExit } from '../common/child_process.js';
4+
import * as fixtures from '../common/fixtures.mjs';
5+
6+
// Path containment: does not match pkg-other as being inside pkg.
7+
spawnSyncAndAssert(process.execPath, [
8+
'--no-warnings',
9+
'--experimental-package-map',
10+
fixtures.path('package-map/package-map-path-prefix.json'),
11+
'--input-type=module',
12+
'--eval', `import pkg from 'pkg'; console.log(pkg);`,
13+
], { cwd: fixtures.path('package-map/pkg-other') }, {
14+
stdout: /pkg-value/,
15+
trim: true,
16+
});
17+
18+
// External paths: resolves packages outside the package map directory.
19+
spawnSyncAndAssert(process.execPath, [
20+
'--no-warnings',
21+
'--experimental-package-map',
22+
fixtures.path('package-map/nested-project/package-map-external-deps.json'),
23+
'--input-type=module',
24+
'--eval', `import dep from 'dep-a'; console.log(dep);`,
25+
], { cwd: fixtures.path('package-map/nested-project/src') }, {
26+
stdout: /dep-a-value/,
27+
trim: true,
28+
});
29+
30+
// Longest path wins: nested package uses its own dependencies, not the parent's.
31+
{
32+
const longestPathMap = fixtures.path('package-map/package-map-longest-path.json');
33+
const cwd = fixtures.path('package-map/root');
34+
35+
spawnSyncAndAssert(process.execPath, [
36+
'--no-warnings',
37+
'--experimental-package-map', longestPathMap,
38+
'--input-type=module',
39+
'--eval', `import inner from 'inner'; console.log(inner);`,
40+
], { cwd }, { stdout: /inner using dep-a-value/, trim: true });
41+
42+
// Root does not list dep-a, so importing it from root should fail.
43+
spawnSyncAndExit(process.execPath, [
44+
'--no-warnings',
45+
'--experimental-package-map', longestPathMap,
46+
'--input-type=module',
47+
'--eval', `import dep from 'dep-a';`,
48+
], { cwd }, {
49+
status: 1,
50+
signal: null,
51+
stderr: /ERR_MODULE_NOT_FOUND/,
52+
});
53+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Test that package maps resolve correctly through a symlinked ancestor directory.
2+
import { canCreateSymLink } from '../common/index.mjs';
3+
import { spawnSyncAndAssert } from '../common/child_process.js';
4+
import * as fixtures from '../common/fixtures.mjs';
5+
import tmpdir from '../common/tmpdir.js';
6+
import { symlinkSync } from 'node:fs';
7+
import path from 'node:path';
8+
9+
if (!canCreateSymLink()) {
10+
process.exit(0);
11+
}
12+
13+
tmpdir.refresh();
14+
15+
const symlinkDir = tmpdir.resolve('symlinked-package-map-esm');
16+
symlinkSync(fixtures.path('package-map'), symlinkDir, 'dir');
17+
18+
spawnSyncAndAssert(process.execPath, [
19+
'--no-warnings',
20+
'--experimental-package-map', path.join(symlinkDir, 'package-map.json'),
21+
'--input-type=module',
22+
'--eval', `import dep from 'dep-a'; console.log(dep);`,
23+
], { cwd: fixtures.path('package-map/root') }, {
24+
stdout: /dep-a-value/,
25+
trim: true,
26+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Test that the same bare specifier resolves to different packages depending on the importer.
2+
import '../common/index.mjs';
3+
import assert from 'node:assert';
4+
import { spawnSyncAndAssert } from '../common/child_process.js';
5+
import * as fixtures from '../common/fixtures.mjs';
6+
7+
spawnSyncAndAssert(process.execPath, [
8+
'--no-warnings',
9+
'--experimental-package-map',
10+
fixtures.path('package-map/package-map-version-fork.json'),
11+
'--input-type=module',
12+
'--eval',
13+
`import app18 from 'app-18'; import app19 from 'app-19'; console.log(app18); console.log(app19);`,
14+
], { cwd: fixtures.path('package-map/root') }, {
15+
stdout(output) {
16+
assert.match(output, /app-18 using react 18/);
17+
assert.match(output, /app-19 using react 19/);
18+
},
19+
});

0 commit comments

Comments
 (0)