Skip to main content

max / goingson

5.1 KB · 156 lines History Blame Raw
1 //! Integration tests for SqliteSyncAccountRepository.
2
3 mod common;
4
5 use goingson_core::SyncAccountRepository;
6 use goingson_db_sqlite::SqliteSyncAccountRepository;
7
8 #[tokio::test]
9 async fn create_applies_schema_defaults() {
10 let pool = common::setup_test_db().await;
11 let user_id = common::create_test_user(&pool).await;
12 let repo = SqliteSyncAccountRepository::new(pool.clone());
13
14 let acct = repo
15 .create(user_id, "google", "Work Calendar", Some("me@example.com"))
16 .await
17 .unwrap();
18
19 assert_eq!(acct.provider, "google");
20 assert_eq!(acct.account_name, "Work Calendar");
21 assert_eq!(acct.email.as_deref(), Some("me@example.com"));
22 // Defaults from migration 037.
23 assert!(acct.sync_calendars);
24 assert!(acct.sync_contacts);
25 assert!(acct.enabled);
26 assert_eq!(acct.sync_interval_minutes, 15);
27 assert!(
28 acct.calendar_ids.is_empty(),
29 "calendar_ids defaults to '[]'"
30 );
31 assert!(acct.last_calendar_sync.is_none());
32 }
33
34 #[tokio::test]
35 async fn create_allows_null_email() {
36 let pool = common::setup_test_db().await;
37 let user_id = common::create_test_user(&pool).await;
38 let repo = SqliteSyncAccountRepository::new(pool.clone());
39
40 let acct = repo
41 .create(user_id, "caldav", "Personal", None)
42 .await
43 .unwrap();
44 assert!(acct.email.is_none());
45
46 let fetched = repo.get_by_id(acct.id, user_id).await.unwrap().unwrap();
47 assert!(fetched.email.is_none());
48 }
49
50 #[tokio::test]
51 async fn get_by_id_missing_is_none() {
52 let pool = common::setup_test_db().await;
53 let user_id = common::create_test_user(&pool).await;
54 let repo = SqliteSyncAccountRepository::new(pool.clone());
55
56 let missing = goingson_core::SyncAccountId::new();
57 assert!(repo.get_by_id(missing, user_id).await.unwrap().is_none());
58 }
59
60 #[tokio::test]
61 async fn update_changes_fields_and_returns_row() {
62 let pool = common::setup_test_db().await;
63 let user_id = common::create_test_user(&pool).await;
64 let repo = SqliteSyncAccountRepository::new(pool.clone());
65
66 let acct = repo
67 .create(user_id, "google", "Old Name", None)
68 .await
69 .unwrap();
70 let updated = repo
71 .update(acct.id, user_id, "New Name", false, false, false)
72 .await
73 .unwrap()
74 .expect("existing account updates to Some");
75
76 assert_eq!(updated.account_name, "New Name");
77 assert!(!updated.sync_calendars);
78 assert!(!updated.sync_contacts);
79 assert!(!updated.enabled);
80 assert_eq!(updated.id, acct.id);
81 }
82
83 #[tokio::test]
84 async fn update_unknown_id_returns_none() {
85 let pool = common::setup_test_db().await;
86 let user_id = common::create_test_user(&pool).await;
87 let repo = SqliteSyncAccountRepository::new(pool.clone());
88
89 let missing = goingson_core::SyncAccountId::new();
90 let result = repo
91 .update(missing, user_id, "x", true, true, true)
92 .await
93 .unwrap();
94 assert!(result.is_none(), "no rows affected -> None");
95 }
96
97 #[tokio::test]
98 async fn delete_removes_row_and_reports_hit() {
99 let pool = common::setup_test_db().await;
100 let user_id = common::create_test_user(&pool).await;
101 let repo = SqliteSyncAccountRepository::new(pool.clone());
102
103 let acct = repo.create(user_id, "google", "Temp", None).await.unwrap();
104 assert!(
105 repo.delete(acct.id, user_id).await.unwrap(),
106 "first delete hits"
107 );
108 assert!(repo.get_by_id(acct.id, user_id).await.unwrap().is_none());
109 assert!(
110 !repo.delete(acct.id, user_id).await.unwrap(),
111 "second delete is a miss"
112 );
113 }
114
115 #[tokio::test]
116 async fn list_all_scoped_per_user_and_ordered_by_created_at() {
117 let pool = common::setup_test_db().await;
118 let user_a = common::create_test_user(&pool).await;
119 let user_b = common::create_test_user(&pool).await;
120 let repo = SqliteSyncAccountRepository::new(pool.clone());
121
122 let first = repo.create(user_a, "google", "First", None).await.unwrap();
123 let second = repo.create(user_a, "caldav", "Second", None).await.unwrap();
124 repo.create(user_b, "google", "Other User", None)
125 .await
126 .unwrap();
127
128 let a = repo.list_all(user_a).await.unwrap();
129 assert_eq!(a.len(), 2, "only user_a's accounts");
130 // Ordered by created_at ASC (first created first).
131 assert_eq!(a[0].id, first.id);
132 assert_eq!(a[1].id, second.id);
133 }
134
135 #[tokio::test]
136 async fn cross_user_access_is_denied() {
137 let pool = common::setup_test_db().await;
138 let owner = common::create_test_user(&pool).await;
139 let intruder = common::create_test_user(&pool).await;
140 let repo = SqliteSyncAccountRepository::new(pool.clone());
141
142 let acct = repo.create(owner, "google", "Owned", None).await.unwrap();
143
144 // Another user cannot read, update, or delete it.
145 assert!(repo.get_by_id(acct.id, intruder).await.unwrap().is_none());
146 assert!(
147 repo.update(acct.id, intruder, "hijack", true, true, true)
148 .await
149 .unwrap()
150 .is_none()
151 );
152 assert!(!repo.delete(acct.id, intruder).await.unwrap());
153 // Still intact for the owner.
154 assert!(repo.get_by_id(acct.id, owner).await.unwrap().is_some());
155 }
156