1pub mod search_fixtures {
3 use crate::search::models::{SearchTweet, SearchUser};
4
5 pub fn create_tweet_fixtures(count: usize) -> Vec<SearchTweet> {
7 (0..count)
8 .map(|i| {
9 let mut tweet = SearchTweet::new(format!("fixture_tweet_{}", i));
10 tweet.text = Some(format!("Fixture tweet text {}", i));
11 tweet.author_id = Some(format!("fixture_user_{}", i));
12 tweet.created_at = Some("2024-01-01T00:00:00Z".to_string());
13 tweet
14 })
15 .collect()
16 }
17
18 pub fn create_user_fixtures(count: usize) -> Vec<SearchUser> {
20 (0..count)
21 .map(|i| {
22 let mut user = SearchUser::new(format!("fixture_user_{}", i));
23 user.name = Some(format!("Fixture User {}", i));
24 user.username = Some(format!("fixture_user_{}", i));
25 user.description = Some(format!("A fixture user {}", i));
26 user
27 })
28 .collect()
29 }
30}
31
32pub mod media_fixtures {
33 use crate::media::models::UploadResult;
34
35 pub const FIXTURE_MEDIA_ID: &str = "fixture_media_id_0000000000000001";
37
38 pub fn create_upload_result() -> UploadResult {
40 UploadResult::new(FIXTURE_MEDIA_ID)
41 }
42
43 pub fn create_upload_results(count: usize) -> Vec<UploadResult> {
45 (0..count)
46 .map(|i| UploadResult::new(format!("fixture_media_id_{:016}", i)))
47 .collect()
48 }
49}
50
51pub mod env_lock {
52 use std::sync::Mutex;
53
54 pub static ENV_LOCK: Mutex<()> = Mutex::new(());
57}
58
59pub mod engagement_fixtures {
61 use crate::tweets::models::Tweet;
62
63 pub fn mock_tweet(id: &str) -> Tweet {
65 let mut tweet = Tweet::new(id.to_string());
66 tweet.text = Some(format!("Test tweet content for {}", id));
67 tweet.author_id = Some("user_test123".to_string());
68 tweet.created_at = Some("2024-01-01T00:00:00Z".to_string());
69 tweet
70 }
71
72 pub fn mock_bookmark_tweets(count: usize) -> Vec<Tweet> {
74 (0..count)
75 .map(|i| mock_tweet(&format!("bookmark_tweet_{}", i)))
76 .collect()
77 }
78
79 pub fn mock_like_result(tweet_id: &str) -> serde_json::Value {
81 serde_json::json!({
82 "tweet_id": tweet_id,
83 "success": true
84 })
85 }
86
87 pub fn mock_retweet_result(tweet_id: &str) -> serde_json::Value {
89 serde_json::json!({
90 "tweet_id": tweet_id,
91 "success": true
92 })
93 }
94
95 pub fn mock_bookmark_list_result(limit: usize, offset: usize) -> serde_json::Value {
97 let tweets: Vec<serde_json::Value> = (offset..(offset + limit))
98 .map(|i| {
99 serde_json::json!({
100 "id": format!("bookmark_tweet_{}", i),
101 "text": format!("Bookmarked tweet text {}", i),
102 "author_id": format!("user_{}", i),
103 "created_at": "2024-01-01T00:00:00Z"
104 })
105 })
106 .collect();
107
108 serde_json::json!({
109 "tweets": tweets,
110 "meta": {
111 "pagination": {
112 "next_token": format!("bookmark_cursor_{}", offset + limit)
113 }
114 }
115 })
116 }
117}
118
119pub mod helpers {
120 use std::path::{Path, PathBuf};
121 use tempfile::TempDir;
122
123 pub fn create_test_dir(prefix: &str) -> TempDir {
126 TempDir::new().unwrap_or_else(|e| {
127 panic!(
128 "Failed to create test directory with prefix '{}': {}",
129 prefix, e
130 )
131 })
132 }
133
134 pub fn create_test_db_path(temp_dir: &Path) -> PathBuf {
136 temp_dir.join("test.db")
137 }
138
139 pub fn create_test_home() -> TempDir {
141 let test_dir = std::env::temp_dir().join(format!("xcom-rs-test-{}", std::process::id()));
142 std::fs::create_dir_all(&test_dir)
143 .unwrap_or_else(|e| panic!("Failed to create test HOME directory: {}", e));
144
145 TempDir::new().unwrap_or_else(|e| panic!("Failed to create test HOME TempDir: {}", e))
146 }
147
148 pub fn create_test_ledger() -> crate::tweets::IdempotencyLedger {
150 crate::tweets::IdempotencyLedger::new(None)
151 .expect("Failed to create test IdempotencyLedger")
152 }
153
154 pub fn create_test_ledger_with_db(db_path: &Path) -> crate::tweets::IdempotencyLedger {
156 crate::tweets::IdempotencyLedger::new(Some(db_path))
157 .expect("Failed to create test IdempotencyLedger with database")
158 }
159
160 pub fn parse_json_output(output: &[u8]) -> serde_json::Value {
162 let stdout = String::from_utf8_lossy(output);
163 serde_json::from_str(&stdout)
164 .unwrap_or_else(|e| panic!("Failed to parse JSON output: {}\nOutput: {}", e, stdout))
165 }
166
167 pub fn assert_success_json(output: &std::process::Output) -> serde_json::Value {
169 assert!(
170 output.status.success(),
171 "Command failed with status: {:?}\nStdout: {}\nStderr: {}",
172 output.status.code(),
173 String::from_utf8_lossy(&output.stdout),
174 String::from_utf8_lossy(&output.stderr)
175 );
176 parse_json_output(&output.stdout)
177 }
178
179 pub fn assert_error_json(
181 output: &std::process::Output,
182 expected_code: i32,
183 ) -> serde_json::Value {
184 assert_eq!(
185 output.status.code(),
186 Some(expected_code),
187 "Expected exit code {} but got {:?}\nStdout: {}\nStderr: {}",
188 expected_code,
189 output.status.code(),
190 String::from_utf8_lossy(&output.stdout),
191 String::from_utf8_lossy(&output.stderr)
192 );
193 parse_json_output(&output.stdout)
194 }
195}