deps_npm/
formatter.rs

1use deps_core::lsp_helpers::EcosystemFormatter;
2
3pub struct NpmFormatter;
4
5impl EcosystemFormatter for NpmFormatter {
6    fn format_version_for_code_action(&self, version: &str) -> String {
7        version.to_string()
8    }
9
10    fn package_url(&self, name: &str) -> String {
11        format!("https://www.npmjs.com/package/{name}")
12    }
13
14    fn yanked_message(&self) -> &'static str {
15        "This version is deprecated"
16    }
17
18    fn yanked_label(&self) -> &'static str {
19        "*(deprecated)*"
20    }
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26
27    #[test]
28    fn test_format_version() {
29        let formatter = NpmFormatter;
30        // Version should not include quotes - parser's version_range excludes them
31        assert_eq!(
32            formatter.format_version_for_code_action("1.0.214"),
33            "1.0.214"
34        );
35        assert_eq!(formatter.format_version_for_code_action("18.3.1"), "18.3.1");
36    }
37
38    #[test]
39    fn test_package_url() {
40        let formatter = NpmFormatter;
41        assert_eq!(
42            formatter.package_url("react"),
43            "https://www.npmjs.com/package/react"
44        );
45        assert_eq!(
46            formatter.package_url("@types/node"),
47            "https://www.npmjs.com/package/@types/node"
48        );
49    }
50
51    #[test]
52    fn test_default_normalize_is_identity() {
53        let formatter = NpmFormatter;
54        assert_eq!(formatter.normalize_package_name("react"), "react");
55        assert_eq!(
56            formatter.normalize_package_name("@types/node"),
57            "@types/node"
58        );
59    }
60
61    #[test]
62    fn test_deprecated_messages() {
63        let formatter = NpmFormatter;
64        assert_eq!(formatter.yanked_message(), "This version is deprecated");
65        assert_eq!(formatter.yanked_label(), "*(deprecated)*");
66    }
67
68    #[test]
69    fn test_version_satisfies_requirement() {
70        let formatter = NpmFormatter;
71
72        // Exact match
73        assert!(formatter.version_satisfies_requirement("1.2.3", "1.2.3"));
74
75        // Partial versions
76        assert!(formatter.version_satisfies_requirement("1.2.3", "1"));
77        assert!(formatter.version_satisfies_requirement("1.2.3", "1.2"));
78
79        // Caret - allows any version with same major (for major > 0)
80        assert!(formatter.version_satisfies_requirement("1.2.3", "^1.2"));
81        assert!(formatter.version_satisfies_requirement("1.2.3", "^1.0"));
82        assert!(formatter.version_satisfies_requirement("1.5.0", "^1.2.3"));
83        assert!(formatter.version_satisfies_requirement("10.1.3", "^10.1.3")); // Same version
84        assert!(formatter.version_satisfies_requirement("10.2.0", "^10.1.3")); // Higher minor
85
86        // Tilde - allows patch changes
87        assert!(formatter.version_satisfies_requirement("1.2.3", "~1.2"));
88        assert!(formatter.version_satisfies_requirement("1.2.5", "~1.2"));
89
90        // Should not match
91        assert!(!formatter.version_satisfies_requirement("1.2.3", "2.0.0"));
92        assert!(!formatter.version_satisfies_requirement("1.2.3", "1.3"));
93        assert!(!formatter.version_satisfies_requirement("2.0.0", "^1.2.3")); // Different major
94    }
95}