wip: currently rewriting the project as a full stack application tangled.org/kacaii.dev/sigo
gleam
at main 377 lines 13 kB view raw
1import app/domain/occurrence/category 2import app/domain/occurrence/priority 3import app/domain/occurrence/sql as o_sql 4import app/domain/occurrence/subcategory 5import app/http_router 6import app/web 7import app_dev/sql as dev_sql 8import app_test 9import dummy 10import gleam/dynamic/decode 11import gleam/float 12import gleam/http 13import gleam/json 14import gleam/list 15import gleam/option 16import gleam/set 17import wisp 18import wisp/simulate 19import youid/uuid 20 21pub fn register_new_occurrence_test() { 22 use ctx <- app_test.global_data() 23 use _ <- list.each(list.range(1, app_test.n_tests)) 24 25 // DUMMY USERS ----------------------------------------------------------- 26 let dummy_applicant_id = dummy.random_user(ctx.db) 27 let dummy_participants_id = { 28 list.map(list.range(0, 12), fn(_) { dummy.random_user(ctx.db) }) 29 } 30 31 // DUMMY BRIGADE ------------------------------------------------------------- 32 let dummy_brigade_id = 33 dummy.random_brigade( 34 conn: ctx.db, 35 leader_id: dummy_applicant_id, 36 members: dummy_participants_id, 37 ) 38 39 // REQUEST ------------------------------------------------------------------- 40 let oc_category = category.to_string(dummy.random_category()) 41 let oc_subcategory = subcategory.to_string(dummy.random_subcategory()) 42 let oc_priority = priority.to_string(dummy.random_priority()) 43 let coords = [float.random() *. 100.0, float.random() *. 100.0] 44 let oc_assigned_brigades = 45 json.array([uuid.to_string(dummy_brigade_id)], json.string) 46 47 let req = 48 simulate.browser_request(http.Post, "/occurrence/new") 49 |> simulate.json_body( 50 json.object([ 51 #("categoria", json.string(oc_category)), 52 #("subcategoria", json.string(oc_subcategory)), 53 #("prioridade", json.string(oc_priority)), 54 #("descricao", json.string(wisp.random_string(33))), 55 #("gps", json.array(coords, json.float)), 56 #("pontoDeReferencia", json.string(wisp.random_string(33))), 57 #("idEquipes", oc_assigned_brigades), 58 ]), 59 ) 60 61 // RESPONSE ------------------------------------------------------------------ 62 let resp = http_router.handle_request(req, ctx) 63 assert resp.status != 422 as "Invalid request Payload" 64 assert resp.status == 401 as "Endpoint restricted to authenticated users" 65 66 let with_auth = app_test.with_authorization(next: req) 67 let resp = http_router.handle_request(with_auth, ctx) 68 assert resp.status == 201 as "HTTP 201 Created" 69 70 // JSON PARSING -------------------------------------------------------------- 71 let body = simulate.read_body(resp) 72 let assert Ok(dummy_occurrence_id) = 73 json.parse(body, { 74 use _ <- decode.field("priority", priority.decoder_pt_br()) 75 76 use dummy_occurrence_id <- decode.field( 77 "id", 78 web.uuid_decoder("occurrence_uuid"), 79 ) 80 81 use _ <- decode.field( 82 "applicant_id", 83 decode.optional(web.uuid_decoder("applicant_uuid")), 84 ) 85 86 use _ <- decode.field( 87 "assigned_brigades", 88 decode.list(web.uuid_decoder("brigade_uuid")), 89 ) 90 91 use _ <- decode.field("created_at", decode.float) 92 93 decode.success(dummy_occurrence_id) 94 }) 95 as "Response contain valid JSON" 96 97 // Check if users were registered as participants ---------------------------- 98 let dummy_participants_set = set.from_list(dummy_participants_id) 99 100 let registered_participants_set = 101 set.from_list({ 102 let assert Ok(returned) = 103 o_sql.query_participants(ctx.db, dummy_occurrence_id) 104 as "Query occurrence participants" 105 106 use row <- list.map(returned.rows) 107 row.user_id 108 }) 109 110 assert set.difference(registered_participants_set, dummy_participants_set) 111 |> set.to_list() 112 == [] 113 as "Registered members contain all expected users" 114 115 assert set.difference(dummy_participants_set, registered_participants_set) 116 |> set.to_list() 117 == [] 118 as "Participants were assigned correclty" 119 120 // 󰃢 CLEANUP ---------------------------------------------------------------- 121 let assert Ok(_) = dev_sql.truncate_occurrence(ctx.db) 122 let assert Ok(_) = dev_sql.truncate_brigade(ctx.db) 123 let assert Ok(_) = dev_sql.soft_truncate_user_account(ctx.db) 124} 125 126pub fn get_occurrences_by_applicant_test() { 127 use ctx <- app_test.global_data() 128 use _ <- list.each(list.range(1, app_test.n_tests)) 129 130 // DUMMY USERS ----------------------------------------------------------- 131 let dummy_applicant_id = dummy.random_user(ctx.db) 132 let dummy_participants_id = { 133 list.map(list.range(0, 12), fn(_) { dummy.random_user(ctx.db) }) 134 } 135 136 // DUMMY BRIGADE ------------------------------------------------------------- 137 let dummy_brigade_id = 138 dummy.random_brigade( 139 conn: ctx.db, 140 leader_id: dummy_applicant_id, 141 members: dummy_participants_id, 142 ) 143 144 // DUMMY OCCURRENCE ---------------------------------------------------------- 145 let dummy_occurrence = 146 dummy.random_occurrence(ctx.db, dummy_applicant_id, [dummy_brigade_id]) 147 148 let path = "/user/" <> uuid.to_string(dummy_applicant_id) <> "/occurrences" 149 let req = simulate.browser_request(http.Get, path) 150 151 let resp = http_router.handle_request(req, ctx) 152 let body = simulate.read_body(resp) 153 assert resp.status == 200 154 155 // JSON PARSING -------------------------------------------------------------- 156 let assert Ok(_) = 157 json.parse(body, { 158 let call_decoder = { 159 use _ <- decode.field("tipo", category.decoder_pt_br()) 160 use _ <- decode.field("detalhes", decode.string) 161 use _ <- decode.field("solicitante", { 162 use name <- decode.field("nome", decode.string) 163 decode.success(name) 164 }) 165 decode.success(Nil) 166 } 167 168 let occurrence_timestamp_decoder = { 169 use _ <- decode.field("abertura", decode.float) 170 use _ <- decode.field("chegadaNoLocal", decode.optional(decode.float)) 171 use _ <- decode.field("finalizacao", decode.optional(decode.float)) 172 decode.success(Nil) 173 } 174 175 let occurrence_metadata_decoder = { 176 use _ <- decode.field("usuarioId", web.uuid_decoder("user_uuid")) 177 use _ <- decode.field("matriculaUsuario", decode.string) 178 use _ <- decode.field("nomeUsuario", decode.string) 179 decode.success(Nil) 180 } 181 182 let occurrence_brigade_list_decoder = 183 decode.list({ 184 use _ <- decode.field("id", web.uuid_decoder("brigade_uuid")) 185 use _ <- decode.field("nomeEquipe", decode.string) 186 use _ <- decode.field("codigoViatura", decode.string) 187 use _ <- decode.field("lider", decode.string) 188 decode.success(Nil) 189 }) 190 191 decode.list({ 192 use id <- decode.field("id", web.uuid_decoder("call_uuid?")) 193 use _ <- decode.field("status", decode.string) 194 use _ <- decode.field("prioridade", priority.decoder_pt_br()) 195 use _ <- decode.field("chamado", call_decoder) 196 use _ <- decode.field( 197 "coordenadas", 198 decode.optional(decode.list(decode.float)), 199 ) 200 use _ <- decode.field("timestamps", occurrence_timestamp_decoder) 201 use _ <- decode.field("metadata", occurrence_metadata_decoder) 202 use _ <- decode.field("equipes", occurrence_brigade_list_decoder) 203 204 assert id == dummy_occurrence 205 as "Occurence uuid should be the same as the dummy one" 206 207 decode.success(Nil) 208 }) 209 }) 210 211 // 󰃢 CLEANUP ---------------------------------------------------------------- 212 let assert Ok(_) = dev_sql.truncate_occurrence(ctx.db) 213 let assert Ok(_) = dev_sql.truncate_brigade(ctx.db) 214 let assert Ok(_) = dev_sql.soft_truncate_user_account(ctx.db) 215} 216 217pub fn delete_occurrence_test() { 218 use ctx <- app_test.global_data() 219 use _ <- list.each(list.range(1, app_test.n_tests)) 220 221 // DUMMY 222 let dummy_applicant = dummy.random_user(ctx.db) 223 let dummy_occurrence = 224 dummy.random_occurrence(ctx.db, applicant_id: dummy_applicant, assign: []) 225 226 let path = "/occurrence/" <> uuid.to_string(dummy_occurrence) 227 let req = simulate.request(http.Delete, path) 228 let resp = http_router.handle_request(req, ctx) 229 230 assert resp.status == 401 as "Only accessible to Admins" 231 232 let with_auth = app_test.with_authorization(req) 233 let resp = http_router.handle_request(with_auth, ctx) 234 235 assert resp.status == 200 as "Status should be HTTP 200 OK" 236 237 let body = simulate.read_body(resp) 238 let assert Ok(deleted_occurrence) = 239 json.parse(body, { 240 use id <- decode.field("id", web.uuid_decoder("occurrence_uuid")) 241 decode.success(id) 242 }) 243 244 assert deleted_occurrence == dummy_occurrence 245 as "Deleted the wrong Occurrence" 246 247 // 󰃢 CLEANUP ---------------------------------------------------------------- 248 let assert Ok(_) = dev_sql.soft_truncate_user_account(ctx.db) 249} 250 251pub fn close_occurrence_test() { 252 use ctx <- app_test.global_data() 253 let base_path = "/occurrence/close/" 254 use _ <- list.each(list.range(1, app_test.n_tests)) 255 256 // DUMMY --------------------------------------------------------------------- 257 let dummy_applicant = dummy.random_user(ctx.db) 258 let dummy_members = 259 list.map(list.range(1, 10), fn(_) { dummy.random_user(ctx.db) }) 260 261 let dummy_brigade = 262 dummy.random_brigade(ctx.db, dummy_applicant, dummy_members) 263 264 let dummy_occurrence = 265 dummy.random_occurrence( 266 conn: ctx.db, 267 applicant_id: dummy_applicant, 268 assign: [dummy_brigade], 269 ) 270 271 let path = base_path <> uuid.to_string(dummy_occurrence) 272 let req = simulate.request(http.Post, path) 273 let resp = http_router.handle_request(req, ctx) 274 275 assert resp.status == 401 as "Restricted to authenticated Users" 276 277 // Response decoder 278 let resp_decoder = { 279 let resolved_at_decoder = decode.optional(decode.float) 280 281 use occ_id <- decode.field("id", web.uuid_decoder("occurrence_uuid")) 282 use resolved_at <- decode.field("resolved_at", resolved_at_decoder) 283 use _ <- decode.field("updated_at", decode.float) 284 285 assert option.is_some(resolved_at) as "Occurrence should be closed" 286 assert occ_id == dummy_occurrence as "Update the correct occurrence" 287 decode.success(Nil) 288 } 289 290 let _happy_path = { 291 let req = app_test.with_authorization(req) 292 let resp = http_router.handle_request(req, ctx) 293 let body = simulate.read_body(resp) 294 295 let assert Ok(_) = json.parse(body, resp_decoder) 296 as "Json response should be valid" 297 } 298 299 // 󰃢 CLEANUP ---------------------------------------------------------------- 300 let assert Ok(_) = dev_sql.truncate_occurrence(ctx.db) 301 let assert Ok(_) = dev_sql.truncate_brigade(ctx.db) 302 let assert Ok(_) = dev_sql.soft_truncate_user_account(ctx.db) 303} 304 305pub fn close_missing_occurrence_test() { 306 use ctx <- app_test.global_data() 307 let base_path = "/occurrence/close/" 308 let path = base_path <> uuid.v7_string() 309 310 let req = 311 simulate.browser_request(http.Post, path) 312 |> app_test.with_authorization() 313 314 let resp = http_router.handle_request(req, ctx) 315 assert resp.status == 404 as "Cant resolve missing occurrence" 316} 317 318pub fn reopen_occurrence_test() { 319 use ctx <- app_test.global_data() 320 let base_path = "/occurrence/reopen/" 321 use _ <- list.each(list.range(1, app_test.n_tests)) 322 323 // DUMMY --------------------------------------------------------------------- 324 let dummy_applicant = dummy.random_user(ctx.db) 325 let dummy_members = 326 list.map(list.range(1, 10), fn(_) { dummy.random_user(ctx.db) }) 327 328 let dummy_brigade = 329 dummy.random_brigade(ctx.db, dummy_applicant, dummy_members) 330 331 let dummy_occurrence = 332 dummy.random_occurrence( 333 conn: ctx.db, 334 applicant_id: dummy_applicant, 335 assign: [dummy_brigade], 336 ) 337 338 let path = base_path <> uuid.to_string(dummy_occurrence) 339 let req = simulate.request(http.Post, path) 340 let resp = http_router.handle_request(req, ctx) 341 342 assert resp.status == 401 as "Restricted to authenticated Users" 343 let req = app_test.with_authorization(req) 344 let resp = http_router.handle_request(req, ctx) 345 let body = simulate.read_body(resp) 346 347 let assert Ok(_) = 348 json.parse(body, { 349 let resolved_at_decoder = decode.optional(decode.float) 350 351 use occ_id <- decode.field("id", web.uuid_decoder("occurrence_uuid")) 352 use resolved_at <- decode.field("resolved_at", resolved_at_decoder) 353 use _ <- decode.field("updated_at", decode.float) 354 355 assert option.is_none(resolved_at) as "Occurrence should be open" 356 assert occ_id == dummy_occurrence as "Update the correct occurrence" 357 decode.success(Nil) 358 }) 359 360 // 󰃢 CLEANUP ---------------------------------------------------------------- 361 let assert Ok(_) = dev_sql.truncate_occurrence(ctx.db) 362 let assert Ok(_) = dev_sql.truncate_brigade(ctx.db) 363 let assert Ok(_) = dev_sql.soft_truncate_user_account(ctx.db) 364} 365 366pub fn reopen_missing_occurrence_test() { 367 use ctx <- app_test.global_data() 368 let base_path = "/occurrence/reopen/" 369 let path = base_path <> uuid.v7_string() 370 371 let req = 372 simulate.browser_request(http.Post, path) 373 |> app_test.with_authorization() 374 375 let resp = http_router.handle_request(req, ctx) 376 assert resp.status == 404 as "Cant reopen missing occurrence" 377}