Skip to main content

update_version/parsers/
package_json_parser.rs

1use crate::parsers::Parser;
2use regex::Regex;
3use semver::Version;
4
5pub struct PackageJsonParser;
6
7impl Parser for PackageJsonParser {
8    fn version_match_regex() -> anyhow::Result<Regex> {
9        Ok(Regex::new(r##"(?m)^(\s*"version"\s*:\s*")([^"]*)""##)?)
10    }
11
12    fn filename_match_regex() -> anyhow::Result<Regex> {
13        Ok(Regex::new(r#"(?i)[/\\]package\.json$"#)?)
14    }
15
16    fn version_line_format(version: &Version) -> anyhow::Result<String> {
17        Ok(format!("${{1}}{version}\""))
18    }
19}
20
21#[cfg(test)]
22mod tests {
23    use super::*;
24
25    #[test]
26    fn test_version_regex_matches_simple() {
27        let regex = PackageJsonParser::version_match_regex().unwrap();
28        let content = r#""version": "1.2.3""#;
29        let captures = regex.captures(content).unwrap();
30        assert_eq!(captures.get(2).unwrap().as_str(), "1.2.3");
31    }
32
33    #[test]
34    fn test_version_regex_matches_with_indentation() {
35        let regex = PackageJsonParser::version_match_regex().unwrap();
36        let content = r#"  "version": "0.1.0""#;
37        let captures = regex.captures(content).unwrap();
38        assert_eq!(captures.get(2).unwrap().as_str(), "0.1.0");
39    }
40
41    #[test]
42    fn test_version_regex_matches_in_file() {
43        let regex = PackageJsonParser::version_match_regex().unwrap();
44        let content = r#"{
45  "name": "my-package",
46  "version": "2.0.0",
47  "description": "A test package"
48}"#;
49        let captures = regex.captures(content).unwrap();
50        assert_eq!(captures.get(2).unwrap().as_str(), "2.0.0");
51    }
52
53    #[test]
54    fn test_version_regex_various_spacing() {
55        let regex = PackageJsonParser::version_match_regex().unwrap();
56
57        let content1 = r#""version":"1.0.0""#;
58        let captures1 = regex.captures(content1).unwrap();
59        assert_eq!(captures1.get(2).unwrap().as_str(), "1.0.0");
60
61        let content2 = r#""version" : "2.0.0""#;
62        let captures2 = regex.captures(content2).unwrap();
63        assert_eq!(captures2.get(2).unwrap().as_str(), "2.0.0");
64    }
65
66    #[test]
67    fn test_filename_regex_matches_package_json() {
68        let regex = PackageJsonParser::filename_match_regex().unwrap();
69        assert!(regex.is_match("/path/to/package.json"));
70        assert!(regex.is_match("\\path\\to\\package.json"));
71        assert!(regex.is_match("/package.json"));
72    }
73
74    #[test]
75    fn test_filename_regex_case_insensitive() {
76        let regex = PackageJsonParser::filename_match_regex().unwrap();
77        assert!(regex.is_match("/path/to/PACKAGE.JSON"));
78        assert!(regex.is_match("/path/to/Package.Json"));
79    }
80
81    #[test]
82    fn test_filename_regex_no_false_positives() {
83        let regex = PackageJsonParser::filename_match_regex().unwrap();
84        assert!(!regex.is_match("/path/to/package-lock.json"));
85        assert!(!regex.is_match("/path/to/package.json.bak"));
86        assert!(!regex.is_match("/path/to/my-package.json"));
87    }
88
89    #[test]
90    fn test_version_line_format() {
91        let version = Version::parse("1.2.3").unwrap();
92        let formatted = PackageJsonParser::version_line_format(&version).unwrap();
93        assert_eq!(formatted, "${1}1.2.3\"");
94    }
95
96    #[test]
97    fn test_version_line_format_with_prerelease() {
98        let version = Version::parse("1.0.0-beta.2").unwrap();
99        let formatted = PackageJsonParser::version_line_format(&version).unwrap();
100        assert_eq!(formatted, "${1}1.0.0-beta.2\"");
101    }
102}