Skip to main content

max / goingson

3.7 KB · 98 lines History Blame Raw
1 //! Integration tests for SqliteDailyNoteRepository.
2
3 mod common;
4
5 use chrono::NaiveDate;
6 use goingson_core::DailyNoteRepository;
7 use goingson_db_sqlite::SqliteDailyNoteRepository;
8
9 fn date(y: i32, m: u32, d: u32) -> NaiveDate {
10 NaiveDate::from_ymd_opt(y, m, d).unwrap()
11 }
12
13 #[tokio::test]
14 async fn upsert_then_get_by_date_roundtrips() {
15 let pool = common::setup_test_db().await;
16 let user_id = common::create_test_user(&pool).await;
17 let repo = SqliteDailyNoteRepository::new(pool.clone());
18 let d = date(2026, 3, 15);
19
20 let created = repo
21 .upsert(user_id, d, "shipped the audit", "less context switching", false)
22 .await
23 .unwrap();
24 assert_eq!(created.note_date, d);
25 assert_eq!(created.went_well, "shipped the audit");
26 assert_eq!(created.could_improve, "less context switching");
27 assert!(!created.is_reviewed);
28 assert!(created.reviewed_at.is_none());
29
30 let fetched = repo.get_by_date(user_id, d).await.unwrap().unwrap();
31 assert_eq!(fetched.id, created.id);
32 assert_eq!(fetched.went_well, "shipped the audit");
33 }
34
35 #[tokio::test]
36 async fn get_by_date_missing_is_none() {
37 let pool = common::setup_test_db().await;
38 let user_id = common::create_test_user(&pool).await;
39 let repo = SqliteDailyNoteRepository::new(pool.clone());
40
41 assert!(repo.get_by_date(user_id, date(2026, 1, 1)).await.unwrap().is_none());
42 }
43
44 #[tokio::test]
45 async fn upsert_conflict_updates_in_place_and_preserves_id_and_created_at() {
46 let pool = common::setup_test_db().await;
47 let user_id = common::create_test_user(&pool).await;
48 let repo = SqliteDailyNoteRepository::new(pool.clone());
49 let d = date(2026, 5, 1);
50
51 let first = repo.upsert(user_id, d, "a", "b", false).await.unwrap();
52 let second = repo.upsert(user_id, d, "updated", "improved", true).await.unwrap();
53
54 // Same (user, date) folds into an update, not a second row.
55 assert_eq!(second.id, first.id, "id preserved on conflict path");
56 assert_eq!(second.created_at, first.created_at, "created_at preserved");
57 assert_eq!(second.went_well, "updated");
58 assert_eq!(second.could_improve, "improved");
59 assert!(second.is_reviewed);
60 assert!(second.reviewed_at.is_some(), "reviewed_at set when is_reviewed");
61
62 // Exactly one row exists for this user.
63 let all = repo.list_all(user_id).await.unwrap();
64 assert_eq!(all.len(), 1);
65 }
66
67 #[tokio::test]
68 async fn list_all_is_ordered_by_note_date_ascending() {
69 let pool = common::setup_test_db().await;
70 let user_id = common::create_test_user(&pool).await;
71 let repo = SqliteDailyNoteRepository::new(pool.clone());
72
73 repo.upsert(user_id, date(2026, 3, 10), "c", "", false).await.unwrap();
74 repo.upsert(user_id, date(2026, 3, 1), "a", "", false).await.unwrap();
75 repo.upsert(user_id, date(2026, 3, 5), "b", "", false).await.unwrap();
76
77 let all = repo.list_all(user_id).await.unwrap();
78 let dates: Vec<NaiveDate> = all.iter().map(|n| n.note_date).collect();
79 assert_eq!(dates, vec![date(2026, 3, 1), date(2026, 3, 5), date(2026, 3, 10)]);
80 }
81
82 #[tokio::test]
83 async fn list_all_is_scoped_per_user() {
84 let pool = common::setup_test_db().await;
85 let user_a = common::create_test_user(&pool).await;
86 let user_b = common::create_test_user(&pool).await;
87 let repo = SqliteDailyNoteRepository::new(pool.clone());
88
89 repo.upsert(user_a, date(2026, 2, 1), "a-note", "", false).await.unwrap();
90 repo.upsert(user_b, date(2026, 2, 1), "b-note", "", false).await.unwrap();
91
92 let a = repo.list_all(user_a).await.unwrap();
93 assert_eq!(a.len(), 1);
94 assert_eq!(a[0].went_well, "a-note");
95 // user_b's identically-dated note does not leak into user_a's listing.
96 assert!(repo.get_by_date(user_a, date(2026, 2, 1)).await.unwrap().is_some());
97 }
98