atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
f48daa8adf591a211fbfdca2c98805b04b0db3c6
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/tests/mod.rsRust148 lines3.6 KB
1
mod body;
2
mod floors;
3
mod household;
4
mod meta;
5
mod methods;
6
mod rolls;
7
mod turns;
8
9
pub use std::{sync::Arc, time::Duration};
10
11
pub use axum::{
12
    Router,
13
    body::{Body, to_bytes},
14
    http::{Method, Request, StatusCode, Version, header},
15
    response::Response,
16
};
17
pub use serde_json::Value;
18
use tower::ServiceExt;
19
20
pub use crate::{
21
    AppState, Config,
22
    game::{
23
        Excuse, Floor, MumVisit, Run, Story,
24
        balance::{BRANCH_TURN, SUSPICION_LIMIT},
25
    },
26
    router,
27
};
28
29
pub const SEED: u64 = 420;
30
31
pub async fn send(
32
    app: &Router,
33
    method: &str,
34
    uri: &str,
35
    headers: &[(&str, &str)],
36
    body: &str,
37
) -> Response {
38
    let mut request = Request::builder()
39
        .method(Method::from_bytes(method.as_bytes()).unwrap())
40
        .uri(uri);
41
    for (name, value) in headers {
42
        request = request.header(*name, *value);
43
    }
44
    app.clone()
45
        .oneshot(request.body(Body::from(body.to_owned())).unwrap())
46
        .await
47
        .unwrap()
48
}
49
50
pub async fn json(response: Response) -> Value {
51
    serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap()).unwrap()
52
}
53
54
pub async fn text(response: Response) -> String {
55
    String::from_utf8(
56
        to_bytes(response.into_body(), usize::MAX)
57
            .await
58
            .unwrap()
59
            .to_vec(),
60
    )
61
    .unwrap()
62
}
63
64
pub fn header<'a>(response: &'a Response, name: &str) -> &'a str {
65
    response.headers()[name].to_str().unwrap()
66
}
67
68
/// Every `Warning` on a response, since a turn can carry several.
69
pub fn warnings(response: &Response) -> Vec<String> {
70
    response
71
        .headers()
72
        .get_all("warning")
73
        .iter()
74
        .map(|value| value.to_str().unwrap().to_owned())
75
        .collect()
76
}
77
78
/// A server holding one run, `cafebabe`, set up by `setup` before anyone can reach it.
79
pub struct Harness {
80
    pub app: Router,
81
    pub origin: String,
82
}
83
84
pub fn harness(floor: Floor, seed: u64, setup: impl FnOnce(&mut Run)) -> Harness {
85
    let state = Arc::new(AppState::default());
86
    let mut run = Run::new("cafebabe".into(), "cafe".into(), seed);
87
    run.floor = floor;
88
    setup(&mut run);
89
    let origin = run.origin_etag();
90
    state.insert(run);
91
    Harness {
92
        app: router(state),
93
        origin,
94
    }
95
}
96
97
pub fn seeded_with(floor: Floor, setup: impl FnOnce(&mut Run)) -> Router {
98
    harness(floor, SEED, setup).app
99
}
100
101
pub fn app_with(floor: Floor, seed: u64, setup: impl FnOnce(&mut Run)) -> Router {
102
    harness(floor, seed, setup).app
103
}
104
105
pub fn app() -> Router {
106
    crate::app(Config::default()).unwrap()
107
}
108
109
pub fn mum_at_the_door(run: &mut Run) {
110
    run.household.mum = Some(MumVisit {
111
        errand: crate::game::HEARD_A_NOISE,
112
        nonce: "abc".into(),
113
        strikes: 0,
114
        knocked: false,
115
    });
116
}
117
118
/// The `Link` entries on a response, as `(rel, title)` with the rel base stripped.
119
pub fn links(response: &Response) -> Vec<(String, Option<String>)> {
120
    header(response, "link")
121
        .split(", <")
122
        .filter_map(|entry| {
123
            let rel = entry.split("rels/").nth(1)?.split('"').next()?.to_owned();
124
            let title = entry
125
                .split("title=\"")
126
                .nth(1)
127
                .and_then(|t| t.split('"').next())
128
                .map(str::to_owned);
129
            Some((rel, title))
130
        })
131
        .collect()
132
}
133
134
pub fn advertised(response: &Response) -> Vec<String> {
135
    links(response)
136
        .into_iter()
137
        .filter(|(rel, _)| rel == "technique")
138
        .filter_map(|(_, title)| title)
139
        .collect()
140
}
141
142
pub fn linked_rels(response: &Response) -> Vec<String> {
143
    links(response)
144
        .into_iter()
145
        .map(|(rel, _)| rel)
146
        .filter(|rel| rel != "technique")
147
        .collect()
148
}