update_version/parsers/
package_json_parser.rs1use 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}