Skip to main content

max / goingson

3.4 KB · 98 lines History Blame Raw
1 //! Integration tests for SqliteWeeklyReviewRepository.
2 //!
3 //! Focus: upsert idempotency (the `ON CONFLICT(user_id, week_start_date)` path)
4 //! and vacation-day round-trips, the review-repo atomicity the audit flagged as
5 //! untested.
6
7 mod common;
8
9 use chrono::{Datelike, NaiveDate};
10 use goingson_core::WeeklyReviewRepository;
11 use goingson_db_sqlite::SqliteWeeklyReviewRepository;
12
13 fn monday() -> NaiveDate {
14 NaiveDate::from_ymd_opt(2026, 6, 15).unwrap()
15 }
16
17 #[tokio::test]
18 async fn test_upsert_creates_then_updates_in_place() {
19 let pool = common::setup_test_db().await;
20 let user_id = common::create_test_user(&pool).await;
21 let repo = SqliteWeeklyReviewRepository::new(pool);
22 let week = monday();
23
24 let first = repo.upsert(user_id, week, "initial notes").await.unwrap();
25 assert_eq!(first.notes, "initial notes");
26 assert_eq!(first.week_start_date, week);
27
28 // Second upsert for the same (user, week) must UPDATE the same row, not insert a duplicate.
29 let second = repo.upsert(user_id, week, "revised notes").await.unwrap();
30 assert_eq!(second.id, first.id, "upsert must reuse the existing row id");
31 assert_eq!(second.notes, "revised notes");
32
33 let all = repo.list_all(user_id).await.unwrap();
34 assert_eq!(
35 all.len(),
36 1,
37 "repeated upsert must not create duplicate weeks"
38 );
39 assert_eq!(all[0].notes, "revised notes");
40 }
41
42 #[tokio::test]
43 async fn test_upsert_is_idempotent_under_repeated_writes() {
44 let pool = common::setup_test_db().await;
45 let user_id = common::create_test_user(&pool).await;
46 let repo = SqliteWeeklyReviewRepository::new(pool);
47 let week = monday();
48
49 for i in 0..5 {
50 repo.upsert(user_id, week, &format!("pass {i}"))
51 .await
52 .unwrap();
53 }
54
55 let all = repo.list_all(user_id).await.unwrap();
56 assert_eq!(all.len(), 1);
57 assert_eq!(all[0].notes, "pass 4");
58 }
59
60 #[tokio::test]
61 async fn test_set_vacation_days_round_trip_and_overwrite() {
62 let pool = common::setup_test_db().await;
63 let user_id = common::create_test_user(&pool).await;
64 let repo = SqliteWeeklyReviewRepository::new(pool);
65 let week = monday();
66
67 repo.upsert(user_id, week, "notes").await.unwrap();
68 repo.set_vacation_days(user_id, week, &[0, 2, 4])
69 .await
70 .unwrap();
71
72 let review = repo.get_for_week(user_id, week).await.unwrap().unwrap();
73 assert_eq!(review.vacation_days, vec![0, 2, 4]);
74
75 // Overwriting vacation days must replace, not append or duplicate the row.
76 repo.set_vacation_days(user_id, week, &[6]).await.unwrap();
77 let review = repo.get_for_week(user_id, week).await.unwrap().unwrap();
78 assert_eq!(review.vacation_days, vec![6]);
79 assert_eq!(repo.list_all(user_id).await.unwrap().len(), 1);
80 }
81
82 #[tokio::test]
83 async fn test_is_current_week_completed_reflects_upsert() {
84 let pool = common::setup_test_db().await;
85 let user_id = common::create_test_user(&pool).await;
86 let repo = SqliteWeeklyReviewRepository::new(pool);
87
88 assert!(!repo.is_current_week_completed(user_id).await.unwrap());
89
90 // Complete the current calendar week's review.
91 let today = chrono::Utc::now().date_naive();
92 let days_since_monday = today.weekday().num_days_from_monday() as i64;
93 let this_monday = today - chrono::Duration::days(days_since_monday);
94 repo.upsert(user_id, this_monday, "done").await.unwrap();
95
96 assert!(repo.is_current_week_completed(user_id).await.unwrap());
97 }
98