wip: currently rewriting the project as a full stack application
tangled.org/kacaii.dev/sigo
gleam
1import app/domain/role
2import app/http_router
3import app/web/session
4import app_dev/sql as dev_sql
5import app_test
6import dummy
7import gleam/dynamic/decode
8import gleam/http
9import gleam/http/response
10import gleam/int
11import gleam/json
12import gleam/list
13import gleam/string
14import wisp
15import wisp/simulate
16import youid/uuid
17
18pub fn login_test() {
19 use ctx <- app_test.global_data()
20 use _ <- list.each(list.range(1, app_test.n_tests))
21
22 let req =
23 simulate.browser_request(http.Post, "/user/login")
24 |> simulate.json_body(
25 json.object([
26 #("matricula", json.string("000")),
27 #("senha", json.string("aluno")),
28 ]),
29 )
30
31 let resp = http_router.handle_request(req, ctx)
32 assert resp.status == 200 as "Status should be 200"
33
34 let body = simulate.read_body(resp)
35
36 let assert Ok(_) =
37 json.parse(body, {
38 use maybe_role <- decode.field("access_level", decode.string)
39 let assert Ok(_) = role.from_string(maybe_role) as "Invalid user Role"
40
41 decode.success(Nil)
42 })
43 as "Response should contain valid JSON data"
44
45 let cookies = response.get_cookies(resp)
46 assert cookies != [] as "Server should set a session Cookie on login"
47
48 let assert Ok(_) = list.key_find(cookies, session.cookie_name)
49 as "Target cookie found in the server response"
50}
51
52pub fn signup_test() {
53 use ctx <- app_test.global_data()
54 use _ <- list.each(list.range(1, app_test.n_tests))
55
56 let dummy_password = wisp.random_string(10)
57 let req =
58 simulate.browser_request(http.Post, "/admin/signup")
59 |> simulate.json_body(
60 json.object([
61 #("nome", wisp.random_string(10) |> json.string),
62 #("matricula", int.random(111) |> int.to_string |> json.string),
63 #("telefone", int.random(9_999_999_999) |> int.to_string |> json.string),
64 #("email", { wisp.random_string(12) <> "@email.com" } |> json.string),
65 #("senha", dummy_password |> json.string),
66 #("confirma_senha", dummy_password |> json.string),
67 #("cargo", dummy.random_role() |> role.to_string_pt_br() |> json.string),
68 ]),
69 )
70
71 let resp = http_router.handle_request(req, ctx)
72 assert resp.status == 401 as "Endpoint access should be restricted"
73
74 // AUTH -------------------------------------------------------------------
75 let with_auth = app_test.with_authorization(next: req)
76 let resp = http_router.handle_request(with_auth, ctx)
77 assert resp.status == 201 as "Response should be 201 Created"
78
79 let body = simulate.read_body(resp)
80
81 let assert Ok(_) =
82 json.parse(body, {
83 use id <- decode.field("id", decode.string)
84 case uuid.from_string(id) {
85 Error(_) -> decode.failure(uuid.v7(), "user_uuid")
86 Ok(value) -> decode.success(value)
87 }
88 })
89 as "Response should contain valid JSON data"
90
91 // CLEANUP ----------------------------------------------------------------
92 let assert Ok(_) = dev_sql.soft_truncate_user_account(ctx.db)
93}
94
95pub fn signup_registration_taken_test() {
96 use ctx <- app_test.global_data()
97
98 let dummy_pswd = wisp.random_string(10)
99 let taken_registration = "000"
100
101 let req =
102 simulate.browser_request(http.Post, "/admin/signup")
103 |> simulate.json_body(
104 json.object([
105 #("nome", wisp.random_string(10) |> json.string),
106 #("matricula", taken_registration |> json.string),
107 #("telefone", int.random(9_999_999_999) |> int.to_string |> json.string),
108 #("email", { wisp.random_string(12) <> "@email.com" } |> json.string),
109 #("senha", dummy_pswd |> json.string),
110 #("confirma_senha", dummy_pswd |> json.string),
111 #("cargo", dummy.random_role() |> role.to_string_pt_br() |> json.string),
112 ]),
113 )
114
115 let with_auth = app_test.with_authorization(next: req)
116 let resp = http_router.handle_request(with_auth, ctx)
117
118 assert resp.status == 409 as "Registration should be unique"
119}
120
121pub fn signup_email_taken_test() {
122 use ctx <- app_test.global_data()
123
124 let dummy_pswd = wisp.random_string(10)
125 let taken_email = "admin@email.com"
126
127 let req =
128 simulate.browser_request(http.Post, "/admin/signup")
129 |> simulate.json_body(
130 json.object([
131 #("nome", wisp.random_string(10) |> json.string),
132 #("matricula", int.random(111) |> int.to_string |> json.string),
133 #("telefone", int.random(9_999_999_999) |> int.to_string |> json.string),
134 #("email", taken_email |> json.string),
135 #("senha", dummy_pswd |> json.string),
136 #("confirma_senha", dummy_pswd |> json.string),
137 #("cargo", dummy.random_role() |> role.to_string_pt_br() |> json.string),
138 ]),
139 )
140
141 let with_auth = app_test.with_authorization(next: req)
142 let resp = http_router.handle_request(with_auth, ctx)
143 assert resp.status == 409 as "Email should be unique"
144}
145
146pub fn signup_phone_taken_test() {
147 use ctx <- app_test.global_data()
148
149 let dummy_pswd = wisp.random_string(10)
150 let taken_phone = "0000000000"
151
152 let req =
153 simulate.browser_request(http.Post, "/admin/signup")
154 |> simulate.json_body(
155 json.object([
156 #("nome", wisp.random_string(10) |> json.string),
157 #("matricula", int.random(111) |> int.to_string |> json.string),
158 #("telefone", taken_phone |> json.string),
159 #("email", { wisp.random_string(12) <> "@email.com" } |> json.string),
160 #("senha", dummy_pswd |> json.string),
161 #("confirma_senha", dummy_pswd |> json.string),
162 #("cargo", dummy.random_role() |> role.to_string_pt_br() |> json.string),
163 ]),
164 )
165
166 let with_auth = app_test.with_authorization(next: req)
167 let resp = http_router.handle_request(with_auth, ctx)
168 assert resp.status == 409 as "Phone should be unique"
169}
170
171pub fn get_all_users_test() {
172 use ctx <- app_test.global_data()
173
174 let req = simulate.browser_request(http.Get, "/admin/users")
175 let resp = http_router.handle_request(req, ctx)
176
177 assert resp.status == 401 as "Access only provided to Admin users"
178
179 // -------------------------------------------------------
180 let with_auth = app_test.with_authorization(next: req)
181 let resp = http_router.handle_request(with_auth, ctx)
182 assert resp.status == 200 as "Endpoint access should be available for Admins"
183
184 let body = simulate.read_body(resp)
185 assert string.is_empty(body) == False as "Response body should not be empty"
186
187 let assert Ok(_) =
188 json.parse(
189 body,
190 decode.list({
191 use _ <- decode.field("id", decode.string)
192 use _ <- decode.field("full_name", decode.string)
193 use _ <- decode.field("registration", decode.string)
194 use _ <- decode.field("email", decode.optional(decode.string))
195 use _ <- decode.field("user_role", decode.string)
196 decode.success(Nil)
197 }),
198 )
199 as "Response should contain valid JSON data"
200}
201
202pub fn update_user_profile_test() {
203 use ctx <- app_test.global_data()
204 use _ <- list.each(list.range(1, app_test.n_tests))
205 let login_path = "/user/login"
206 let signup_path = "/admin/signup"
207
208 // DUMMY ------------------------------------------------------------------
209 let dummy_password = "aluno"
210 let dummy_registration = "001"
211 let dummy_phone = "8190000000"
212 let dummy_email = "wibble@email.com"
213
214 let new_user_req =
215 simulate.browser_request(http.Post, signup_path)
216 |> simulate.json_body(
217 json.object([
218 #("nome", wisp.random_string(10) |> json.string),
219 #("matricula", dummy_registration |> json.string),
220 #("telefone", dummy_phone |> json.string),
221 #("email", dummy_email |> json.string),
222 #("senha", dummy_password |> json.string),
223 #("confirma_senha", dummy_password |> json.string),
224 #("cargo", role.to_string_pt_br(role.Firefighter) |> json.string),
225 ]),
226 )
227
228 let with_auth = app_test.with_authorization(new_user_req)
229 let new_user_resp = http_router.handle_request(with_auth, ctx)
230
231 let assert Ok(_) =
232 json.parse(simulate.read_body(new_user_resp), {
233 use maybe_uuid <- decode.field("id", decode.string)
234 case uuid.from_string(maybe_uuid) {
235 Error(_) -> decode.failure(uuid.v7(), "user_uuid")
236 Ok(value) -> decode.success(value)
237 }
238 })
239 as "Response contain invalid JSON"
240
241 let path = "/user/profile/update"
242 let login_req =
243 simulate.browser_request(http.Post, login_path)
244 |> simulate.json_body(
245 json.object([
246 #("matricula", json.string(dummy_registration)),
247 #("senha", json.string(dummy_password)),
248 ]),
249 )
250
251 let login_resp = http_router.handle_request(login_req, ctx)
252
253 // UPDATING DUMMY ------------------------------------------------------------
254 let new_name = wisp.random_string(8)
255 let new_email = wisp.random_string(6) <> "@email.com"
256 let new_phone = int.random(11) |> int.to_string
257
258 let req =
259 simulate.browser_request(http.Put, path)
260 |> simulate.json_body(
261 json.object([
262 #("full_name", json.string(new_name)),
263 #("email", json.string(new_email)),
264 #("phone", json.string(new_phone)),
265 ]),
266 )
267 |> simulate.session(login_req, login_resp)
268
269 let resp = http_router.handle_request(req, ctx)
270
271 // ASSERTIONS ----------------------------------------------------------------
272
273 // HAPPY PATH
274 assert resp.status == 200 as "Status should be HTTP 200 OK"
275 let body = simulate.read_body(resp)
276
277 let assert Ok(_) =
278 json.parse(body, {
279 use returned_full_name <- decode.field("full_name", decode.string)
280 use returned_email <- decode.field("email", decode.string)
281 use returned_phone <- decode.field("phone", decode.string)
282
283 assert returned_full_name == new_name as "Name was not updated"
284 assert returned_email == new_email as "Email was not updated"
285 assert returned_phone == new_phone as "Phone was not updated"
286
287 decode.success(Nil)
288 })
289 as "Response should contain valid JSON"
290
291 // EMAIL ALREADY TAKEN -------------------------------------------------------
292 {
293 let taken_email = "admin@email.com"
294 let req =
295 simulate.browser_request(http.Put, path)
296 |> simulate.json_body(
297 json.object([
298 #("full_name", json.string(new_name)),
299 #("email", json.string(taken_email)),
300 #("phone", json.string(new_phone)),
301 ]),
302 )
303 |> simulate.session(login_req, login_resp)
304
305 let resp = http_router.handle_request(req, ctx)
306 assert resp.status == 409 as "Status should be HTTP 409"
307 }
308
309 // PHONE ALREADY TAKEN -------------------------------------------------------
310 {
311 let taken_phone = "0000000000"
312 let req =
313 simulate.browser_request(http.Put, path)
314 |> simulate.json_body(
315 json.object([
316 #("full_name", json.string(new_name)),
317 #("email", json.string(new_email)),
318 #("phone", json.string(taken_phone)),
319 ]),
320 )
321 |> simulate.session(login_req, login_resp)
322 let resp = http_router.handle_request(req, ctx)
323 assert resp.status == 409 as "Status should be HTTP 409"
324 }
325
326 // CLEANUP ----------------------------------------------------------------
327 let assert Ok(_) = dev_sql.soft_truncate_user_account(ctx.db)
328}