use std::path::Path;
use simd_json::json;
use crate::{package_json, Ctx, PathUtil, ResolveError, ResolveOptions, Resolver};
#[tokio::test]
async fn test_simple() {
let f = super::fixture().join("exports-field");
let f2 = super::fixture().join("exports-field2");
let f4 = super::fixture().join("exports-field-error");
let f5 = super::fixture().join("imports-exports-wildcard");
let f6 = super::fixture().join("export-query");
let resolver = Resolver::new(ResolveOptions {
extensions: vec![".js".into()],
fully_specified: true,
condition_names: vec!["webpack".into()],
..ResolveOptions::default()
});
#[rustfmt::skip]
let pass = [
("resolve root using exports field, not a main field", f.clone(), "exports-field", f.join("node_modules/exports-field/x.js")),
("resolver should respect condition names", f.clone(), "exports-field/dist/main.js", f.join("node_modules/exports-field/lib/lib2/main.js")),
("resolver should respect query parameters #1", f2.clone(), "exports-field/dist/main.js?foo", f2.join("node_modules/exports-field/lib/lib2/main.js?foo")),
("resolver should respect fragment parameters #1", f2.clone(), "exports-field/dist/main.js#foo", f2.join("node_modules/exports-field/lib/lib2/main.js#foo")),
("relative path should work, if relative path as request is used", f.clone(), "./node_modules/exports-field/lib/main.js", f.join("node_modules/exports-field/lib/main.js")),
("self-resolving root", f.clone(), "@exports-field/core", f.join("a.js")),
("should resolve with wildcard pattern #1", f5.clone(), "m/features/f.js", f5.join("node_modules/m/src/features/f.js")),
("should resolve with wildcard pattern #2", f5.clone(), "m/features/y/y.js", f5.join("node_modules/m/src/features/y/y.js")),
("should resolve with wildcard pattern #3", f5.clone(), "m/features-no-ext/y/y.js", f5.join("node_modules/m/src/features/y/y.js")),
("should resolve with wildcard pattern #4", f5.clone(), "m/middle/nested/f.js", f5.join("node_modules/m/src/middle/nested/f.js")),
("should resolve with wildcard pattern #5", f5.clone(), "m/middle-1/nested/f.js", f5.join("node_modules/m/src/middle-1/nested/f.js")),
("should resolve with wildcard pattern #6", f5.clone(), "m/middle-2/nested/f.js", f5.join("node_modules/m/src/middle-2/nested/f.js")),
("should resolve with wildcard pattern #7", f5.clone(), "m/middle-3/nested/f", f5.join("node_modules/m/src/middle-3/nested/f/nested/f.js")),
("should resolve with wildcard pattern #8", f5.clone(), "m/middle-4/f/nested", f5.join("node_modules/m/src/middle-4/f/f.js")),
("should resolve with wildcard pattern #9", f5.clone(), "m/middle-5/f$/$", f5.join("node_modules/m/src/middle-5/f$/$.js")),
("should resolve with query string #10", f6.clone(), "export-query/add", f6.join("add.js?query1?query2")),
("should resolve with query string #10", f6.clone(), "export-query/minus", f6.join("minus.js?query?extra")),
("should resolve with query string #10", f6.clone(), "export-query/equal", f6.join("equal.js?query")),
];
for (comment, path, request, expected) in pass {
let resolved_path = resolver
.resolve(&path, request)
.await
.map(|r| r.full_path());
assert_eq!(resolved_path, Ok(expected), "{comment} {path:?} {request}");
}
let p = f.join("node_modules/exports-field/package.json");
let p2 = f2.join("node_modules/exports-field/package.json");
let p4 = f4.join("node_modules/exports-field/package.json");
let p5 = f5.join("node_modules/m/package.json");
#[rustfmt::skip]
let fail = [
("resolver should respect query parameters #2. Direct matching", f2.clone(), "exports-field?foo", ResolveError::PackagePathNotExported("./?foo".into(), p2.clone())),
("resolver should respect fragment parameters #2. Direct matching", f2, "exports-field#foo", ResolveError::PackagePathNotExported("./#foo".into(), p2)),
("relative path should not work with exports field", f.clone(), "./node_modules/exports-field/dist/main.js", ResolveError::NotFound("./node_modules/exports-field/dist/main.js".into())),
("backtracking should not work for request", f.clone(), "exports-field/dist/../../../a.js", ResolveError::InvalidPackageTarget("./lib/../../../a.js".to_string(), "./dist/".to_string(), p.clone())),
("backtracking should not work for exports field target", f.clone(), "exports-field/dist/a.js", ResolveError::InvalidPackageTarget("./../../a.js".to_string(), "./dist/a.js".to_string(), p.clone())),
("not exported error", f.clone(), "exports-field/anything/else", ResolveError::PackagePathNotExported("./anything/else".to_string(), p.clone())),
("request ending with slash #1", f.clone(), "exports-field/", ResolveError::PackagePathNotExported("./".to_string(), p.clone())),
("request ending with slash #2", f.clone(), "exports-field/dist/", ResolveError::PackagePathNotExported("./dist/".to_string(), p.clone())),
("request ending with slash #3", f.clone(), "exports-field/lib/", ResolveError::PackagePathNotExported("./lib/".to_string(), p)),
("should throw error if target is invalid", f4, "exports-field", ResolveError::InvalidPackageTarget("./a/../b/../../pack1/index.js".to_string(), ".".to_string(), p4)),
("throw error if exports field is invalid", f.clone(), "invalid-exports-field", ResolveError::InvalidPackageConfig(f.join("node_modules/invalid-exports-field/package.json"))),
("should throw error if target is 'null'", f5, "m/features/internal/file.js", ResolveError::PackagePathNotExported("./features/internal/file.js".to_string(), p5)),
];
for (comment, path, request, error) in fail {
let resolution = resolver.resolve(&path, request).await;
assert_eq!(resolution, Err(error), "{comment} {path:?} {request}");
}
}
#[tokio::test]
async fn exports_not_browser_field1() {
let f = super::fixture().join("exports-field");
let resolver = Resolver::new(ResolveOptions {
alias_fields: vec![vec!["browser".into()]],
condition_names: vec!["webpack".into()],
extensions: vec![".js".into()],
..ResolveOptions::default()
});
let resolved_path = resolver
.resolve(&f, "exports-field/dist/main.js")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f.join("node_modules/exports-field/lib/lib2/main.js"))
);
}
#[tokio::test]
async fn exports_not_browser_field2() {
let f2 = super::fixture().join("exports-field2");
let resolver = Resolver::new(ResolveOptions {
alias_fields: vec![vec!["browser".into()]],
extensions: vec![".js".into()],
condition_names: vec!["node".into()],
..ResolveOptions::default()
});
let resolved_path = resolver
.resolve(&f2, "exports-field/dist/main.js")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f2.join("node_modules/exports-field/lib/browser.js"))
);
}
#[tokio::test]
async fn extension_without_fully_specified() {
let f2 = super::fixture().join("exports-field2");
let commonjs_resolver = Resolver::new(ResolveOptions {
extensions: vec![".js".into()],
condition_names: vec!["webpack".into()],
..ResolveOptions::default()
});
let resolved_path = commonjs_resolver
.resolve(&f2, "exports-field/dist/main")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f2.join("node_modules/exports-field/lib/lib2/main.js"))
);
}
#[tokio::test]
async fn field_name_path() {
let f2 = super::fixture().join("exports-field2");
let f3 = super::fixture().join("exports-field3");
let exports_fields = [
vec![vec!["exportsField".into(), "exports".into()]],
vec![
vec!["exportsField".into(), "exports".into()],
vec!["exports".into()],
],
vec![
vec!["exports".into()],
vec!["exportsField".into(), "exports".into()],
],
];
for exports_fields in exports_fields {
let resolver = Resolver::new(ResolveOptions {
alias_fields: vec![vec!["browser".into()]],
exports_fields,
extensions: vec![".js".into()],
..ResolveOptions::default()
});
let resolved_path = resolver
.resolve(&f3, "exports-field")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f3.join("node_modules/exports-field/main.js"))
);
}
let resolver = Resolver::new(ResolveOptions {
alias_fields: vec![vec!["browser".into()]],
exports_fields: vec![vec!["exports".into()]],
extensions: vec![".js".into()],
..ResolveOptions::default()
});
let resolved_path = resolver
.resolve(&f2, "exports-field")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f2.join("node_modules/exports-field/index.js"))
);
let resolver = Resolver::new(ResolveOptions {
alias_fields: vec![vec!["browser".into()]],
exports_fields: vec![
vec!["ex".into()],
vec!["exports_field".into(), "exports".into()],
],
extensions: vec![".js".into()],
..ResolveOptions::default()
});
let resolved_path = resolver
.resolve(&f3, "exports-field")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f3.join("node_modules/exports-field/index"))
);
let resolver = Resolver::new(ResolveOptions {
exports_fields: vec![vec!["broken".into()]],
extensions: vec![".js".into()],
..ResolveOptions::default()
});
let resolved_path = resolver
.resolve(&f3, "exports-field")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f3.join("node_modules/exports-field/src/index.js"))
);
}
#[tokio::test]
async fn shared_resolvers() {
let f3 = super::fixture().join("exports-field3");
let resolver1 = Resolver::new(ResolveOptions {
exports_fields: vec![vec!["exportsField".into(), "exports".into()]],
extensions: vec![".js".into()],
..ResolveOptions::default()
});
let resolved_path = resolver1
.resolve(&f3, "exports-field")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f3.join("node_modules/exports-field/main.js"))
);
let resolver2 = resolver1.clone_with_options(ResolveOptions {
exports_fields: vec![vec!["ex".into()]],
extensions: vec![".js".into()],
..ResolveOptions::default()
});
let resolved_path = resolver2
.resolve(&f3, "exports-field")
.await
.map(|r| r.full_path());
assert_eq!(
resolved_path,
Ok(f3.join("node_modules/exports-field/index"))
);
}
#[tokio::test]
async fn extension_alias_1_2() {
let f = super::fixture().join("exports-field-and-extension-alias");
let resolver = Resolver::new(ResolveOptions {
extensions: vec![".js".into()],
extension_alias: vec![(".js".into(), vec![".ts".into(), ".js".into()])],
fully_specified: true,
condition_names: vec!["webpack".into(), "default".into()],
..ResolveOptions::default()
});
#[rustfmt::skip]
let pass = [
("should resolve with the `extensionAlias` option", f.clone(), "@org/pkg/string.js", f.join("node_modules/@org/pkg/dist/string.js")),
("should resolve with the `extensionAlias` option #2", f.clone(), "pkg/string.js", f.join("node_modules/pkg/dist/string.js")),
];
for (comment, path, request, expected) in pass {
let resolved_path = resolver
.resolve(&path, request)
.await
.map(|r| r.full_path());
assert_eq!(resolved_path, Ok(expected), "{comment} {path:?} {request}");
}
}
#[tokio::test]
async fn extension_alias_3() {
let f = super::fixture().join("exports-field-and-extension-alias");
let resolver = Resolver::new(ResolveOptions {
extensions: vec![".js".into()],
extension_alias: vec![(
".js".into(),
vec![
".foo".into(),
".baz".into(),
".baz".into(),
".ts".into(),
".js".into(),
],
)],
fully_specified: true,
condition_names: vec!["webpack".into(), "default".into()],
..ResolveOptions::default()
});
#[rustfmt::skip]
let pass = [
("should resolve with the `extensionAlias` option #3", f.clone(), "pkg/string.js", f.join("node_modules/pkg/dist/string.js")),
];
for (comment, path, request, expected) in pass {
let resolved_path = resolver
.resolve(&path, request)
.await
.map(|r| r.full_path());
assert_eq!(resolved_path, Ok(expected), "{comment} {path:?} {request}");
}
}
#[tokio::test]
async fn extension_alias_throw_error() {
let f = super::fixture().join("exports-field-and-extension-alias");
let resolver = Resolver::new(ResolveOptions {
extensions: vec![".js".into()],
extension_alias: vec![(".js".into(), vec![".ts".into()])],
fully_specified: true,
condition_names: vec!["webpack".into(), "default".into()],
..ResolveOptions::default()
});
#[rustfmt::skip]
let fail = [
("should throw error with the `extensionAlias` option", f.clone(), "pkg/string.js", ResolveError::ExtensionAlias("string.js".into(), "string.ts".into(), f.join("node_modules/pkg/dist"))),
];
for (comment, path, request, error) in fail {
let resolution = resolver.resolve(&path, request).await;
assert_eq!(resolution, Err(error), "{comment} {path:?} {request}");
}
}
struct TestCase {
name: &'static str,
expect: Option<Vec<&'static str>>,
exports_field: package_json::JSONValue<'static>,
request: &'static str,
condition_names: Vec<&'static str>,
}
#[allow(clippy::needless_pass_by_value)]
fn exports_field(value: simd_json::value::OwnedValue) -> package_json::JSONValue<'static> {
value.into()
}
#[tokio::test]
async fn test_cases() {
let test_cases = [
TestCase {
name: "sample #1",
expect: Some(vec!["./dist/test/file.js"]),
exports_field: exports_field(json!({
"./foo/": {
"import": [
"./dist/",
"./src/"
],
"webpack": "./wp/"
},
".": "./main.js"
})),
request: "./foo/test/file.js",
condition_names: vec!["import", "webpack"],
},
TestCase {
name: "sample #1",
expect: Some(vec!["./src/test/file.js"]),
exports_field: exports_field(json!({
"./foo/": {
"import": [
"./src/"
],
"webpack": "./wp/"
},
".": "./main.js"
})),
request: "./foo/test/file.js",
condition_names: vec!["import", "webpack"],
},
TestCase {
name: "sample #1 (wildcard)",
expect: Some(vec!["./dist/test/file.js"]),
exports_field: exports_field(json!({
"./foo/*": {
"import": [
"./dist/*",
"./src/*"
],
"webpack": "./wp/*"
},
".": "./main.js"
})),
request: "./foo/test/file.js",
condition_names: vec!["import", "webpack"],
},
TestCase {
name: "sample #1 (wildcard)",
expect: Some(vec!["./src/test/file.js"]),
exports_field: exports_field(json!({
"./foo/*": {
"import": [
"./src/*"
],
"webpack": "./wp/*"
},
".": "./main.js"
})),
request: "./foo/test/file.js",
condition_names: vec!["import", "webpack"],
},
TestCase {
name: "sample #2",
expect: Some(vec!["./data/timezones/pdt.mjs"]),
exports_field: exports_field(json!({
"./timezones/": "./data/timezones/"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "sample #2 (wildcard)",
expect: Some(vec!["./data/timezones/pdt.mjs"]),
exports_field: exports_field(json!({
"./timezones/*": "./data/timezones/*"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "sample #3",
expect: Some(vec!["./data/timezones/timezones/pdt.mjs"]),
exports_field: exports_field(json!({
"./": "./data/timezones/"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "sample #3 (wildcard)",
expect: Some(vec!["./data/timezones/timezones/pdt.mjs"]),
exports_field: exports_field(json!({
"./*": "./data/timezones/*.mjs"
})),
request: "./timezones/pdt",
condition_names: vec![],
},
TestCase {
name: "sample #4",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./lib/": {
"browser": [
"./browser/"
]
},
"./dist/index.js": {
"node": "./index.js"
}
})),
request: "./dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "sample #4 (wildcard)",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./lib/*": {
"browser": [
"./browser/*"
]
},
"./dist/index.js": {
"node": "./index.js"
}
})),
request: "./dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "sample #5",
expect: Some(vec!["./browser/index.js"]),
exports_field: exports_field(json!({
"./lib/": {
"browser": [
"./browser/"
]
},
"./dist/index.js": {
"node": "./index.js",
"default": "./browser/index.js"
}
})),
request: "./dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "sample #5 (wildcard)",
expect: Some(vec!["./browser/index.js"]),
exports_field: exports_field(json!({
"./lib/*": {
"browser": [
"./browser/*"
]
},
"./dist/index.js": {
"node": "./index.js",
"default": "./browser/index.js"
}
})),
request: "./dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "sample #6",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./dist/a": "./dist/index.js"
})),
request: "./dist/aaa",
condition_names: vec![],
},
TestCase {
name: "sample #7",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./dist/a/a/": "./dist/index.js"
})),
request: "./dist/a/a",
condition_names: vec![],
},
TestCase {
name: "sample #7 (wildcard)",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./dist/a/a/*": "./dist/index.js"
})),
request: "./dist/a/a",
condition_names: vec![],
},
TestCase {
name: "sample #8",
expect: Some(vec![]),
exports_field: exports_field(json!({
".": "./index.js"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "sample #9",
expect: Some(vec!["./main.js"]),
exports_field: exports_field(json!({
"./index.js": "./main.js"
})),
request: "./index.js",
condition_names: vec![],
},
TestCase {
name: "sample #10",
expect: Some(vec!["./ok.js"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./#foo",
condition_names: vec![],
},
TestCase {
name: "sample #11",
expect: Some(vec!["./ok.js"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./bar#foo",
condition_names: vec![],
},
TestCase {
name: "sample #12",
expect: Some(vec!["./ok.js#abc"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./#zapp/ok.js#abc",
condition_names: vec![],
},
TestCase {
name: "sample #12",
expect: Some(vec!["./ok.js#abc"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./#zapp/ok.js#abc",
condition_names: vec![],
},
TestCase {
name: "sample #13",
expect: Some(vec!["./ok.js?abc"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./#zapp/ok.js?abc",
condition_names: vec![],
},
TestCase {
name: "sample #14",
expect: Some(vec!["./🎉.js"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./#zapp/🎉.js",
condition_names: vec![],
},
TestCase {
name: "sample #15",
expect: Some(vec!["./%F0%9F%8E%89.js"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./#zapp/%F0%9F%8E%89.js",
condition_names: vec![],
},
TestCase {
name: "sample #16",
expect: Some(vec!["./ok.js"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./🎉",
condition_names: vec![],
},
TestCase {
name: "sample #17",
expect: Some(vec!["./other.js"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./%F0%9F%8E%89",
condition_names: vec![],
},
TestCase {
name: "sample #18",
expect: Some(vec!["./ok.js"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./module",
condition_names: vec![],
},
TestCase {
name: "sample #19",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./module#foo",
condition_names: vec![],
},
TestCase {
name: "sample #20",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./zzz*"
})),
request: "./module?foo",
condition_names: vec![],
},
TestCase {
name: "sample #21",
expect: Some(vec!["./zizizi"]),
exports_field: exports_field(json!({
"./#foo": "./ok.js",
"./module": "./ok.js",
"./🎉": "./ok.js",
"./%F0%9F%8E%89": "./other.js",
"./bar#foo": "./ok.js",
"./#zapp/": "./",
"./#zipp*": "./z*z*z*"
})),
request: "./#zippi",
condition_names: vec![],
},
TestCase {
name: "sample #22",
expect: Some(vec!["./d?e?f"]),
exports_field: exports_field(json!({
"./a?b?c/": "./"
})),
request: "./a?b?c/d?e?f",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #1",
expect: Some(vec!["./dist/index.js"]),
exports_field: exports_field(json!({
".": "./dist/index.js"
})),
request: ".",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #2",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./": "./",
"./*": "./*",
"./dist/index.js": "./dist/index.js"
})),
request: ".",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #3",
expect: Some(vec!["./dist/a.js"]),
exports_field: exports_field(json!({
"./dist/": "./dist/",
"./dist/*": "./dist/*",
"./dist*": "./dist*",
"./dist/index.js": "./dist/a.js"
})),
request: "./dist/index.js",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #4",
expect: Some(vec!["./index.js"]),
exports_field: exports_field(json!({
"./": {
"browser": [
"./browser/"
]
},
"./*": {
"browser": [
"./browser/*"
]
},
"./dist/index.js": {
"browser": "./index.js"
}
})),
request: "./dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "Direct mapping #5",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./": {
"browser": [
"./browser/"
]
},
"./*": {
"browser": [
"./browser/*"
]
},
"./dist/index.js": {
"node": "./node.js"
}
})),
request: "./dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "Direct mapping #6",
expect: Some(vec!["./index.js"]),
exports_field: exports_field(json!({
".": {
"browser": "./index.js",
"node": "./src/node/index.js",
"default": "./src/index.js"
}
})),
request: ".",
condition_names: vec!["browser"],
},
TestCase {
name: "Direct mapping #7",
expect: Some(vec!["./src/index.js"]), exports_field: exports_field(json!({
".": {
"default": "./src/index.js",
"browser": "./index.js",
"node": "./src/node/index.js"
}
})),
request: ".",
condition_names: vec!["browser"],
},
TestCase {
name: "Direct mapping #8",
expect: Some(vec!["./src/index.js"]),
exports_field: exports_field(json!({
".": {
"browser": "./index.js",
"node": "./src/node/index.js",
"default": "./src/index.js"
}
})),
request: ".",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #9",
expect: Some(vec!["./index"]),
exports_field: exports_field(json!({
".": "./index"
})),
request: ".",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #10",
expect: Some(vec!["./index.js"]),
exports_field: exports_field(json!({
"./index": "./index.js"
})),
request: "./index",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #11",
expect: Some(vec!["./foo.js"]),
exports_field: exports_field(json!({
"./": "./",
"./*": "./*",
"./dist/index.js": "./dist/index.js"
})),
request: "./foo.js",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #12",
expect: Some(vec!["./foo/bar/baz.js"]),
exports_field: exports_field(json!({
"./": "./",
"./*": "./*",
"./dist/index.js": "./dist/index.js"
})),
request: "./foo/bar/baz.js",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #13",
expect: Some(vec!["./foo/bar/baz.js"]),
exports_field: exports_field(json!({
"./": "./",
"./dist/index.js": "./dist/index.js"
})),
request: "./foo/bar/baz.js",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #14",
expect: Some(vec!["./foo/bar/baz.js"]),
exports_field: exports_field(json!({
"./*": "./*",
"./dist/index.js": "./dist/index.js"
})),
request: "./foo/bar/baz.js",
condition_names: vec![],
},
TestCase {
name: "Direct and conditional mapping #1",
expect: Some(vec![]),
exports_field: exports_field(json!({
".": [{
"browser": "./browser.js"
}, {
"require": "./require.js"
}, {
"import": "./import.mjs"
}]
})),
request: ".",
condition_names: vec![],
},
TestCase {
name: "Direct and conditional mapping #2",
expect: Some(vec!["./import.mjs"]),
exports_field: exports_field(json!({
".": [{
"browser": "./browser.js"
}, {
"require": "./require.js"
}, {
"import": "./import.mjs"
}]
})),
request: ".",
condition_names: vec!["import"],
},
TestCase {
name: "Direct and conditional mapping #3",
expect: Some(vec!["./require.js"]),
exports_field: exports_field(json!({
".": [
{
"browser": "./browser.js"
},
{
"require": "./require.js"
},
{
"import": "./import.mjs"
}
]
})),
request: ".",
condition_names: vec!["import", "require"],
},
TestCase {
name: "Direct and conditional mapping #3",
expect: Some(vec!["./import.mjs"]),
exports_field: exports_field(json!({
".": [{
"browser": "./browser.js"
}, {
"import": "./import.mjs"
}]
})),
request: ".",
condition_names: vec!["import", "require"],
},
TestCase {
name: "Direct and conditional mapping #4",
expect: Some(vec!["./require.js"]),
exports_field: exports_field(json!({
".": [{
"browser": "./browser.js"
}, {
"require": [
"./require.js"
]
}, {
"import": [
"./import.mjs",
"./import.js"
]
}]
})),
request: ".",
condition_names: vec!["import", "require"],
},
TestCase {
name: "Direct and conditional mapping #4",
expect: Some(vec!["./import.mjs"]),
exports_field: exports_field(json!({
".": [
{
"browser": "./browser.js"
},
{
"import": [
"./import.mjs",
"./import.js"
]
}
]
})),
request: ".",
condition_names: vec!["import", "require"],
},
TestCase {
name: "Direct and conditional mapping #4",
expect: Some(vec!["./import.js"]),
exports_field: exports_field(json!({
".": [
{
"browser": "./browser.js"
},
{
"import": [
"./import.js"
]
}
]
})),
request: ".",
condition_names: vec!["import", "require"],
},
TestCase {
name: "mapping to a folder root #1",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./timezones": "./data/timezones/"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #2",
expect: None,
exports_field: exports_field(json!({
"./timezones/": "./data/timezones"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #3",
expect: Some(vec!["./data/timezones/pdt/index.mjs"]),
exports_field: exports_field(json!({
"./timezones/pdt/": "./data/timezones/pdt/"
})),
request: "./timezones/pdt/index.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #3 (wildcard)",
expect: Some(vec!["./data/timezones/pdt/index.mjs"]),
exports_field: exports_field(json!({
"./timezones/pdt/*": "./data/timezones/pdt/*"
})),
request: "./timezones/pdt/index.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #4",
expect: Some(vec!["./timezones/pdt.mjs"]),
exports_field: exports_field(json!({
"./": "./timezones/"
})),
request: "./pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #4 (wildcard)",
expect: Some(vec!["./timezones/pdt.mjs"]),
exports_field: exports_field(json!({
"./*": "./timezones/*"
})),
request: "./pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #5",
expect: Some(vec!["./timezones/pdt.mjs"]),
exports_field: exports_field(json!({
"./": "./"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #5 (wildcard)",
expect: Some(vec!["./timezones/pdt.mjs"]),
exports_field: exports_field(json!({
"./*": "./*"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #6",
expect: None,
exports_field: exports_field(json!({
"./": "."
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #6 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./*": "."
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #7",
expect: Some(vec![]),
exports_field: exports_field(json!({
".": "./"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #7 (wildcard)",
expect: Some(vec![]),
exports_field: exports_field(json!({
".": "./*"
})),
request: "./timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #1",
expect: Some(vec!["./lib/index.mjs"]),
exports_field: exports_field(json!({
"./": "./",
"./dist/": "./lib/"
})),
request: "./dist/index.mjs",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #1 (wildcard)",
expect: Some(vec!["./lib/index.mjs"]),
exports_field: exports_field(json!({
"./*": "./*",
"./dist/*": "./lib/*"
})),
request: "./dist/index.mjs",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #2",
expect: Some(vec!["./dist/utils/index.js"]),
exports_field: exports_field(json!({
"./dist/utils/": "./dist/utils/",
"./dist/": "./lib/"
})),
request: "./dist/utils/index.js",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #2 (wildcard)",
expect: Some(vec!["./dist/utils/index.js"]),
exports_field: exports_field(json!({
"./dist/utils/*": "./dist/utils/*",
"./dist/*": "./lib/*"
})),
request: "./dist/utils/index.js",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #3",
expect: Some(vec!["./dist/utils/index.js"]),
exports_field: exports_field(json!({
"./dist/utils/index.js": "./dist/utils/index.js",
"./dist/utils/": "./dist/utils/index.mjs",
"./dist/": "./lib/"
})),
request: "./dist/utils/index.js",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #3 (wildcard)",
expect: Some(vec!["./dist/utils/index.js"]),
exports_field: exports_field(json!({
"./dist/utils/index.js": "./dist/utils/index.js",
"./dist/utils/*": "./dist/utils/index.mjs",
"./dist/*": "./lib/*"
})),
request: "./dist/utils/index.js",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #4",
expect: Some(vec!["./lib/index.mjs"]),
exports_field: exports_field(json!({
"./": {
"browser": "./browser/"
},
"./dist/": "./lib/"
})),
request: "./dist/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "the longest matching path prefix is prioritized #4 (wildcard)",
expect: Some(vec!["./lib/index.mjs"]),
exports_field: exports_field(json!({
"./*": {
"browser": "./browser/*"
},
"./dist/*": "./lib/*"
})),
request: "./dist/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "conditional mapping folder #1",
expect: Some(vec!["./utils/index.js"]),
exports_field: exports_field(json!({
"./utils/": {
"browser": [
"lodash/",
"./utils/"
],
"node": [
"./utils-node/"
]
}
})),
request: "./utils/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "conditional mapping folder #1",
expect: Some(vec!["./utils/index.js"]),
exports_field: exports_field(json!({
"./utils/": {
"browser": [
"./utils/"
],
"node": [
"./utils-node/"
]
}
})),
request: "./utils/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "conditional mapping folder #1 (wildcard)",
expect: Some(vec!["./utils/index.js"]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": [
"lodash/*",
"./utils/*"
],
"node": [
"./utils-node/*"
]
}
})),
request: "./utils/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "conditional mapping folder #1 (wildcard)",
expect: Some(vec!["./utils/index.js"]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": [
"./utils/*"
],
"node": [
"./utils-node/*"
]
}
})),
request: "./utils/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "conditional mapping folder #2",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/": {
"webpack": "./wpk/",
"browser": [
"lodash/",
"./utils/"
],
"node": [
"./node/"
]
}
})),
request: "./utils/index.mjs",
condition_names: vec![],
},
TestCase {
name: "conditional mapping folder #2 (wildcard)",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/*": {
"webpack": "./wpk/*",
"browser": [
"lodash/*",
"./utils/*"
],
"node": [
"./node/*"
]
}
})),
request: "./utils/index.mjs",
condition_names: vec![],
},
TestCase {
name: "conditional mapping folder #3",
expect: Some(vec!["./wpk/index.mjs"]),
exports_field: exports_field(json!({
"./utils/": {
"webpack": "./wpk/",
"browser": [
"lodash/",
"./utils/"
],
"node": [
"./utils/"
]
}
})),
request: "./utils/index.mjs",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "conditional mapping folder #3 (wildcard)",
expect: Some(vec!["./wpk/index.mjs"]),
exports_field: exports_field(json!({
"./utils/*": {
"webpack": "./wpk/*",
"browser": [
"lodash/*",
"./utils/*"
],
"node": [
"./utils/*"
]
}
})),
request: "./utils/index.mjs",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "incorrect exports field #1",
expect: None,
exports_field: exports_field(json!({
"/utils/": "./a/"
})),
request: "./utils/index.mjs",
condition_names: vec![],
},
TestCase {
name: "incorrect exports field #2",
expect: None,
exports_field: exports_field(json!({
"./utils/": "/a/"
})),
request: "./utils/index.mjs",
condition_names: vec![],
},
TestCase {
name: "incorrect exports field #3",
expect: None,
exports_field: exports_field(json!({
"/utils/": {
"browser": "./a/",
"default": "./b/"
}
})),
request: "./utils/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect exports field #4",
expect: None,
exports_field: exports_field(json!({
"./utils/": {
"browser": "/a/",
"default": "/b/"
}
})),
request: "./utils/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect exports field #4 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./utils/*": {
"browser": "/a/",
"default": "/b/"
}
})),
request: "./utils/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect exports field #5",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/index": "./a/index.js"
})),
request: "./utils/index.mjs",
condition_names: vec![],
},
TestCase {
name: "incorrect exports field #6",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/index.mjs": "./a/index.js"
})),
request: "./utils/index",
condition_names: vec![],
},
TestCase {
name: "incorrect exports field #7",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/index": {
"browser": "./a/index.js",
"default": "./b/index.js"
}
})),
request: "./utils/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect exports field #8",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/index.mjs": {
"browser": "./a/index.js",
"default": "./b/index.js"
}
})),
request: "./utils/index",
condition_names: vec!["browser"],
},
TestCase {
name: "backtracking package base #1",
expect: Some(vec!["./dist/index"]),
exports_field: exports_field(json!({
"./../../utils/": "./dist/"
})),
request: "./../../utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #1 (wildcard)",
expect: Some(vec!["./dist/index"]),
exports_field: exports_field(json!({
"./../../utils/*": "./dist/*"
})),
request: "./../../utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #2",
expect: None,
exports_field: exports_field(json!({
"../../utils/": "./dist/"
})),
request: "../../utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #2 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"../../utils/*": "./dist/*"
})),
request: "../../utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #3",
expect: None,
exports_field: exports_field(json!({
"./utils/": "../src/"
})),
request: "./utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #3 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./utils/*": "../src/*"
})),
request: "./utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #6",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/../utils/index": "./src/../index.js"
})),
request: "./utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #7",
expect: None,
exports_field: exports_field(json!({
"./utils/": {
"browser": "../this/"
}
})),
request: "./utils/index",
condition_names: vec!["browser"],
},
TestCase {
name: "backtracking package base #7",
expect: None,
exports_field: exports_field(json!({
"./utils/*": {
"browser": "../this/*"
}
})),
request: "./utils/index",
condition_names: vec!["browser"],
},
TestCase {
name: "backtracking package base #8",
expect: None,
exports_field: exports_field(json!({
"./utils/": {
"browser": "./utils/../"
}
})),
request: "./utils/index",
condition_names: vec!["browser"],
},
TestCase {
name: "backtracking package base #8 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./utils/*": {
"browser": "./utils/../*"
}
})),
request: "./utils/index",
condition_names: vec!["browser"],
},
TestCase {
name: "backtracking package base #9",
expect: Some(vec!["./dist/index"]),
exports_field: exports_field(json!({
"./": "./src/../../",
"./dist/": "./dist/"
})),
request: "./dist/index",
condition_names: vec!["browser"],
},
TestCase {
name: "backtracking package base #9 (wildcard)",
expect: Some(vec!["./dist/index"]),
exports_field: exports_field(json!({
"./*": "./src/../../*",
"./dist/*": "./dist/*"
})),
request: "./dist/index",
condition_names: vec!["browser"],
},
TestCase {
name: "backtracking target folder #1",
expect: None,
exports_field: exports_field(json!({
"./utils/": "./dist/"
})),
request: "./utils/timezone/../../index",
condition_names: vec![],
},
TestCase {
name: "backtracking target folder #1 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./utils/*": "./dist/*"
})),
request: "./utils/timezone/../../index",
condition_names: vec![],
},
TestCase {
name: "backtracking target folder #2",
expect: None,
exports_field: exports_field(json!({
"./utils/": "./dist/"
})),
request: "./utils/timezone/../index",
condition_names: vec![],
},
TestCase {
name: "backtracking target folder #2 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./utils/*": "./dist/*"
})),
request: "./utils/timezone/../index",
condition_names: vec![],
},
TestCase {
name: "backtracking target folder #3",
expect: None,
exports_field: exports_field(json!({
"./utils/": "./dist/target/"
})),
request: "./utils/../../index",
condition_names: vec![],
},
TestCase {
name: "backtracking target folder #3 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./utils/*": "./dist/target/*"
})),
request: "./utils/../../index",
condition_names: vec![],
},
TestCase {
name: "nested node_modules path #1",
expect: None,
exports_field: exports_field(json!({
"./utils/": {
"browser": "./node_modules/"
}
})),
request: "./utils/lodash/dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "nested node_modules path #1 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./utils/*": {
"browser": "./node_modules/*"
}
})),
request: "./utils/lodash/dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "nested node_modules path #2",
expect: None,
exports_field: exports_field(json!({
"./utils/": "./utils/../node_modules/"
})),
request: "./utils/lodash/dist/index.js",
condition_names: vec![],
},
TestCase {
name: "nested node_modules path #2 (wildcard)",
expect: None,
exports_field: exports_field(json!({
"./utils/*": "./utils/../node_modules/*"
})),
request: "./utils/lodash/dist/index.js",
condition_names: vec![],
},
TestCase {
name: "nested mapping #1",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/": {
"browser": {
"webpack": "./",
"default": {
"node": "./node/"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "nested mapping #1 (wildcard)",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": {
"webpack": "./*",
"default": {
"node": "./node/*"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "nested mapping #2",
expect: Some(vec!["./index.js"]),
exports_field: exports_field(json!({
"./utils/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": "./node/"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "nested mapping #2",
expect: Some(vec!["./node/index.js"]),
exports_field: exports_field(json!({
"./utils/": {
"browser": {
"webpack": [
"./node/"
],
"default": {
"node": "./node/"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "nested mapping #2 (wildcard)",
expect: Some(vec!["./index.js"]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": {
"webpack": [
"./*",
"./node/*"
],
"default": {
"node": "./node/*"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "nested mapping #2 (wildcard)",
expect: Some(vec!["./node/index.js"]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": {
"webpack": [
"./node/*"
],
"default": {
"node": "./node/*"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "nested mapping #3",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": "./node/"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["webpack"],
},
TestCase {
name: "nested mapping #3 (wildcard)",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": {
"webpack": [
"./*",
"./node/*"
],
"default": {
"node": "./node/*"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["webpack"],
},
TestCase {
name: "nested mapping #4",
expect: Some(vec!["./node/index.js"]),
exports_field: exports_field(json!({
"./utils/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": "./node/"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["node", "browser"],
},
TestCase {
name: "nested mapping #4 (wildcard)",
expect: Some(vec!["./node/index.js"]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": {
"webpack": [
"./*",
"./node/*"
],
"default": {
"node": "./node/*"
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["node", "browser"],
},
TestCase {
name: "nested mapping #5",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": {
"webpack": [
"./wpck/"
]
}
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "node"],
},
TestCase {
name: "nested mapping #5 (wildcard)",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": {
"webpack": [
"./*",
"./node/*"
],
"default": {
"node": {
"webpack": [
"./wpck/*"
]
}
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "node"],
},
TestCase {
name: "nested mapping #6",
expect: Some(vec!["./index.js"]),
exports_field: exports_field(json!({
"./utils/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": {
"webpack": [
"./wpck/"
]
}
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "node", "webpack"],
},
TestCase {
name: "nested mapping #6",
expect: Some(vec!["./node/index.js"]),
exports_field: exports_field(json!({
"./utils/": {
"browser": {
"webpack": [
"./node/"
],
"default": {
"node": {
"webpack": [
"./wpck/"
]
}
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "node", "webpack"],
},
TestCase {
name: "nested mapping #6 (wildcard)",
expect: Some(vec!["./index.js"]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": {
"webpack": [
"./*",
"./node/*"
],
"default": {
"node": {
"webpack": [
"./wpck/*"
]
}
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "node", "webpack"],
},
TestCase {
name: "nested mapping #6 (wildcard)",
expect: Some(vec!["./node/index.js"]),
exports_field: exports_field(json!({
"./utils/*": {
"browser": {
"webpack": [
"./node/*"
],
"default": {
"node": {
"webpack": [
"./wpck/*"
]
}
}
}
}
})),
request: "./utils/index.js",
condition_names: vec!["browser", "node", "webpack"],
},
TestCase {
name: "nested mapping #7",
expect: Some(vec!["./y.js"]),
exports_field: exports_field(json!({
"./a.js": {
"abc": {
"def": "./x.js"
},
"ghi": "./y.js"
}
})),
request: "./a.js",
condition_names: vec!["abc", "ghi"],
},
TestCase {
name: "nested mapping #8",
expect: Some(vec![]),
exports_field: exports_field(json!({
"./a.js": {
"abc": {
"def": "./x.js",
"default": []
},
"ghi": "./y.js"
}
})),
request: "./a.js",
condition_names: vec!["abc", "ghi"],
},
TestCase {
name: "syntax sugar #1",
expect: Some(vec!["./main.js"]),
exports_field: exports_field(json!("./main.js")),
request: ".",
condition_names: vec![],
},
TestCase {
name: "syntax sugar #2",
expect: Some(vec![]),
exports_field: exports_field(json!("./main.js")),
request: "./lib.js",
condition_names: vec![],
},
TestCase {
name: "syntax sugar #3",
expect: Some(vec!["./a.js"]),
exports_field: exports_field(json!(["./a.js", "./b.js"])),
request: ".",
condition_names: vec![],
},
TestCase {
name: "syntax sugar #3",
expect: Some(vec!["./b.js"]),
exports_field: exports_field(json!(["./b.js"])),
request: ".",
condition_names: vec![],
},
TestCase {
name: "syntax sugar #4",
expect: Some(vec![]),
exports_field: exports_field(json!(["./a.js", "./b.js"])),
request: "./lib.js",
condition_names: vec![],
},
TestCase {
name: "syntax sugar #5",
expect: Some(vec!["./index.js"]),
exports_field: exports_field(json!({
"browser": {
"default": "./index.js"
}
})),
request: ".",
condition_names: vec!["browser"],
},
TestCase {
name: "syntax sugar #6",
expect: Some(vec![]),
exports_field: exports_field(json!({
"browser": {
"default": "./index.js"
}
})),
request: "./lib.js",
condition_names: vec!["browser"],
},
TestCase {
name: "syntax sugar #7",
expect: None,
exports_field: exports_field(json!({
"./node": "./node.js",
"browser": {
"default": "./index.js"
}
})),
request: ".",
condition_names: vec!["browser"],
},
TestCase {
name: "syntax sugar #8",
expect: None,
exports_field: exports_field(json!({
"browser": {
"default": "./index.js"
},
"./node": "./node.js"
})),
request: ".",
condition_names: vec!["browser"],
},
TestCase {
name: "wildcard longest #1",
expect: Some(vec!["./abc/d"]),
exports_field: exports_field(json!({
"./ab*": "./ab/*",
"./abc*": "./abc/*",
"./a*": "./a/*"
})),
request: "./abcd",
condition_names: vec!["browser"],
},
TestCase {
name: "wildcard longest #2",
expect: Some(vec!["./abc/d/e"]),
exports_field: exports_field(json!({
"./ab*": "./ab/*",
"./abc*": "./abc/*",
"./a*": "./a/*"
})),
request: "./abcd/e",
condition_names: vec!["browser"],
},
TestCase {
name: "wildcard longest #3",
expect: Some(vec!["./abc/d"]),
exports_field: exports_field(json!({
"./x/ab*": "./ab/*",
"./x/abc*": "./abc/*",
"./x/a*": "./a/*"
})),
request: "./x/abcd",
condition_names: vec!["browser"],
},
TestCase {
name: "wildcard longest #4",
expect: Some(vec!["./abc/d/e"]),
exports_field: exports_field(json!({
"./x/ab*": "./ab/*",
"./x/abc*": "./abc/*",
"./x/a*": "./a/*"
})),
request: "./x/abcd/e",
condition_names: vec!["browser"],
},
TestCase {
name: "path tree edge case #1",
expect: Some(vec!["./A/b/d.js"]),
exports_field: exports_field(json!({
"./a/": "./A/",
"./a/b/c": "./c.js"
})),
request: "./a/b/d.js",
condition_names: vec![],
},
TestCase {
name: "path tree edge case #1 (wildcard)",
expect: Some(vec!["./A/b/d.js"]),
exports_field: exports_field(json!({
"./a/*": "./A/*",
"./a/b/c": "./c.js"
})),
request: "./a/b/d.js",
condition_names: vec![],
},
TestCase {
name: "path tree edge case #2",
expect: Some(vec!["./A/c.js"]),
exports_field: exports_field(json!({
"./a/": "./A/",
"./a/b": "./b.js"
})),
request: "./a/c.js",
condition_names: vec![],
},
TestCase {
name: "path tree edge case #2 (wildcard)",
expect: Some(vec!["./A/c.js"]),
exports_field: exports_field(json!({
"./a/*": "./A/*",
"./a/b": "./b.js"
})),
request: "./a/c.js",
condition_names: vec![],
},
TestCase {
name: "path tree edge case #3",
expect: Some(vec!["./A/b/d/c.js"]),
exports_field: exports_field(json!({
"./a/": "./A/",
"./a/b/c/d": "./c.js"
})),
request: "./a/b/d/c.js",
condition_names: vec![],
},
TestCase {
name: "path tree edge case #3 (wildcard)",
expect: Some(vec!["./A/b/d/c.js"]),
exports_field: exports_field(json!({
"./a/*": "./A/*",
"./a/b/c/d": "./c.js"
})),
request: "./a/b/d/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #1",
expect: Some(vec!["./A/b.js"]),
exports_field: exports_field(json!({
"./a/*.js": "./A/*.js"
})),
request: "./a/b.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #2",
expect: Some(vec!["./A/b/c.js"]),
exports_field: exports_field(json!({
"./a/*.js": "./A/*.js"
})),
request: "./a/b/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #3",
expect: Some(vec!["./A/b/c.js"]),
exports_field: exports_field(json!({
"./a/*/c.js": "./A/*/c.js"
})),
request: "./a/b/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #4",
expect: Some(vec!["./A/b/b.js"]),
exports_field: exports_field(json!({
"./a/*/c.js": "./A/*/*.js"
})),
request: "./a/b/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #5",
expect: Some(vec!["./browser/index.js"]),
exports_field: exports_field(json!({
"./lib/*": {
"browser": [
"./browser/*"
]
},
"./dist/*.js": {
"node": "./*.js",
"default": "./browser/*.js"
}
})),
request: "./dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "wildcard pattern #5",
expect: Some(vec!["./browser/index.js"]),
exports_field: exports_field(json!({
"./lib/*": {
"browser": [
"./browser/*"
]
},
"./dist/*.js": {
"node": "./*.js",
"default": "./browser/*.js"
}
})),
request: "./lib/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "wildcard pattern #6",
expect: Some(vec!["./browser/foo/bar.js"]),
exports_field: exports_field(json!({
"./lib/*/bar.js": {
"browser": [
"./browser/*/bar.js"
]
},
"./dist/*/bar.js": {
"node": "./*.js",
"default": "./browser/*.js"
}
})),
request: "./lib/foo/bar.js",
condition_names: vec!["browser"],
},
TestCase {
name: "wildcard pattern #6",
expect: Some(vec!["./browser/foo.js"]),
exports_field: exports_field(json!({
"./lib/*/bar.js": {
"browser": [
"./browser/*/bar.js"
]
},
"./dist/*/bar.js": {
"node": "./*.js",
"default": "./browser/*.js"
}
})),
request: "./dist/foo/bar.js",
condition_names: vec!["browser"],
},
TestCase {
name: "wildcard pattern #7",
expect: Some(vec!["./browser/foo/default.js"]),
exports_field: exports_field(json!({
"./lib/*/bar.js": {
"browser": [
"./browser/*/bar.js"
]
},
"./dist/*/bar.js": {
"node": "./*.js",
"default": "./browser/*/default.js"
}
})),
request: "./dist/foo/bar.js",
condition_names: vec!["default"],
},
TestCase {
name: "wildcard pattern #8",
expect: Some(vec!["./A/b/b/b.js"]),
exports_field: exports_field(json!({
"./a/*/c.js": "./A/*/*/*.js"
})),
request: "./a/b/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #9",
expect: Some(vec!["./A/b/b/b.js"]),
exports_field: exports_field(json!({
"./a/*/c.js": [
"./A/*/*/*.js",
"./B/*/*/*.js"
]
})),
request: "./a/b/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #9",
expect: Some(vec!["./B/b/b/b.js"]),
exports_field: exports_field(json!({
"./a/*/c.js": [
"./B/*/*/*.js"
]
})),
request: "./a/b/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #10",
expect: Some(vec!["./A/b/b/b.js"]),
exports_field: exports_field(json!({
"./a/foo-*/c.js": "./A/*/*/*.js"
})),
request: "./a/foo-b/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #11",
expect: Some(vec!["./A/b/b/b.js"]),
exports_field: exports_field(json!({
"./a/*-foo/c.js": "./A/*/*/*.js"
})),
request: "./a/b-foo/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #12",
expect: Some(vec!["./A/b/b/b.js"]),
exports_field: exports_field(json!({
"./a/foo-*-foo/c.js": "./A/*/*/*.js"
})),
request: "./a/foo-b-foo/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #13",
expect: Some(vec!["./A/b/c/d.js"]),
exports_field: exports_field(json!({
"./a/foo-*-foo/c.js": "./A/b/c/d.js"
})),
request: "./a/foo-b-foo/c.js",
condition_names: vec![],
},
TestCase {
name: "wildcard pattern #14",
expect: Some(vec!["./A/b/c/*.js"]),
exports_field: exports_field(json!({
"./a/foo-foo/c.js": "./A/b/c/*.js"
})),
request: "./a/foo-foo/c.js",
condition_names: vec![],
},
];
for case in test_cases {
let resolved = Resolver::new(ResolveOptions {
condition_names: case
.condition_names
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>(),
..ResolveOptions::default()
})
.package_exports_resolve(
Path::new(""),
case.request,
&case.exports_field,
&mut Ctx::default(),
)
.await
.map(|p| p.map(|p| p.to_path_buf()));
if let Some(expect) = case.expect {
if expect.is_empty() {
assert!(
matches!(resolved, Err(ResolveError::PackagePathNotExported(_, _))),
"{} {:?}",
&case.name,
&resolved
);
} else {
for expect in expect {
assert_eq!(
resolved,
Ok(Some(Path::new(expect).normalize())),
"{}",
&case.name
);
}
}
} else {
assert!(resolved.is_err(), "{} {resolved:?}", &case.name);
}
}
}