node/test/es-module/test-esm-resolve-type.mjs
Geoffrey Booth 604ce4cc66
module: unflag detect-module
PR-URL: https://github.com/nodejs/node/pull/53619
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
2024-07-20 18:30:46 +00:00

247 lines
8.1 KiB
JavaScript

// Flags: --expose-internals
/**
* This test ensures defaultResolve returns the found module format in the
* return object in the form:
* { url: <url_value>, format: <'module'|'commonjs'|undefined> };
*/
import * as common from '../common/index.mjs';
import tmpdir from '../common/tmpdir.js';
import * as fixtures from '../common/fixtures.mjs';
import path from 'path';
import fs from 'fs';
import url from 'url';
import process from 'process';
if (!common.isMainThread) {
common.skip(
'test-esm-resolve-type.mjs: process.chdir is not available in Workers'
);
}
import assert from 'assert';
import internalResolve from 'node:internal/modules/esm/resolve';
const {
defaultResolve: resolve
} = internalResolve;
const rel = (file) => tmpdir.resolve(file);
const previousCwd = process.cwd();
const nmDir = rel('node_modules');
try {
tmpdir.refresh();
process.chdir(tmpdir.path);
/**
* ensure that resolving by full path does not return the format
* with the defaultResolver
*/
[
[ '/es-modules/package-ends-node_modules/index.js', 'module' ],
[ '/es-modules/package-type-module/index.js', 'module' ],
[ '/es-modules/package-type-commonjs/index.js', 'commonjs' ],
[ '/es-modules/package-without-type/index.js', null ],
[ '/es-modules/package-without-pjson/index.js', null ],
].forEach(([ testScript, expectedType ]) => {
const resolvedPath = path.resolve(fixtures.path(testScript));
const resolveResult = resolve(url.pathToFileURL(resolvedPath));
assert.strictEqual(resolveResult.format, expectedType);
});
/**
* create a test module and try to resolve it by module name.
* check the result is as expected
*
* for test-module-ne: everything .js that is not 'module' is 'commonjs'
*/
for (const [ moduleName, moduleExtension, moduleType, expectedResolvedType ] of
[ [ 'test-module-mainjs', 'js', 'module', 'module'],
[ 'test-module-mainmjs', 'mjs', 'module', 'module'],
[ 'test-module-cjs', 'js', 'commonjs', 'commonjs'],
[ 'test-module-ne', 'js', undefined, null],
]) {
process.chdir(previousCwd);
tmpdir.refresh();
process.chdir(tmpdir.path);
const createDir = (path) => {
if (!fs.existsSync(path)) {
fs.mkdirSync(path);
}
};
const mDir = rel(`node_modules/${moduleName}`);
const subDir = rel(`node_modules/${moduleName}/subdir`);
const pkg = rel(`node_modules/${moduleName}/package.json`);
const script = rel(`node_modules/${moduleName}/subdir/mainfile.${moduleExtension}`);
createDir(nmDir);
createDir(mDir);
createDir(subDir);
const pkgJsonContent = {
...(moduleType !== undefined) && { type: moduleType },
main: `subdir/mainfile.${moduleExtension}`
};
fs.writeFileSync(pkg, JSON.stringify(pkgJsonContent));
fs.writeFileSync(script,
'export function esm-resolve-tester() {return 42}');
const resolveResult = resolve(`${moduleName}`);
assert.strictEqual(resolveResult.format, expectedResolvedType);
fs.rmSync(nmDir, { recursive: true, force: true });
}
// Helpers
const createDir = (path) => {
if (!fs.existsSync(path)) {
fs.mkdirSync(path);
}
};
{
// Create a dummy dual package
//
/**
* this creates the following directory structure:
*
* ./node_modules:
* |-> my-dual-package
* |-> es
* |-> index.js
* |-> package.json [2]
* |-> lib
* |-> index.js
* |->package.json [1]
*
* in case the package is imported:
* import * as my-package from 'my-dual-package'
* it will cause the resolve method to return:
* {
* url: '<base_path>/node_modules/my-dual-package/es/index.js',
* format: 'module'
* }
*
* following testcase ensures that resolve works correctly in this case
* returning the information as specified above. Source for 'url' value
* is [1], source for 'format' value is [2]
*/
const moduleName = 'my-dual-package';
const mDir = rel(`node_modules/${moduleName}`);
const esSubDir = rel(`node_modules/${moduleName}/es`);
const cjsSubDir = rel(`node_modules/${moduleName}/lib`);
const pkg = rel(`node_modules/${moduleName}/package.json`);
const esmPkg = rel(`node_modules/${moduleName}/es/package.json`);
const esScript = rel(`node_modules/${moduleName}/es/index.js`);
const cjsScript = rel(`node_modules/${moduleName}/lib/index.js`);
createDir(nmDir);
createDir(mDir);
createDir(esSubDir);
createDir(cjsSubDir);
const mainPkgJsonContent = {
type: 'commonjs',
exports: {
'.': {
'require': './lib/index.js',
'import': './es/index.js',
'default': './lib/index.js'
},
'./package.json': './package.json',
}
};
const esmPkgJsonContent = {
type: 'module'
};
fs.writeFileSync(pkg, JSON.stringify(mainPkgJsonContent));
fs.writeFileSync(esmPkg, JSON.stringify(esmPkgJsonContent));
fs.writeFileSync(
esScript,
'export function esm-resolve-tester() {return 42}'
);
fs.writeFileSync(
cjsScript,
'module.exports = {esm-resolve-tester: () => {return 42}}'
);
// test the resolve
const resolveResult = resolve(`${moduleName}`);
assert.strictEqual(resolveResult.format, 'module');
assert.ok(resolveResult.url.includes('my-dual-package/es/index.js'));
}
// TestParameters are ModuleName, mainRequireScript, mainImportScript,
// mainPackageType, subdirPkgJsonType, expectedResolvedFormat, mainSuffix
[
[ 'mjs-mod-mod', 'index.js', 'index.mjs', 'module', 'module', 'module'],
[ 'mjs-com-com', 'idx.js', 'idx.mjs', 'commonjs', 'commonjs', 'module'],
[ 'mjs-mod-com', 'index.js', 'imp.mjs', 'module', 'commonjs', 'module'],
[ 'cjs-mod-mod', 'index.cjs', 'imp.cjs', 'module', 'module', 'commonjs'],
[ 'js-com-com', 'index.js', 'imp.js', 'commonjs', 'commonjs', 'commonjs'],
[ 'js-com-mod', 'index.js', 'imp.js', 'commonjs', 'module', 'module'],
[ 'qmod', 'index.js', 'imp.js', 'commonjs', 'module', 'module', '?k=v'],
[ 'hmod', 'index.js', 'imp.js', 'commonjs', 'module', 'module', '#Key'],
[ 'qhmod', 'index.js', 'imp.js', 'commonjs', 'module', 'module', '?k=v#h'],
[ 'ts-mod-com', 'index.js', 'imp.ts', 'module', 'commonjs', undefined],
].forEach((testVariant) => {
const [
moduleName,
mainRequireScript,
mainImportScript,
mainPackageType,
subdirPackageType,
expectedResolvedFormat,
mainSuffix = '' ] = testVariant;
const mDir = rel(`node_modules/${moduleName}`);
const subDir = rel(`node_modules/${moduleName}/subdir`);
const pkg = rel(`node_modules/${moduleName}/package.json`);
const subdirPkg = rel(`node_modules/${moduleName}/subdir/package.json`);
const esScript = rel(`node_modules/${moduleName}/subdir/${mainImportScript}`);
const cjsScript = rel(`node_modules/${moduleName}/subdir/${mainRequireScript}`);
createDir(nmDir);
createDir(mDir);
createDir(subDir);
const mainPkgJsonContent = {
type: mainPackageType,
exports: {
'.': {
'require': `./subdir/${mainRequireScript}${mainSuffix}`,
'import': `./subdir/${mainImportScript}${mainSuffix}`,
'default': `./subdir/${mainRequireScript}${mainSuffix}`
},
'./package.json': './package.json',
}
};
const subdirPkgJsonContent = {
type: `${subdirPackageType}`
};
fs.writeFileSync(pkg, JSON.stringify(mainPkgJsonContent));
fs.writeFileSync(subdirPkg, JSON.stringify(subdirPkgJsonContent));
fs.writeFileSync(
esScript,
'export function esm-resolve-tester() {return 42}'
);
fs.writeFileSync(
cjsScript,
'module.exports = {esm-resolve-tester: () => {return 42}}'
);
// test the resolve
const resolveResult = resolve(`${moduleName}`);
assert.strictEqual(resolveResult.format, expectedResolvedFormat);
assert.ok(resolveResult.url.endsWith(`${moduleName}/subdir/${mainImportScript}${mainSuffix}`));
});
} finally {
process.chdir(previousCwd);
fs.rmSync(nmDir, { recursive: true, force: true });
}