View raw

1 open Hito_app 2 open Support 3 4 let suite = 5 [ 6 ( "web.overview", 7 [ 8 ( "selecting a routine redirects and records the active routine", 9 `Quick, 10 fun () -> 11 (* POST-redirect-GET: selecting a routine answers 303, and the 12 redirected GET is served. The domain effect is what matters: the 13 trainee now has an active routine. *) 14 let c, repo = client_with_repo () in 15 let _ = register c ~username:"lifter" ~password:"heavyduty1" in 16 let trainee = the_trainee repo ~username:"lifter" in 17 Alcotest.(check bool) 18 "no active routine before selection" true 19 (Option.is_none 20 (Lwt_main.run 21 (Test_repo.active_routine repo trainee.Trainee.id))); 22 let token = Option.get (csrf_token (body (get c "/"))) in 23 let selection = 24 post c "/routines/ideal/select" [ ("dream.csrf", token) ] 25 in 26 Alcotest.(check int) "selection redirects" 303 (status selection); 27 Alcotest.(check bool) 28 "a routine is now active" true 29 (Option.is_some 30 (Lwt_main.run 31 (Test_repo.active_routine repo trainee.Trainee.id))); 32 (* The redirected GET is served. *) 33 Alcotest.(check int) 34 "the redirected GET is 200" 200 35 (status (get c "/")) ); 36 ( "the home preview shows each exercise's current best weight and reps", 37 `Quick, 38 fun () -> 39 (* Give the Day 1 exercise Laterals a prior effort through an import, 40 which feeds the log but never advances the routine cycle. The next 41 workout stays Day 1, and its preview must show Laterals with the 42 recorded best — the record to beat, per the Heavy Duty progress 43 chart. *) 44 let c, repo = client_with_repo () in 45 let _ = register c ~username:"lifter" ~password:"heavyduty1" in 46 let trainee = the_trainee repo ~username:"lifter" in 47 let token = Option.get (csrf_token (body (get c "/"))) in 48 let _ = post c "/routines/ideal/select" [ ("dream.csrf", token) ] in 49 let header = 50 "title,start_time,end_time,description,exercise_title,superset_id,exercise_notes,set_index,set_type,weight_kg,reps,distance_km,duration_seconds,rpe\r\n" 51 in 52 let source = 53 header 54 ^ "Delts,\"01 Jan 2024, 10:00\",\"01 Jan 2024, 11:00\",,Side \ 55 Raise,,,0,failure,14,10,,,\r\n" 56 in 57 let token = Option.get (csrf_token (body (get c "/profile"))) in 58 let _ = 59 post_multipart c "/profile/import" 60 ~file:(Some ("csv", "workouts.csv", source)) 61 ~fields:[ ("dream.csrf", token); ("utc_offset_seconds", "0") ] 62 in 63 let batch = 64 List.hd 65 (Lwt_main.run 66 (Test_repo.import_batches repo trainee.Trainee.id)) 67 in 68 let bid = 69 Workout_import.batch_id_to_string 70 (Workout_import.batch_identity batch) 71 in 72 let wid = 73 Workout_import.workout_id_to_string 74 (Workout_import.workout_identity 75 (List.hd (Workout_import.batch_workouts batch))) 76 in 77 let review = "/profile/import/" ^ bid in 78 let t = Option.get (csrf_token (body (get c review))) in 79 let _ = 80 post c 81 (Printf.sprintf "/profile/import/%s/workouts/%s/map" bid wid) 82 [ 83 ("dream.csrf", t); 84 ("source_name", "Side Raise"); 85 ("exercise_id", "laterals"); 86 ] 87 in 88 let t = Option.get (csrf_token (body (get c review))) in 89 let _ = 90 post c 91 (Printf.sprintf "/profile/import/%s/workouts/%s/promote" bid wid) 92 [ ("dream.csrf", t) ] 93 in 94 let page = body (get c "/") in 95 (* The cycle has not advanced: the next workout is still Day 1. *) 96 Alcotest.(check bool) 97 "the Day 1 preview lists Laterals" true 98 (Option.is_some (index_from ~needle:"Laterals" page 0)); 99 Alcotest.(check bool) 100 "Laterals shows its best load and reps" true 101 (Option.is_some (index_from ~needle:">14<" page 0) 102 && Option.is_some (index_from ~needle:">10<" page 0)) ); 103 ( "the routine page is served once a routine is selected", 104 `Quick, 105 fun () -> 106 let c = client () in 107 let _ = sign_in_new c in 108 let token = Option.get (csrf_token (body (get c "/"))) in 109 let selection = 110 post c "/routines/ideal/select" [ ("dream.csrf", token) ] 111 in 112 Alcotest.(check int) "routine selected" 303 (status selection); 113 Alcotest.(check int) 114 "routine is available" 200 115 (status (get c "/routine")); 116 Alcotest.(check int) 117 "routine browser is available" 200 118 (status (get c "/routines")) ); 119 ( "the routine page states the rest between workouts", 120 `Quick, 121 fun () -> 122 let c = client () in 123 let _ = sign_in_new c in 124 let token = Option.get (csrf_token (body (get c "/"))) in 125 let _ = post c "/routines/ideal/select" [ ("dream.csrf", token) ] in 126 let page = body (get c "/routine") in 127 let has needle = Option.is_some (index_from ~needle page 0) in 128 Alcotest.(check bool) 129 "rest between workouts is stated" true (has "Rest 48 hours"); 130 Alcotest.(check bool) 131 "the last rest leads back to the first workout" true 132 (has "Rest 72 hours, then Day 1") ); 133 ( "selecting an unknown routine is not found and selects nothing", 134 `Quick, 135 fun () -> 136 let c, repo = client_with_repo () in 137 let _ = register c ~username:"lifter" ~password:"heavyduty1" in 138 let trainee = the_trainee repo ~username:"lifter" in 139 let token = Option.get (csrf_token (body (get c "/"))) in 140 let response = 141 post c "/routines/no-such-routine/select" 142 [ ("dream.csrf", token) ] 143 in 144 Alcotest.(check int) "responds 404" 404 (status response); 145 (* A missing routine leaves the trainee with no active routine. *) 146 Alcotest.(check bool) 147 "no routine was selected" true 148 (Option.is_none 149 (Lwt_main.run 150 (Test_repo.active_routine repo trainee.Trainee.id))) ); 151 ] ); 152 ] 153