atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
ea51d9fda49d82c38cf3920e34d6be05d8398cae
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/tests/methods.rsRust153 lines6.1 KB
1
use super::*;
2
3
#[tokio::test]
4
async fn creating_a_run_returns_location_and_etag() {
5
    let response = send(&app(), "POST", "/runs?seed=1", &[], "").await;
6
    assert_eq!(response.status(), StatusCode::CREATED);
7
    assert!(header(&response, "location").starts_with("/runs/"));
8
    assert!(response.headers().contains_key(header::ETAG));
9
    assert_eq!(header(&response, "server"), "jelqd/0.6.9");
10
}
11
12
#[tokio::test]
13
async fn bodies_do_not_repeat_the_headers() {
14
    let Harness { app, .. } = harness(Floor::Bedroom, SEED, |_| {});
15
    let response = send(&app, "GET", "/runs/cafebabe", &[], "").await;
16
    assert!(response.headers().contains_key("x-eq"));
17
    assert_eq!(header(&response, "x-turn"), "0");
18
    assert_eq!(header(&response, "x-floor-turn"), "0/10");
19
    assert!(response.headers().get("x-floor-over").is_none());
20
    let body = json(response).await;
21
    for stat in [
22
        "eq",
23
        "girth",
24
        "foreskin",
25
        "stamina",
26
        "cash",
27
        "self_reported_length",
28
    ] {
29
        assert!(body.get(stat).is_none(), "{stat} is already a header");
30
    }
31
}
32
33
#[tokio::test]
34
async fn jelqing_cold_goes_through_at_a_price() {
35
    let friction = async |warm: bool| {
36
        let app = seeded_with(Floor::Bedroom, |run| {
37
            run.body.eq = if warm { 40 } else { 20 };
38
            run.body.foreskin = Some(1.0);
39
        });
40
        let response = send(&app, "JELQ", "/runs/cafebabe?technique=stretch", &[], "").await;
41
        let noted = warnings(&response).iter().any(|w| w.contains("Cold start"));
42
        assert_eq!(noted, !warm);
43
        header(&response, "x-friction").to_owned()
44
    };
45
    assert_eq!(friction(true).await, "1/10");
46
    assert_eq!(friction(false).await, "3/10");
47
}
48
49
#[tokio::test]
50
async fn wet_without_lube_is_unsupported_media() {
51
    let Harness { app, .. } = harness(Floor::Bedroom, SEED, |_| {});
52
    send(&app, "JELQ", "/runs/cafebabe?technique=warmup", &[], "").await;
53
    let response = send(&app, "JELQ", "/runs/cafebabe?technique=wet", &[], "").await;
54
    assert_eq!(response.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
55
    let images = send(
56
        &app,
57
        "JELQ",
58
        "/runs/cafebabe?technique=wet",
59
        &[("content-type", "image/jpeg")],
60
        "",
61
    )
62
    .await;
63
    assert_eq!(json(images).await["detail"], "No.");
64
}
65
66
#[tokio::test]
67
async fn unknown_methods_are_not_implemented() {
68
    let Harness { app, .. } = harness(Floor::Bedroom, SEED, |_| {});
69
    let response = send(&app, "MILK", "/runs/cafebabe", &[], "").await;
70
    assert_eq!(response.status(), StatusCode::NOT_IMPLEMENTED);
71
    let teapot = send(&app, "BREW", "/runs/cafebabe", &[], "").await;
72
    assert_eq!(teapot.status(), StatusCode::IM_A_TEAPOT);
73
}
74
75
#[tokio::test]
76
async fn the_clinic_does_not_advertise_jelq() {
77
    let Harness { app, .. } = harness(Floor::Clinic, SEED, |_| {});
78
    let options = send(&app, "OPTIONS", "/runs/cafebabe", &[], "").await;
79
    assert!(!header(&options, "allow").contains("JELQ"));
80
    let jelq = send(&app, "JELQ", "/runs/cafebabe?technique=wet", &[], "").await;
81
    assert_eq!(jelq.status(), StatusCode::METHOD_NOT_ALLOWED);
82
    assert!(!header(&jelq, "allow").contains("JELQ"));
83
    let Harness { app: bedroom, .. } = harness(Floor::Bedroom, SEED, |_| {});
84
    let options = send(&bedroom, "OPTIONS", "/runs/cafebabe", &[], "").await;
85
    assert!(header(&options, "allow").contains("JELQ"));
86
}
87
88
#[tokio::test]
89
async fn http_1_0_gets_the_pdf_treatment() {
90
    let request = Request::builder()
91
        .uri("/graveyard")
92
        .version(Version::HTTP_10)
93
        .body(Body::empty())
94
        .unwrap();
95
    let response = app().oneshot(request).await.unwrap();
96
    assert_eq!(response.status(), StatusCode::HTTP_VERSION_NOT_SUPPORTED);
97
}
98
99
#[tokio::test]
100
async fn links_offer_only_usable_techniques() {
101
    let app = seeded_with(Floor::Bedroom, |run| run.body.foreskin = Some(1.0));
102
    let cold = send(&app, "GET", "/runs/cafebabe", &[], "").await;
103
    assert!(
104
        advertised(&cold).contains(&"stretch".to_owned()),
105
        "a cold jelq is allowed"
106
    );
107
    let warm = send(&app, "JELQ", "/runs/cafebabe?technique=warmup", &[], "").await;
108
    let usable = advertised(&warm);
109
    assert!(usable.contains(&"wet".to_owned()) && usable.contains(&"dry".to_owned()));
110
    assert!(!usable.contains(&"uli".to_owned()), "uli needs the forum");
111
    assert!(!usable.contains(&"pump".to_owned()), "pump needs a pump");
112
    assert!(
113
        header(&warm, "link")
114
            .contains("title=\"wet\"; allow=\"JELQ\"; lubricant=\"required\"; intensity=\"1-10\"")
115
    );
116
    let edge = header(&warm, "link")
117
        .split(", ")
118
        .find(|link| link.contains("title=\"edge\""))
119
        .unwrap();
120
    assert!(
121
        edge.ends_with("allow=\"JELQ\"; lubricant=\"optional\""),
122
        "an edge takes lube but no intensity"
123
    );
124
125
    let Harness { app: forum, .. } = harness(Floor::Forum, SEED, |_| {});
126
    let response = send(&forum, "GET", "/runs/cafebabe", &[], "").await;
127
    assert!(advertised(&response).is_empty());
128
}
129
130
#[tokio::test]
131
async fn links_hide_resources_that_would_do_nothing() {
132
    let Harness { app: bedroom, .. } = harness(Floor::Bedroom, SEED, |_| {});
133
    let before = linked_rels(&send(&bedroom, "GET", "/runs/cafebabe", &[], "").await);
134
    assert!(before.contains(&"drawer".to_owned()));
135
    assert!(!before.contains(&"diagnosis".to_owned()));
136
    assert!(!before.contains(&"thread".to_owned()));
137
    let searched = send(&bedroom, "POST", "/runs/cafebabe/drawer", &[], "").await;
138
    assert!(!linked_rels(&searched).contains(&"drawer".to_owned()));
139
140
    let Harness { app: clinic, .. } = harness(Floor::Clinic, SEED, |_| {});
141
    let rels = linked_rels(&send(&clinic, "GET", "/runs/cafebabe", &[], "").await);
142
    assert!(rels.contains(&"diagnosis".to_owned()) && rels.contains(&"thread".to_owned()));
143
}
144
145
#[tokio::test]
146
async fn an_ended_run_names_its_cause() {
147
    let app = seeded_with(Floor::Bedroom, |_| {});
148
    let abandoned = send(&app, "DELETE", "/runs/cafebabe", &[], "").await;
149
    assert_eq!(header(&abandoned, "x-run-over"), "abandoned");
150
    let after = send(&app, "GET", "/runs/cafebabe", &[], "").await;
151
    assert_eq!(after.status(), StatusCode::GONE);
152
    assert_eq!(header(&after, "x-run-over"), "abandoned");
153
}