ridewithgps_client/
sync.rs1use crate::{Result, RideWithGpsClient};
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
9#[serde(rename_all = "lowercase")]
10pub enum ItemType {
11 Route,
13
14 Trip,
16
17 Event,
19
20 Collection,
22}
23
24#[derive(Debug, Clone, Deserialize, Serialize)]
26pub struct SyncItem {
27 pub id: u64,
29
30 pub item_type: ItemType,
32
33 pub updated_at: DateTime<Utc>,
35
36 pub deleted: Option<bool>,
38}
39
40#[derive(Debug, Clone, Deserialize, Serialize)]
42pub struct SyncResponse {
43 pub items: Vec<SyncItem>,
45
46 pub server_datetime: DateTime<Utc>,
48}
49
50impl RideWithGpsClient {
51 pub fn sync(&self, since: &DateTime<Utc>) -> Result<SyncResponse> {
86 let since_str = since.to_rfc3339();
87 let url = format!(
88 "/api/v1/sync.json?since={}",
89 urlencoding::encode(&since_str)
90 );
91 self.get(&url)
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use chrono::TimeZone;
99
100 #[test]
101 fn test_sync_item_deserialization() {
102 let json = r#"{
103 "id": 123,
104 "item_type": "route",
105 "updated_at": "2025-01-15T10:30:00Z",
106 "deleted": false
107 }"#;
108
109 let item: SyncItem = serde_json::from_str(json).unwrap();
110 assert_eq!(item.id, 123);
111 assert_eq!(item.item_type, ItemType::Route);
112 assert_eq!(item.deleted, Some(false));
113 }
114
115 #[test]
116 fn test_sync_response_deserialization() {
117 let json = r#"{
118 "items": [
119 {
120 "id": 123,
121 "item_type": "route",
122 "updated_at": "2025-01-15T10:30:00Z",
123 "deleted": false
124 },
125 {
126 "id": 456,
127 "item_type": "trip",
128 "updated_at": "2025-01-15T11:00:00Z",
129 "deleted": true
130 }
131 ],
132 "server_datetime": "2025-01-15T12:00:00Z"
133 }"#;
134
135 let response: SyncResponse = serde_json::from_str(json).unwrap();
136 assert_eq!(response.items.len(), 2);
137 assert_eq!(response.items[0].item_type, ItemType::Route);
138 assert_eq!(response.items[1].item_type, ItemType::Trip);
139 assert_eq!(
140 response.server_datetime,
141 Utc.with_ymd_and_hms(2025, 1, 15, 12, 0, 0).unwrap()
142 );
143 }
144
145 #[test]
146 fn test_item_type_serialization() {
147 assert_eq!(
148 serde_json::to_string(&ItemType::Route).unwrap(),
149 r#""route""#
150 );
151 assert_eq!(serde_json::to_string(&ItemType::Trip).unwrap(), r#""trip""#);
152 }
153}