[OCaml] High Intensity Training Online
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