use std::path::Path;
use simd_json::{json, prelude::*};
use crate::{package_json::JSONValue, Ctx, PathUtil, ResolveError, ResolveOptions, Resolver};
#[tokio::test]
async fn test_simple() {
let f = super::fixture().join("imports-field");
let f2 = super::fixture().join("imports-exports-wildcard/node_modules/m/");
let resolver = Resolver::new(ResolveOptions {
extensions: vec![".js".into()],
main_files: vec!["index.js".into()],
condition_names: vec!["webpack".into()],
..ResolveOptions::default()
});
#[rustfmt::skip]
let pass = [
("should resolve using imports field instead of self-referencing", f.clone(), "#imports-field", f.join("b.js")),
("should resolve using imports field instead of self-referencing for a subpath", f.join("dir"), "#imports-field", f.join("b.js")),
("should resolve package #1", f.clone(), "#a/dist/main.js", f.join("node_modules/a/lib/lib2/main.js")),
("should resolve package #3", f.clone(), "#ccc/index.js", f.join("node_modules/c/index.js")),
("should resolve package #4", f.clone(), "#c", f.join("node_modules/c/index.js")),
("should resolve with wildcard pattern", f2.clone(), "#internal/i.js", f2.join("src/internal/i.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}");
}
#[rustfmt::skip]
let fail = [
("should disallow resolve out of package scope", f.clone(), "#b", ResolveError::InvalidPackageTarget("../b.js".to_string(), "#b".to_string(), f.join("package.json"))),
("should resolve package #2", f.clone(), "#a", ResolveError::PackageImportNotDefined("#a".to_string(), f.join("package.json"))),
];
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 shared_resolvers() {
let f = super::fixture().join("imports-field");
let resolver1 = Resolver::new(ResolveOptions {
extensions: vec![".js".into()],
main_files: vec!["index.js".into()],
imports_fields: vec![vec!["imports".into()]],
condition_names: vec!["webpack".into()],
..ResolveOptions::default()
});
let resolved_path = resolver1
.resolve(&f, "#imports-field")
.await
.map(|r| r.full_path());
assert_eq!(resolved_path, Ok(f.join("b.js")));
let resolver2 = resolver1.clone_with_options(ResolveOptions {
imports_fields: vec![vec!["other".into(), "imports".into()]],
..ResolveOptions::default()
});
let resolved_path = resolver2.resolve(&f, "#b").await.map(|r| r.full_path());
assert_eq!(resolved_path, Ok(f.join("a.js")));
}
struct TestCase {
name: &'static str,
expect: Option<Vec<&'static str>>,
imports_field: JSONValue<'static>,
request: &'static str,
condition_names: Vec<&'static str>,
}
#[allow(clippy::needless_pass_by_value)]
fn imports_field(value: simd_json::value::OwnedValue) -> JSONValue<'static> {
value.into()
}
#[tokio::test]
async fn test_cases() {
let test_cases = [
TestCase {
name: "sample #1",
expect: Some(vec!["./dist/test/file.js"]),
imports_field: imports_field(json!({
"#abc/": {
"import": [
"./dist/",
"./src/"
],
"webpack": "./wp/"
},
"#abc": "./main.js"
})),
request: "#abc/test/file.js",
condition_names: vec!["import", "webpack"],
},
TestCase {
name: "sample #1",
expect: Some(vec!["./src/test/file.js"]),
imports_field: imports_field(json!({
"#abc/": {
"import": [
"./src/"
],
"webpack": "./wp/"
},
"#abc": "./main.js"
})),
request: "#abc/test/file.js",
condition_names: vec!["import", "webpack"],
},
TestCase {
name: "sample #2",
expect: Some(vec!["./data/timezones/pdt.mjs"]),
imports_field: imports_field(json!({
"#1/timezones/": "./data/timezones/"
})),
request: "#1/timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "sample #3",
expect: Some(vec!["./data/timezones/timezones/pdt.mjs"]),
imports_field: imports_field(json!({
"#aaa/": "./data/timezones/",
"#a/": "./data/timezones/"
})),
request: "#a/timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "sample #4",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/lib/": {
"browser": [
"./browser/"
]
},
"#a/dist/index.js": {
"node": "./index.js"
}
})),
request: "#a/dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "sample #5",
expect: Some(vec!["./browser/index.js"]),
imports_field: imports_field(json!({
"#a/lib/": {
"browser": [
"./browser/"
]
},
"#a/dist/index.js": {
"node": "./index.js",
"default": "./browser/index.js"
}
})),
request: "#a/dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "sample #6",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/dist/a": "./dist/index.js"
})),
request: "#a/dist/aaa",
condition_names: vec![],
},
TestCase {
name: "sample #7",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/a/a/": "./dist/index.js"
})),
request: "#a/a/a",
condition_names: vec![],
},
TestCase {
name: "sample #8",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a": "./index.js"
})),
request: "#a/timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "sample #9",
expect: Some(vec!["./main.js"]),
imports_field: imports_field(json!({
"#a/index.js": "./main.js"
})),
request: "#a/index.js",
condition_names: vec![],
},
TestCase {
name: "sample #10",
expect: Some(vec!["./ok.js"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/#foo",
condition_names: vec![],
},
TestCase {
name: "sample #11",
expect: Some(vec!["./ok.js"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/bar#foo",
condition_names: vec![],
},
TestCase {
name: "sample #12",
expect: Some(vec!["./ok.js#abc"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/#zapp/ok.js#abc",
condition_names: vec![],
},
TestCase {
name: "sample #13",
expect: Some(vec!["./ok.js?abc"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/#zapp/ok.js?abc",
condition_names: vec![],
},
TestCase {
name: "sample #14",
expect: Some(vec!["./🎉.js"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/#zapp/🎉.js",
condition_names: vec![],
},
TestCase {
name: "sample #15",
expect: Some(vec!["./%F0%9F%8E%89.js"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/#zapp/%F0%9F%8E%89.js",
condition_names: vec![],
},
TestCase {
name: "sample #16",
expect: Some(vec!["./ok.js"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/🎉",
condition_names: vec![],
},
TestCase {
name: "sample #17",
expect: Some(vec!["./other.js"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/%F0%9F%8E%89",
condition_names: vec![],
},
TestCase {
name: "sample #18",
expect: Some(vec!["./ok.js"]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/module",
condition_names: vec![],
},
TestCase {
name: "sample #19",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/module#foo",
condition_names: vec![],
},
TestCase {
name: "sample #20",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/#foo": "./ok.js",
"#a/module": "./ok.js",
"#a/🎉": "./ok.js",
"#a/%F0%9F%8E%89": "./other.js",
"#a/bar#foo": "./ok.js",
"#a/#zapp/": "./"
})),
request: "#a/module?foo",
condition_names: vec![],
},
TestCase {
name: "sample #21",
expect: Some(vec!["./d?e?f"]),
imports_field: imports_field(json!({
"#a/a?b?c/": "./"
})),
request: "#a/a?b?c/d?e?f",
condition_names: vec![],
},
TestCase {
name: "sample #22",
expect: None,
imports_field: imports_field(json!({
"#a/": "/user/a/"
})),
request: "#a/index",
condition_names: vec![],
},
TestCase {
name: "path tree edge case #1",
expect: Some(vec!["./A/b/d.js"]),
imports_field: imports_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"]),
imports_field: imports_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/c/d.js"]),
imports_field: imports_field(json!({
"#a/": "./A/",
"#a/b/c/d": "./c.js"
})),
request: "#a/b/c/d.js",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #1",
expect: Some(vec!["./dist/index.js"]),
imports_field: imports_field(json!({
"#a": "./dist/index.js"
})),
request: "#a",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #2",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": "./"
})),
request: "#a",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #3",
expect: Some(vec!["./dist/a.js"]),
imports_field: imports_field(json!({
"#a/": "./dist/",
"#a/index.js": "./dist/a.js"
})),
request: "#a/index.js",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #4",
expect: Some(vec!["./index.js"]),
imports_field: imports_field(json!({
"#a/": {
"browser": [
"./browser/"
]
},
"#a/index.js": {
"browser": "./index.js"
}
})),
request: "#a/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "Direct mapping #5",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"browser": [
"./browser/"
]
},
"#a/index.js": {
"node": "./node.js"
}
})),
request: "#a/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "Direct mapping #6",
expect: Some(vec!["./index.js"]),
imports_field: imports_field(json!({
"#a": {
"browser": "./index.js",
"node": "./src/node/index.js",
"default": "./src/index.js"
}
})),
request: "#a",
condition_names: vec!["browser"],
},
TestCase {
name: "Direct mapping #7",
expect: Some(vec!["./src/index.js"]), imports_field: imports_field(json!({
"#a": {
"default": "./src/index.js",
"browser": "./index.js",
"node": "./src/node/index.js"
}
})),
request: "#a",
condition_names: vec!["browser"],
},
TestCase {
name: "Direct mapping #8",
expect: Some(vec!["./src/index.js"]),
imports_field: imports_field(json!({
"#a": {
"browser": "./index.js",
"node": "./src/node/index.js",
"default": "./src/index.js"
}
})),
request: "#a",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #9",
expect: Some(vec!["./index"]),
imports_field: imports_field(json!({
"#a": "./index"
})),
request: "#a",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #10",
expect: Some(vec!["./index.js"]),
imports_field: imports_field(json!({
"#a/index": "./index.js"
})),
request: "#a/index",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #11",
expect: None,
imports_field: imports_field(json!({
"#a": "b"
})),
request: "#a",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #12",
expect: None,
imports_field: imports_field(json!({
"#a/": "b/"
})),
request: "#a/index",
condition_names: vec![],
},
TestCase {
name: "Direct mapping #13",
expect: None,
imports_field: imports_field(json!({
"#a?q=a#hashishere": "b#anotherhashishere"
})),
request: "#a?q=a#hashishere",
condition_names: vec![],
},
TestCase {
name: "Direct and conditional mapping #1",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a": [
{
"browser": "./browser.js"
},
{
"require": "./require.js"
},
{
"import": "./import.mjs"
}
]
})),
request: "#a",
condition_names: vec![],
},
TestCase {
name: "Direct and conditional mapping #2",
expect: Some(vec!["./import.mjs"]),
imports_field: imports_field(json!({
"#a": [
{
"browser": "./browser.js"
},
{
"require": "./require.js"
},
{
"import": "./import.mjs"
}
]
})),
request: "#a",
condition_names: vec!["import"],
},
TestCase {
name: "Direct and conditional mapping #3",
expect: Some(vec!["./require.js"]),
imports_field: imports_field(json!({
"#a": [
{
"browser": "./browser.js"
},
{
"require": "./require.js"
},
{
"import": "./import.mjs"
}
]
})),
request: "#a",
condition_names: vec!["import", "require"],
},
TestCase {
name: "Direct and conditional mapping #3",
expect: Some(vec!["./import.mjs"]),
imports_field: imports_field(json!({
"#a": [
{
"browser": "./browser.js"
},
{
"import": "./import.mjs"
}
]
})),
request: "#a",
condition_names: vec!["import", "require"],
},
TestCase {
name: "Direct and conditional mapping #4",
expect: Some(vec!["./require.js"]),
imports_field: imports_field(json!({
"#a": [
{
"browser": "./browser.js"
},
{
"require": [
"./require.js"
]
},
{
"import": [
"./import.mjs",
"#b/import.js"
]
}
]
})),
request: "#a",
condition_names: vec!["import", "require"],
},
TestCase {
name: "Direct and conditional mapping #4",
expect: Some(vec!["./import.mjs"]),
imports_field: imports_field(json!({
"#a": [
{
"browser": "./browser.js"
},
{
"import": [
"./import.mjs",
"#b/import.js"
]
}
]
})),
request: "#a",
condition_names: vec!["import", "require"],
},
TestCase {
name: "Direct and conditional mapping #4",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a": [
{
"browser": "./browser.js"
},
{
"import": [
"#b/import.js"
]
}
]
})),
request: "#a",
condition_names: vec!["import", "require"],
},
TestCase {
name: "mapping to a folder root #1",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#timezones": "./data/timezones/"
})),
request: "#timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #2",
expect: None,
imports_field: imports_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"]),
imports_field: imports_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"]),
imports_field: imports_field(json!({
"#a/": "./timezones/"
})),
request: "#a/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #5",
expect: Some(vec!["./timezones/pdt.mjs"]),
imports_field: imports_field(json!({
"#a/": "./"
})),
request: "#a/timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #6",
expect: None,
imports_field: imports_field(json!({
"#a/": "."
})),
request: "#a/timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "mapping to a folder root #7",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a": "./"
})),
request: "#a/timezones/pdt.mjs",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #1",
expect: Some(vec!["./lib/index.mjs"]),
imports_field: imports_field(json!({
"#a/": "./",
"#a/dist/": "./lib/"
})),
request: "#a/dist/index.mjs",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #2",
expect: Some(vec!["./dist/utils/index.js"]),
imports_field: imports_field(json!({
"#a/dist/utils/": "./dist/utils/",
"#a/dist/": "./lib/"
})),
request: "#a/dist/utils/index.js",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #3",
expect: Some(vec!["./dist/utils/index.js"]),
imports_field: imports_field(json!({
"#a/dist/utils/index.js": "./dist/utils/index.js",
"#a/dist/utils/": "./dist/utils/index.mjs",
"#a/dist/": "./lib/"
})),
request: "#a/dist/utils/index.js",
condition_names: vec![],
},
TestCase {
name: "the longest matching path prefix is prioritized #4",
expect: Some(vec!["./lib/index.mjs"]),
imports_field: imports_field(json!({
"#a/": {
"browser": "./browser/"
},
"#a/dist/": "./lib/"
})),
request: "#a/dist/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "conditional mapping folder #1",
expect: Some(vec!["./utils/index.js"]),
imports_field: imports_field(json!({
"#a/": {
"browser": [
"lodash/",
"./utils/"
],
"node": [
"./utils-node/"
]
}
})),
request: "#a/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "conditional mapping folder #1",
expect: Some(vec!["./utils/index.js"]),
imports_field: imports_field(json!({
"#a/": {
"browser": [
"./utils/"
],
"node": [
"./utils-node/"
]
}
})),
request: "#a/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "conditional mapping folder #2",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"webpack": "./wpk/",
"browser": [
"lodash/",
"./utils/"
],
"node": [
"./node/"
]
}
})),
request: "#a/index.mjs",
condition_names: vec![],
},
TestCase {
name: "conditional mapping folder #3",
expect: Some(vec!["./wpk/index.mjs"]),
imports_field: imports_field(json!({
"#a/": {
"webpack": "./wpk/",
"browser": [
"lodash/",
"./utils/"
],
"node": [
"./utils/"
]
}
})),
request: "#a/index.mjs",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "incorrect exports field #1",
expect: Some(vec![]),
imports_field: imports_field(json!({
"/utils/": "./a/"
})),
request: "#a/index.mjs",
condition_names: vec![],
},
TestCase {
name: "incorrect exports field #2",
expect: Some(vec![]),
imports_field: imports_field(json!({
"/utils/": {
"browser": "./a/",
"default": "./b/"
}
})),
request: "#a/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect exports field #3",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/index": "./a/index.js"
})),
request: "#a/index.mjs",
condition_names: vec![],
},
TestCase {
name: "incorrect exports field #4",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/index.mjs": "./a/index.js"
})),
request: "#a/index",
condition_names: vec![],
},
TestCase {
name: "incorrect exports field #5",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/index": {
"browser": "./a/index.js",
"default": "./b/index.js"
}
})),
request: "#a/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect exports field #6",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/index.mjs": {
"browser": "./a/index.js",
"default": "./b/index.js"
}
})),
request: "#a/index",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect request #1",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": "./a/"
})),
request: "/utils/index.mjs",
condition_names: vec![],
},
TestCase {
name: "incorrect request #2",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"browser": "./a/",
"default": "./b/"
}
})),
request: "./utils/index.mjs",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect request #3",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"browser": "./a/",
"default": "./b/"
}
})),
request: "#",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect request #4",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"browser": "./a/",
"default": "./b/"
}
})),
request: "#/",
condition_names: vec!["browser"],
},
TestCase {
name: "incorrect request #5",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"browser": "./a/",
"default": "./b/"
}
})),
request: "#a/",
condition_names: vec!["browser"],
},
TestCase {
name: "backtracking package base #1",
expect: Some(vec!["dist/index"]),
imports_field: imports_field(json!({
"#a/../../utils/": "./dist/"
})),
request: "#a/../../utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #2",
expect: None,
imports_field: imports_field(json!({
"#a/": "./dist/"
})),
request: "#a/../../utils/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #3",
expect: None,
imports_field: imports_field(json!({
"#a/": "../src/"
})),
request: "#a/index",
condition_names: vec![],
},
TestCase {
name: "backtracking package base #4",
expect: None,
imports_field: imports_field(json!({
"#a/": {
"browser": "./utils/../../../"
}
})),
request: "#a/index",
condition_names: vec!["browser"],
},
TestCase {
name: "nested node_modules path #1",
expect: None,
imports_field: imports_field(json!({
"#a/": {
"browser": "moment/node_modules/"
}
})),
request: "#a/lodash/dist/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "nested node_modules path #2",
expect: None,
imports_field: imports_field(json!({
"#a/": "../node_modules/"
})),
request: "#a/lodash/dist/index.js",
condition_names: vec![],
},
TestCase {
name: "nested mapping #1",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"browser": {
"webpack": "./",
"default": {
"node": "./node/"
}
}
}
})),
request: "#a/index.js",
condition_names: vec!["browser"],
},
TestCase {
name: "nested mapping #2",
expect: Some(vec!["./index.js"]),
imports_field: imports_field(json!({
"#a/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": "./node/"
}
}
}
})),
request: "#a/index.js",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "nested mapping #2",
expect: Some(vec!["./node/index.js"]),
imports_field: imports_field(json!({
"#a/": {
"browser": {
"webpack": [
"./node/"
],
"default": {
"node": "./node/"
}
}
}
})),
request: "#a/index.js",
condition_names: vec!["browser", "webpack"],
},
TestCase {
name: "nested mapping #3",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": "./node/"
}
}
}
})),
request: "#a/index.js",
condition_names: vec!["webpack"],
},
TestCase {
name: "nested mapping #4",
expect: None,
imports_field: imports_field(json!({
"#a/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": "moment/node/"
}
}
}
})),
request: "#a/index.js",
condition_names: vec!["node", "browser"],
},
TestCase {
name: "nested mapping #5",
expect: Some(vec![]),
imports_field: imports_field(json!({
"#a/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": {
"webpack": [
"./wpck/"
]
}
}
}
}
})),
request: "#a/index.js",
condition_names: vec!["browser", "node"],
},
TestCase {
name: "nested mapping #6",
expect: Some(vec!["./index.js"]),
imports_field: imports_field(json!({
"#a/": {
"browser": {
"webpack": [
"./",
"./node/"
],
"default": {
"node": {
"webpack": [
"./wpck/"
]
}
}
}
}
})),
request: "#a/index.js",
condition_names: vec!["browser", "node", "webpack"],
},
TestCase {
name: "nested mapping #6",
expect: Some(vec!["./node/index.js"]),
imports_field: imports_field(json!({
"#a/": {
"browser": {
"webpack": [
"./node/"
],
"default": {
"node": {
"webpack": [
"./wpck/"
]
}
}
}
}
})),
request: "#a/index.js",
condition_names: vec!["browser", "node", "webpack"],
},
TestCase {
name: "nested mapping #7",
expect: Some(vec!["./y.js"]),
imports_field: imports_field(json!({
"#a": {
"abc": {
"def": "./x.js"
},
"ghi": "./y.js"
}
})),
request: "#a",
condition_names: vec!["abc", "ghi"],
},
TestCase {
name: "nested mapping #8",
expect: None,
imports_field: imports_field(json!({
"#a": {
"abc": {
"def": "./x.js",
"default": []
},
"ghi": "./y.js"
}
})),
request: "#a",
condition_names: vec!["abc", "ghi"],
},
];
for case in test_cases {
let resolved = Resolver::default()
.package_imports_exports_resolve(
case.request,
case.imports_field.as_object().unwrap(),
Path::new(""),
true,
&case
.condition_names
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>(),
&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, Ok(None)),
"{} {:?}",
&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);
}
}
}