auto_gitmoji/
lib.rs

1pub mod commit;
2pub mod emoji;
3pub mod matcher;
4
5// Re-export main types for convenience
6pub use commit::{GitCommit, GitError};
7pub use emoji::{EMOJI_MAP, EmojiLookup};
8pub use matcher::{GitmojiMatcher, MatcherFactory, MatcherResult};
9
10// Re-export LLM types only when the feature is enabled
11#[cfg(feature = "llm")]
12pub use matcher::llm::{LLMConfig, LLMMatcher, LLMModel, LLMProvider, LLMWithFallbackMatcher};
13
14pub fn add(left: u64, right: u64) -> u64 {
15    left + right
16}
17
18#[cfg(test)]
19mod tests {
20    use super::*;
21    use crate::matcher::MatcherFactory;
22
23    #[test]
24    fn test_library_integration() {
25        // Test that all main components work together
26        let matcher = MatcherFactory::simple();
27
28        // Test emoji lookup
29        let emoji = EmojiLookup::code_to_unicode(":sparkles:");
30        assert_eq!(emoji, Some("✨"));
31
32        // Test matcher
33        let result = matcher.match_emoji("fix critical bug").unwrap();
34        assert!(result.is_some());
35        let (code, format_message) = result.unwrap();
36        assert_eq!(code, ":bug:");
37        assert_eq!(format_message, ":bug: fix critical bug");
38
39        // Test that emoji lookup works for the matched code
40        let emoji_unicode = EmojiLookup::code_to_unicode(&code);
41        assert_eq!(emoji_unicode, Some("🐛"));
42    }
43
44    #[test]
45    fn test_end_to_end_workflow() {
46        // Simulate the complete workflow: message -> emoji match -> format
47        let matcher = MatcherFactory::simple();
48
49        let test_cases = vec![
50            ("add user authentication", ":sparkles:", "✨"),
51            ("fix memory leak", ":bug:", "🐛"),
52            ("update documentation", ":memo:", "📝"),
53            ("add unit tests", ":white_check_mark:", "✅"),
54        ];
55
56        for (message, expected_code, expected_emoji) in test_cases {
57            // Match emoji
58            let match_result = matcher.match_emoji(message).unwrap();
59            assert!(match_result.is_some());
60
61            let (code, format_message) = match_result.unwrap();
62
63            // Verify emoji lookup
64            let emoji_from_lookup = EmojiLookup::code_to_unicode(&code);
65            assert!(emoji_from_lookup.is_some());
66
67            // Verify format message structure
68            assert!(format_message.contains(message));
69            assert!(format_message.starts_with(&code));
70
71            // For exact keyword matches, should match expected code
72            if code == expected_code {
73                assert_eq!(emoji_from_lookup.unwrap(), expected_emoji);
74            }
75        }
76    }
77
78    #[test]
79    fn test_public_api_exports() {
80        // Test that all expected types are properly exported
81
82        // Test GitCommit export
83        let _commit = GitCommit::format_message(":sparkles:", "test");
84
85        // Test EmojiLookup export
86        let _emoji = EmojiLookup::code_to_unicode(":sparkles:");
87
88        // Test MatcherResult export
89        let _result: MatcherResult = Some((
90            ":sparkles:".to_string(),
91            ":sparkles: test message".to_string(),
92        ));
93
94        // Test EMOJI_MAP export
95        assert!(!EMOJI_MAP.is_empty());
96    }
97
98    #[test]
99    fn test_error_handling_integration() {
100        // Test error handling across components
101
102        // Test invalid emoji code
103        let invalid_emoji = EmojiLookup::code_to_unicode(":nonexistent:");
104        assert!(invalid_emoji.is_none());
105
106        // Test dry run commit (should always work)
107        let commit_result = GitCommit::commit("test message", true);
108        assert!(commit_result.is_ok());
109
110        // Test matcher with edge cases
111        let matcher = MatcherFactory::simple();
112        let edge_cases = vec!["", "   ", "\n\t", "🎉🐛✨"];
113
114        for case in edge_cases {
115            let result = matcher.match_emoji(case);
116            assert!(result.is_ok());
117            assert!(result.unwrap().is_some()); // Should always return something
118        }
119    }
120
121    #[test]
122    fn test_data_consistency() {
123        // Test consistency between emoji map and matcher results
124        let matcher = MatcherFactory::simple();
125
126        let test_messages = vec![
127            "fix bug",
128            "add feature",
129            "update docs",
130            "run tests",
131            "refactor code",
132        ];
133
134        for message in test_messages {
135            let result = matcher.match_emoji(message).unwrap();
136            assert!(result.is_some());
137
138            let (code, format_message) = result.unwrap();
139
140            // The emoji code should be valid in lookup
141            let lookup_emoji = EmojiLookup::code_to_unicode(&code);
142            assert!(lookup_emoji.is_some());
143
144            // Format message should contain the original message
145            assert!(format_message.contains(message));
146            assert!(format_message.starts_with(&code));
147        }
148    }
149
150    #[test]
151    fn test_performance_basic() {
152        // Basic performance test - should complete quickly
153        let matcher = MatcherFactory::simple();
154
155        let start = std::time::Instant::now();
156
157        // Run many operations
158        for i in 0..1000 {
159            let message = format!("fix bug number {i}");
160            let _result = matcher.match_emoji(&message).unwrap();
161        }
162
163        let duration = start.elapsed();
164
165        // Should complete in reasonable time (less than 1 second)
166        assert!(
167            duration.as_secs() < 1,
168            "Performance test took too long: {duration:?}"
169        );
170    }
171
172    // Keep the original add function test for now
173    #[test]
174    fn it_works() {
175        let result = add(2, 2);
176        assert_eq!(result, 4);
177    }
178}