an http based roguelike rpg about jelqing
Blame: tests/http.rs
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 1 | use std::sync::Arc; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 2 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 3 | use axum::{ |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 4 | Router, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 5 | body::{Body, to_bytes}, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 6 | http::{Method, Request, StatusCode, header}, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 7 | response::Response, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 8 | }; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 9 | use jelqd::{AppState, game::Run, router}; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 10 | use serde_json::Value; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 11 | use tower::ServiceExt; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 12 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 13 | async fn send( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 14 | app: &Router, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 15 | method: &str, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 16 | uri: &str, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 17 | headers: &[(&str, &str)], |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 18 | body: &str, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 19 | ) -> Response { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 20 | let mut request = Request::builder() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 21 | .method(Method::from_bytes(method.as_bytes()).unwrap()) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 22 | .uri(uri); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 23 | for (name, value) in headers { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 24 | request = request.header(*name, *value); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 25 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 26 | app.clone() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 27 | .oneshot(request.body(Body::from(body.to_owned())).unwrap()) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 28 | .await |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 29 | .unwrap() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 30 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 31 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 32 | async fn json(response: Response) -> Value { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 33 | serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap()).unwrap() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 34 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 35 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 36 | fn seeded(turn: u32) -> (Router, String) { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 37 | let state = Arc::new(AppState::default()); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 38 | let mut run = Run::new("cafebabe".into(), 69, 0); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 39 | run.turn = turn; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 40 | let etag = run.origin_etag.clone(); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 41 | state.insert(run); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 42 | (router(state), etag) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 43 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 44 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 45 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 46 | async fn creating_a_run_returns_location_and_etag() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 47 | let app = jelqd::app(); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 48 | let response = send(&app, "POST", "/runs?seed=1", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 49 | assert_eq!(response.status(), StatusCode::CREATED); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 50 | assert!(response.headers().contains_key(header::LOCATION)); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 51 | assert!(response.headers().contains_key(header::ETAG)); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 52 | assert_eq!(response.headers()[header::SERVER], "jelqd/0.6.9"); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 53 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 54 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 55 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 56 | async fn jelqing_cold_fails_the_precondition() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 57 | let (app, _) = seeded(0); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 58 | let response = send(&app, "JELQ", "/runs/cafebabe?technique=stretch", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 59 | assert_eq!(response.status(), StatusCode::PRECONDITION_FAILED); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 60 | assert_eq!( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 61 | response.headers()[header::CONTENT_TYPE], |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 62 | "application/problem+json" |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 63 | ); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 64 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 65 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 66 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 67 | async fn wet_without_lube_is_unsupported_media() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 68 | let (app, _) = seeded(0); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 69 | send(&app, "JELQ", "/runs/cafebabe?technique=warmup", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 70 | let response = send(&app, "JELQ", "/runs/cafebabe?technique=wet", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 71 | assert_eq!(response.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 72 | let images = send( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 73 | &app, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 74 | "JELQ", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 75 | "/runs/cafebabe?technique=wet", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 76 | &[("content-type", "image/jpeg")], |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 77 | "", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 78 | ) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 79 | .await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 80 | assert_eq!(json(images).await["detail"], "No."); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 81 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 82 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 83 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 84 | async fn unknown_methods_are_not_implemented() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 85 | let (app, _) = seeded(0); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 86 | let response = send(&app, "MILK", "/runs/cafebabe", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 87 | assert_eq!(response.status(), StatusCode::NOT_IMPLEMENTED); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 88 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 89 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 90 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 91 | async fn patch_only_accepts_the_truth() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 92 | let (app, _) = seeded(0); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 93 | let patch = [("content-type", "application/json-patch+json")]; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 94 | let replace = send( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 95 | &app, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 96 | "PATCH", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 97 | "/runs/cafebabe", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 98 | &patch, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 99 | r#"[{"op":"replace","path":"/length","value":12}]"#, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 100 | ) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 101 | .await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 102 | assert_eq!(replace.status(), StatusCode::UNPROCESSABLE_ENTITY); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 103 | let lie = send( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 104 | &app, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 105 | "PATCH", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 106 | "/runs/cafebabe", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 107 | &patch, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 108 | r#"[{"op":"test","path":"/length","value":40}]"#, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 109 | ) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 110 | .await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 111 | assert_eq!( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 112 | json(lie).await["type"], |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 113 | "https://jelq.dev/problems/exaggeration" |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 114 | ); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 115 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 116 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 117 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 118 | async fn deleting_the_foreskin_requires_certainty() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 119 | let (app, _) = seeded(0); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 120 | let response = send(&app, "DELETE", "/runs/cafebabe/foreskin", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 121 | assert_eq!(response.status(), StatusCode::PRECONDITION_REQUIRED); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 122 | let etag = send(&app, "GET", "/runs/cafebabe/foreskin", &[], "") |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 123 | .await |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 124 | .headers()[header::ETAG] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 125 | .to_str() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 126 | .unwrap() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 127 | .to_owned(); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 128 | let response = send( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 129 | &app, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 130 | "DELETE", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 131 | "/runs/cafebabe/foreskin", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 132 | &[("if-match", &etag)], |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 133 | "", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 134 | ) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 135 | .await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 136 | assert_eq!(response.status(), StatusCode::NO_CONTENT); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 137 | let response = send(&app, "GET", "/runs/cafebabe/foreskin", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 138 | assert_eq!(response.status(), StatusCode::GONE); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 139 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 140 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 141 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 142 | async fn length_is_chunked_until_the_ruler() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 143 | let (app, _) = seeded(0); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 144 | let lie = send(&app, "GET", "/runs/cafebabe/length", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 145 | assert!(!lie.headers().contains_key(header::CONTENT_LENGTH)); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 146 | let found = send(&app, "POST", "/runs/cafebabe/drawer", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 147 | assert_eq!(found.status(), StatusCode::FOUND); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 148 | let truth = send(&app, "GET", "/runs/cafebabe/length", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 149 | let declared: usize = truth.headers()[header::CONTENT_LENGTH] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 150 | .to_str() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 151 | .unwrap() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 152 | .parse() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 153 | .unwrap(); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 154 | let body = to_bytes(truth.into_body(), usize::MAX).await.unwrap(); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 155 | assert_eq!(body.len(), declared); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 156 | assert!(body.starts_with(b"8=") && body.ends_with(b"D")); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 157 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 158 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 159 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 160 | async fn the_clinic_escalates_toward_honesty() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 161 | let (app, _) = seeded(20); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 162 | let mut hints = Vec::new(); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 163 | for _ in 0..3 { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 164 | let response = send( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 165 | &app, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 166 | "GET", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 167 | "/runs/cafebabe/diagnosis", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 168 | &[("authorization", "Excuse \"changing\"")], |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 169 | "", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 170 | ) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 171 | .await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 172 | assert_eq!(response.status(), StatusCode::UNAUTHORIZED); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 173 | hints.push( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 174 | response.headers()[header::WWW_AUTHENTICATE] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 175 | .to_str() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 176 | .unwrap() |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 177 | .to_owned(), |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 178 | ); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 179 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 180 | assert!(hints[2].contains("Be honest.")); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 181 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 182 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 183 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 184 | async fn the_true_ending_is_not_modified() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 185 | let (app, etag) = seeded(20); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 186 | let early = seeded(3).0; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 187 | let response = send(&early, "GET", "/runs/cafebabe/diagnosis", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 188 | assert_eq!(response.status(), StatusCode::TOO_EARLY); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 189 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 190 | let response = send( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 191 | &app, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 192 | "GET", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 193 | "/runs/cafebabe/diagnosis", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 194 | &[ |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 195 | ("authorization", "Bearer honesty"), |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 196 | ("if-none-match", &etag), |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 197 | ], |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 198 | "", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 199 | ) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 200 | .await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 201 | assert_eq!(response.status(), StatusCode::NOT_MODIFIED); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 202 | assert_eq!(response.headers()["x-diagnosis"], "normal"); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 203 | } |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 204 | |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 205 | #[tokio::test] |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 206 | async fn mom_accepts_a_known_excuse() { |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 207 | let state = Arc::new(AppState::default()); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 208 | let mut run = Run::new("cafebabe".into(), 69, 0); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 209 | run.mom_present = true; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 210 | state.insert(run); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 211 | let app = router(state); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 212 | let response = send(&app, "GET", "/runs/cafebabe", &[], "").await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 213 | assert_eq!(response.status(), StatusCode::UNAUTHORIZED); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 214 | assert_eq!(response.headers()["via"], "1.1 mom"); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 215 | let response = send( |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 216 | &app, |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 217 | "GET", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 218 | "/runs/cafebabe", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 219 | &[("authorization", "Excuse \"homework\"")], |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 220 | "", |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 221 | ) |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 222 | .await; |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 223 | assert_eq!(response.status(), StatusCode::OK); |
a9b016e4b248 | atagen | 2026-10-10 08:12 UTC | 224 | } |