use crate::{ResolveError, ResolveOptions, Resolver, TsconfigDiscovery, TsconfigOptions};
fn dts_fixture() -> std::path::PathBuf {
super::fixture_root().join("dts_resolver")
}
fn containing_file() -> std::path::PathBuf {
dts_fixture().join("index.ts")
}
fn resolver() -> Resolver {
Resolver::new(ResolveOptions {
condition_names: vec!["import".into(), "types".into()],
..ResolveOptions::default()
})
}
#[test]
fn relative_basic_ts() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./relative-basic/index").unwrap();
assert_eq!(result.path(), dts_fixture().join("relative-basic/index.ts"));
}
#[test]
fn relative_dts_over_js() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./relative-dts-over-js/index").unwrap();
assert_eq!(result.path(), dts_fixture().join("relative-dts-over-js/index.d.ts"));
}
#[test]
fn relative_directory_index() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./relative-basic").unwrap();
assert_eq!(result.path(), dts_fixture().join("relative-basic/index.ts"));
}
#[test]
fn extension_substitution_js_to_dts() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-substitution/foo.js").unwrap();
assert_eq!(result.path(), dts_fixture().join("extension-substitution/foo.d.ts"));
}
#[test]
fn extension_substitution_mjs_to_dmts() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-substitution/bar.mjs").unwrap();
assert_eq!(result.path(), dts_fixture().join("extension-substitution/bar.d.mts"));
}
#[test]
fn extension_substitution_cjs_to_dcts() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-substitution/baz.cjs").unwrap();
assert_eq!(result.path(), dts_fixture().join("extension-substitution/baz.d.cts"));
}
#[test]
fn extension_priority_ts_wins() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-priority/main").unwrap();
assert_eq!(result.path(), dts_fixture().join("extension-priority/main.ts"));
}
#[test]
fn extension_priority_dts_over_js() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-priority/only-dts").unwrap();
assert_eq!(result.path(), dts_fixture().join("extension-priority/only-dts.d.ts"));
}
#[test]
fn directory_module_with_main() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./dir-module").unwrap();
assert_eq!(result.path(), dts_fixture().join("dir-module/lib/main.ts"));
}
#[test]
fn at_types_basic() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "debug").unwrap();
assert_eq!(result.path(), dts_fixture().join("node_modules/@types/debug/index.d.ts"));
}
#[test]
fn at_types_scoped() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "@babel/generator").unwrap();
assert_eq!(
result.path(),
dts_fixture().join("node_modules/@types/babel__generator/index.d.ts")
);
}
#[test]
fn exports_field_types_condition() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "with-exports").unwrap();
assert_eq!(result.path(), dts_fixture().join("node_modules/with-exports/types/index.d.ts"));
}
#[test]
fn types_versions_root() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "with-types-versions").unwrap();
assert_eq!(
result.path(),
dts_fixture().join("node_modules/with-types-versions/dist/index.d.ts")
);
}
#[test]
fn types_versions_subpath() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "with-types-versions/sub").unwrap();
assert_eq!(result.path(), dts_fixture().join("node_modules/with-types-versions/dist/sub.d.ts"));
}
#[test]
fn typings_field() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "with-typings").unwrap();
assert_eq!(result.path(), dts_fixture().join("node_modules/with-typings/types.d.ts"));
}
#[test]
fn node_protocol_not_resolved() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "node:fs");
assert!(result.is_err(), "node:fs should not resolve");
}
#[test]
fn no_types_not_resolved() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "no-types").unwrap();
assert_eq!(result.path(), dts_fixture().join("node_modules/no-types/index.js"));
}
#[test]
fn exports_esm_match_finds_declaration() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "exports-dts-for-mjs").unwrap();
assert_eq!(
result.path(),
dts_fixture().join("node_modules/exports-dts-for-mjs/dist/index.d.mts")
);
}
#[test]
fn types_field() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "with-types").unwrap();
assert_eq!(result.path(), dts_fixture().join("node_modules/with-types/types/index.d.ts"));
}
#[test]
fn typings_takes_precedence_over_types() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "with-both-types-fields").unwrap();
assert_eq!(
result.path(),
dts_fixture().join("node_modules/with-both-types-fields/typings.d.ts")
);
}
#[test]
fn completely_unresolvable_package() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "completely-empty");
assert!(result.is_err());
}
#[test]
fn nonexistent_package() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "this-package-does-not-exist");
assert_eq!(result, Err(ResolveError::NotFound("this-package-does-not-exist".into())));
}
#[test]
fn node_protocol_returns_not_found() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "node:fs");
assert_eq!(result, Err(ResolveError::NotFound("node:fs".into())));
}
#[test]
fn hash_import() {
let r = resolver();
let containing = dts_fixture().join("hash-import/index.ts");
let result = r.resolve_dts(containing, "#internal").unwrap();
assert_eq!(result.path(), dts_fixture().join("hash-import/src/internal.d.ts"));
}
#[test]
fn tsconfig_paths_in_dts() {
let r = Resolver::new(ResolveOptions {
condition_names: vec!["import".into(), "types".into()],
tsconfig: Some(TsconfigDiscovery::Manual(TsconfigOptions {
config_file: dts_fixture().join("with-tsconfig/tsconfig.json"),
references: crate::TsconfigReferences::Disabled,
})),
..ResolveOptions::default()
});
let containing = dts_fixture().join("with-tsconfig/index.ts");
let result = r.resolve_dts(containing, "@lib/utils").unwrap();
assert_eq!(result.path(), dts_fixture().join("with-tsconfig/lib/utils.ts"));
}
#[test]
fn extension_substitution_mjs_prefers_mts() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-substitution/priority.mjs").unwrap();
assert_eq!(result.path(), dts_fixture().join("extension-substitution/priority.mts"));
}
#[test]
fn extension_substitution_json_to_d_json_ts() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-substitution/qux.json").unwrap();
assert_eq!(result.path(), dts_fixture().join("extension-substitution/qux.d.json.ts"));
}
#[test]
fn extension_substitution_tsx() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-substitution/comp.tsx").unwrap();
assert_eq!(result.path(), dts_fixture().join("extension-substitution/comp.tsx"));
}
#[test]
fn self_referencing_package() {
let r = resolver();
let containing = dts_fixture().join("node_modules/with-self-ref/src/index.ts");
let result = r.resolve_dts(containing, "with-self-ref").unwrap();
assert_eq!(result.path(), dts_fixture().join("node_modules/with-self-ref/types/index.d.ts"));
}
#[test]
fn subpath_with_types_versions() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "with-subpath/sub/foo").unwrap();
assert_eq!(result.path(), dts_fixture().join("node_modules/with-subpath/dist/foo.d.ts"));
}
#[test]
fn dts_module_type_mts() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "exports-dts-for-mjs").unwrap();
assert_eq!(result.module_type(), Some(crate::ModuleType::Module));
}
#[test]
fn dts_module_type_cts() {
let r = resolver();
let result = r.resolve_dts(containing_file(), "./extension-substitution/baz.cjs").unwrap();
assert_eq!(result.module_type(), Some(crate::ModuleType::CommonJs));
}
#[test]
fn mangle_unscoped() {
assert_eq!(
crate::ResolverGeneric::<crate::FileSystemOs>::dts_mangle_scoped_name("debug"),
"debug"
);
}
#[test]
fn mangle_scoped() {
assert_eq!(
crate::ResolverGeneric::<crate::FileSystemOs>::dts_mangle_scoped_name("@babel/generator"),
"babel__generator"
);
}
#[test]
fn mangle_scoped_multi_slash() {
assert_eq!(
crate::ResolverGeneric::<crate::FileSystemOs>::dts_mangle_scoped_name("@scope/pkg/sub"),
"scope__pkg/sub"
);
}