node-jest/resolveexports/test/resolve.js

712 lines
16 KiB
JavaScript

import { suite } from 'uvu';
import * as assert from 'uvu/assert';
import * as $exports from '../src';
function pass(pkg, expects, ...args) {
let out = $exports.resolve(pkg, ...args);
assert.is(out, expects);
}
function fail(pkg, target, ...args) {
try {
$exports.resolve(pkg, ...args);
assert.unreachable();
} catch (err) {
assert.instance(err, Error);
assert.is(err.message, `Missing "${target}" export in "${pkg.name}" package`);
}
}
// ---
const resolve = suite('$.resolve');
resolve('should be a function', () => {
assert.type($exports.resolve, 'function');
});
resolve('exports=string', () => {
let pkg = {
"name": "foobar",
"exports": "$string",
};
pass(pkg, '$string');
pass(pkg, '$string', '.');
pass(pkg, '$string', 'foobar');
fail(pkg, './other', 'other');
fail(pkg, './other', 'foobar/other');
fail(pkg, './hello', './hello');
});
resolve('exports = { self }', () => {
let pkg = {
"name": "foobar",
"exports": {
"import": "$import",
"require": "$require",
}
};
pass(pkg, '$import');
pass(pkg, '$import', '.');
pass(pkg, '$import', 'foobar');
fail(pkg, './other', 'other');
fail(pkg, './other', 'foobar/other');
fail(pkg, './hello', './hello');
});
resolve('exports["."] = string', () => {
let pkg = {
"name": "foobar",
"exports": {
".": "$self",
}
};
pass(pkg, '$self');
pass(pkg, '$self', '.');
pass(pkg, '$self', 'foobar');
fail(pkg, './other', 'other');
fail(pkg, './other', 'foobar/other');
fail(pkg, './hello', './hello');
});
resolve('exports["."] = object', () => {
let pkg = {
"name": "foobar",
"exports": {
".": {
"import": "$import",
"require": "$require",
}
}
};
pass(pkg, '$import');
pass(pkg, '$import', '.');
pass(pkg, '$import', 'foobar');
fail(pkg, './other', 'other');
fail(pkg, './other', 'foobar/other');
fail(pkg, './hello', './hello');
});
resolve('exports["./foo"] = string', () => {
let pkg = {
"name": "foobar",
"exports": {
"./foo": "$import",
}
};
pass(pkg, '$import', './foo');
pass(pkg, '$import', 'foobar/foo');
fail(pkg, '.');
fail(pkg, '.', 'foobar');
fail(pkg, './other', 'foobar/other');
});
resolve('exports["./foo"] = object', () => {
let pkg = {
"name": "foobar",
"exports": {
"./foo": {
"import": "$import",
"require": "$require",
}
}
};
pass(pkg, '$import', './foo');
pass(pkg, '$import', 'foobar/foo');
fail(pkg, '.');
fail(pkg, '.', 'foobar');
fail(pkg, './other', 'foobar/other');
});
// https://nodejs.org/api/packages.html#packages_nested_conditions
resolve('nested conditions', () => {
let pkg = {
"name": "foobar",
"exports": {
"node": {
"import": "$node.import",
"require": "$node.require"
},
"default": "$default",
}
};
pass(pkg, '$node.import');
pass(pkg, '$node.import', 'foobar');
// browser => no "node" key
pass(pkg, '$default', '.', { browser: true });
pass(pkg, '$default', 'foobar', { browser: true });
fail(pkg, './hello', './hello');
fail(pkg, './other', 'foobar/other');
fail(pkg, './other', 'other');
});
resolve('nested conditions :: subpath', () => {
let pkg = {
"name": "foobar",
"exports": {
"./lite": {
"node": {
"import": "$node.import",
"require": "$node.require"
},
"browser": {
"import": "$browser.import",
"require": "$browser.require"
},
}
}
};
pass(pkg, '$node.import', 'foobar/lite');
pass(pkg, '$node.require', 'foobar/lite', { require: true });
pass(pkg, '$browser.import', 'foobar/lite', { browser: true });
pass(pkg, '$browser.require', 'foobar/lite', { browser: true, require: true });
});
resolve('nested conditions :: subpath :: inverse', () => {
let pkg = {
"name": "foobar",
"exports": {
"./lite": {
"import": {
"browser": "$browser.import",
"node": "$node.import",
},
"require": {
"browser": "$browser.require",
"node": "$node.require",
}
}
}
};
pass(pkg, '$node.import', 'foobar/lite');
pass(pkg, '$node.require', 'foobar/lite', { require: true });
pass(pkg, '$browser.import', 'foobar/lite', { browser: true });
pass(pkg, '$browser.require', 'foobar/lite', { browser: true, require: true });
});
// https://nodejs.org/api/packages.html#packages_subpath_folder_mappings
resolve('exports["./"]', () => {
let pkg = {
"name": "foobar",
"exports": {
".": {
"require": "$require",
"import": "$import"
},
"./package.json": "./package.json",
"./": "./"
}
};
pass(pkg, '$import');
pass(pkg, '$import', 'foobar');
pass(pkg, '$require', 'foobar', { require: true });
pass(pkg, './package.json', 'package.json');
pass(pkg, './package.json', 'foobar/package.json');
pass(pkg, './package.json', './package.json');
// "loose" / everything exposed
pass(pkg, './hello.js', 'hello.js');
pass(pkg, './hello.js', 'foobar/hello.js');
pass(pkg, './hello/world.js', './hello/world.js');
});
resolve('exports["./"] :: w/o "." key', () => {
let pkg = {
"name": "foobar",
"exports": {
"./package.json": "./package.json",
"./": "./"
}
};
fail(pkg, '.', ".");
fail(pkg, '.', "foobar");
pass(pkg, './package.json', 'package.json');
pass(pkg, './package.json', 'foobar/package.json');
pass(pkg, './package.json', './package.json');
// "loose" / everything exposed
pass(pkg, './hello.js', 'hello.js');
pass(pkg, './hello.js', 'foobar/hello.js');
pass(pkg, './hello/world.js', './hello/world.js');
});
// https://nodejs.org/api/packages.html#packages_subpath_folder_mappings
resolve('exports["./*"]', () => {
let pkg = {
"name": "foobar",
"exports": {
"./*": "./cheese/*.mjs"
}
};
fail(pkg, '.', ".");
fail(pkg, '.', "foobar");
pass(pkg, './cheese/hello.mjs', 'hello');
pass(pkg, './cheese/hello.mjs', 'foobar/hello');
pass(pkg, './cheese/hello/world.mjs', './hello/world');
// evaluate as defined, not wrong
pass(pkg, './cheese/hello.js.mjs', 'hello.js');
pass(pkg, './cheese/hello.js.mjs', 'foobar/hello.js');
pass(pkg, './cheese/hello/world.js.mjs', './hello/world.js');
});
// https://nodejs.org/api/packages.html#packages_subpath_folder_mappings
resolve('exports["./features/"]', () => {
let pkg = {
"name": "foobar",
"exports": {
"./features/": "./features/"
}
};
pass(pkg, './features/', 'features/');
pass(pkg, './features/', 'foobar/features/');
pass(pkg, './features/hello.js', 'foobar/features/hello.js');
fail(pkg, './features', 'features');
fail(pkg, './features', 'foobar/features');
fail(pkg, './package.json', 'package.json');
fail(pkg, './package.json', 'foobar/package.json');
fail(pkg, './package.json', './package.json');
});
// https://nodejs.org/api/packages.html#packages_subpath_folder_mappings
resolve('exports["./features/"] :: with "./" key', () => {
let pkg = {
"name": "foobar",
"exports": {
"./features/": "./features/",
"./package.json": "./package.json",
"./": "./"
}
};
pass(pkg, './features', 'features'); // via "./"
pass(pkg, './features', 'foobar/features'); // via "./"
pass(pkg, './features/', 'features/'); // via "./features/"
pass(pkg, './features/', 'foobar/features/'); // via "./features/"
pass(pkg, './features/hello.js', 'foobar/features/hello.js');
pass(pkg, './package.json', 'package.json');
pass(pkg, './package.json', 'foobar/package.json');
pass(pkg, './package.json', './package.json');
// Does NOT hit "./" (match Node)
fail(pkg, '.', '.');
fail(pkg, '.', 'foobar');
});
resolve('exports["./features/"] :: conditions', () => {
let pkg = {
"name": "foobar",
"exports": {
"./features/": {
"browser": {
"import": "./browser.import/",
"require": "./browser.require/",
},
"import": "./import/",
"require": "./require/",
},
}
};
// import
pass(pkg, './import/', 'features/');
pass(pkg, './import/', 'foobar/features/');
pass(pkg, './import/hello.js', './features/hello.js');
pass(pkg, './import/hello.js', 'foobar/features/hello.js');
// require
pass(pkg, './require/', 'features/', { require: true });
pass(pkg, './require/', 'foobar/features/', { require: true });
pass(pkg, './require/hello.js', './features/hello.js', { require: true });
pass(pkg, './require/hello.js', 'foobar/features/hello.js', { require: true });
// require + browser
pass(pkg, './browser.require/', 'features/', { browser: true, require: true });
pass(pkg, './browser.require/', 'foobar/features/', { browser: true, require: true });
pass(pkg, './browser.require/hello.js', './features/hello.js', { browser: true, require: true });
pass(pkg, './browser.require/hello.js', 'foobar/features/hello.js', { browser: true, require: true });
});
// https://nodejs.org/api/packages.html#packages_subpath_folder_mappings
resolve('exports["./features/*"]', () => {
let pkg = {
"name": "foobar",
"exports": {
"./features/*": "./features/*.js",
}
};
fail(pkg, './features', 'features');
fail(pkg, './features', 'foobar/features');
fail(pkg, './features/', 'features/');
fail(pkg, './features/', 'foobar/features/');
pass(pkg, './features/a.js', 'foobar/features/a');
pass(pkg, './features/ab.js', 'foobar/features/ab');
pass(pkg, './features/abc.js', 'foobar/features/abc');
pass(pkg, './features/hello.js', 'foobar/features/hello');
pass(pkg, './features/world.js', 'foobar/features/world');
// incorrect, but matches Node. evaluate as defined
pass(pkg, './features/hello.js.js', 'foobar/features/hello.js');
pass(pkg, './features/world.js.js', 'foobar/features/world.js');
fail(pkg, './package.json', 'package.json');
fail(pkg, './package.json', 'foobar/package.json');
fail(pkg, './package.json', './package.json');
});
// https://nodejs.org/api/packages.html#packages_subpath_folder_mappings
resolve('exports["./features/*"] :: with "./" key', () => {
let pkg = {
"name": "foobar",
"exports": {
"./features/*": "./features/*.js",
"./": "./"
}
};
pass(pkg, './features', 'features'); // via "./"
pass(pkg, './features', 'foobar/features'); // via "./"
pass(pkg, './features/', 'features/'); // via "./"
pass(pkg, './features/', 'foobar/features/'); // via "./"
pass(pkg, './features/hello.js', 'foobar/features/hello');
pass(pkg, './features/world.js', 'foobar/features/world');
// incorrect, but matches Node. evaluate as defined
pass(pkg, './features/hello.js.js', 'foobar/features/hello.js');
pass(pkg, './features/world.js.js', 'foobar/features/world.js');
pass(pkg, './package.json', 'package.json');
pass(pkg, './package.json', 'foobar/package.json');
pass(pkg, './package.json', './package.json');
// Does NOT hit "./" (match Node)
fail(pkg, '.', '.');
fail(pkg, '.', 'foobar');
});
resolve('exports["./features/*"] :: conditions', () => {
let pkg = {
"name": "foobar",
"exports": {
"./features/*": {
"browser": {
"import": "./browser.import/*.mjs",
"require": "./browser.require/*.js",
},
"import": "./import/*.mjs",
"require": "./require/*.js",
},
}
};
// import
fail(pkg, './features/', 'features/'); // no file
fail(pkg, './features/', 'foobar/features/'); // no file
pass(pkg, './import/hello.mjs', './features/hello');
pass(pkg, './import/hello.mjs', 'foobar/features/hello');
// require
fail(pkg, './features/', 'features/', { require: true }); // no file
fail(pkg, './features/', 'foobar/features/', { require: true }); // no file
pass(pkg, './require/hello.js', './features/hello', { require: true });
pass(pkg, './require/hello.js', 'foobar/features/hello', { require: true });
// require + browser
fail(pkg, './features/', 'features/', { browser: true, require: true }); // no file
fail(pkg, './features/', 'foobar/features/', { browser: true, require: true }); // no file
pass(pkg, './browser.require/hello.js', './features/hello', { browser: true, require: true });
pass(pkg, './browser.require/hello.js', 'foobar/features/hello', { browser: true, require: true });
});
resolve('should handle mixed path/conditions', () => {
let pkg = {
"name": "foobar",
"exports": {
".": [
{
"import": "$root.import",
},
"$root.string"
],
"./foo": [
{
"require": "$foo.require"
},
"$foo.string"
]
}
}
pass(pkg, '$root.import');
pass(pkg, '$root.import', 'foobar');
pass(pkg, '$foo.string', 'foo');
pass(pkg, '$foo.string', 'foobar/foo');
pass(pkg, '$foo.string', './foo');
pass(pkg, '$foo.require', 'foo', { require: true });
pass(pkg, '$foo.require', 'foobar/foo', { require: true });
pass(pkg, '$foo.require', './foo', { require: true });
});
resolve.run();
// ---
const requires = suite('options.requires', {
"exports": {
"require": "$require",
"import": "$import",
}
});
requires('should ignore "require" keys by default', pkg => {
pass(pkg, '$import');
});
requires('should use "require" key when defined first', pkg => {
pass(pkg, '$require', '.', { require: true });
});
requires('should ignore "import" key when enabled', () => {
let pkg = {
"exports": {
"import": "$import",
"require": "$require",
}
};
pass(pkg, '$require', '.', { require: true });
pass(pkg, '$import', '.');
});
requires('should match "default" if "require" is after', () => {
let pkg = {
"exports": {
"default": "$default",
"require": "$require",
}
};
pass(pkg, '$default', '.', { require: true });
});
requires.run();
// ---
const browser = suite('options.browser', {
"exports": {
"browser": "$browser",
"node": "$node",
}
});
browser('should ignore "browser" keys by default', pkg => {
pass(pkg, '$node');
});
browser('should use "browser" key when defined first', pkg => {
pass(pkg, '$browser', '.', { browser: true });
});
browser('should ignore "node" key when enabled', () => {
let pkg = {
"exports": {
"node": "$node",
"import": "$import",
"browser": "$browser",
}
};
// import defined before browser
pass(pkg, '$import', '.', { browser: true });
});
browser.run();
// ---
const conditions = suite('options.conditions', {
"exports": {
"production": "$prod",
"development": "$dev",
"default": "$default",
}
});
conditions('should ignore unknown conditions by default', pkg => {
pass(pkg, '$default');
});
conditions('should recognize custom field(s) when specified', pkg => {
pass(pkg, '$dev', '.', {
conditions: ['development']
});
pass(pkg, '$prod', '.', {
conditions: ['development', 'production']
});
});
conditions('should throw an error if no known conditions', ctx => {
let pkg = {
"name": "hello",
"exports": {
...ctx.exports
},
};
delete pkg.exports.default;
try {
$exports.resolve(pkg);
assert.unreachable();
} catch (err) {
assert.instance(err, Error);
assert.is(err.message, `No known conditions for "." entry in "hello" package`);
}
});
conditions.run();
// ---
const unsafe = suite('options.unsafe', {
"exports": {
".": {
"production": "$prod",
"development": "$dev",
"default": "$default",
},
"./spec/type": {
"import": "$import",
"require": "$require",
"default": "$default"
},
"./spec/env": {
"worker": {
"default": "$worker"
},
"browser": "$browser",
"node": "$node",
"default": "$default"
}
}
});
unsafe('should ignore unknown conditions by default', pkg => {
pass(pkg, '$default', '.', {
unsafe: true,
});
});
unsafe('should ignore "import" and "require" conditions by default', pkg => {
pass(pkg, '$default', './spec/type', {
unsafe: true,
});
pass(pkg, '$default', './spec/type', {
unsafe: true,
require: true,
});
});
unsafe('should ignore "node" and "browser" conditions by default', pkg => {
pass(pkg, '$default', './spec/type', {
unsafe: true,
});
pass(pkg, '$default', './spec/type', {
unsafe: true,
browser: true,
});
});
unsafe('should respect/accept any custom condition(s) when specified', pkg => {
// root, dev only
pass(pkg, '$dev', '.', {
unsafe: true,
conditions: ['development']
});
// root, defined order
pass(pkg, '$prod', '.', {
unsafe: true,
conditions: ['development', 'production']
});
// import vs require, defined order
pass(pkg, '$require', './spec/type', {
unsafe: true,
conditions: ['require']
});
// import vs require, defined order
pass(pkg, '$import', './spec/type', {
unsafe: true,
conditions: ['import', 'require']
});
// import vs require, defined order
pass(pkg, '$node', './spec/env', {
unsafe: true,
conditions: ['node']
});
// import vs require, defined order
pass(pkg, '$browser', './spec/env', {
unsafe: true,
conditions: ['browser', 'node']
});
// import vs require, defined order
pass(pkg, '$worker', './spec/env', {
unsafe: true,
conditions: ['browser', 'node', 'worker']
});
});
unsafe.run();