use {
http::{header, Request, StatusCode},
tsukuyomi::{
config::prelude::*, extractor,
App,
},
tsukuyomi_server::test::ResponseExt,
};
#[test]
fn empty_routes() -> tsukuyomi_server::Result<()> {
let app = App::create(())?;
let mut server = tsukuyomi_server::test::server(app)?;
let response = server.perform("/")?;
assert_eq!(response.status(), StatusCode::NOT_FOUND);
Ok(())
}
#[test]
fn single_route() -> tsukuyomi_server::Result<()> {
let app = App::create(
path!("/hello") .to(endpoint::call(|| "Tsukuyomi")),
)?;
let mut server = tsukuyomi_server::test::server(app)?;
let response = server.perform("/hello")?;
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(
response.header(header::CONTENT_TYPE)?,
"text/plain; charset=utf-8"
);
assert_eq!(response.header(header::CONTENT_LENGTH)?, "9");
assert_eq!(*response.body().to_bytes(), b"Tsukuyomi"[..]);
Ok(())
}
#[test]
fn post_body() -> tsukuyomi_server::Result<()> {
let app = App::create(
path!("/hello") .to(endpoint::post()
.extract(tsukuyomi::extractor::body::plain())
.call(|body: String| body)),
)?;
let mut server = tsukuyomi_server::test::server(app)?;
let response = server.perform(
Request::post("/hello") .body("Hello, Tsukuyomi."),
)?;
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(
response.header(header::CONTENT_TYPE)?,
"text/plain; charset=utf-8"
);
assert_eq!(response.header(header::CONTENT_LENGTH)?, "17");
assert_eq!(*response.body().to_bytes(), b"Hello, Tsukuyomi."[..]);
Ok(())
}
#[test]
fn cookies() -> tsukuyomi_server::Result<()> {
use cookie::Cookie;
use time::Duration;
let expires_in = time::now() + Duration::days(7);
let app = App::create(chain![
path!("/login") .to(endpoint::any()
.extract(extractor::ready(move |input| {
input.cookies.jar()?.add(
Cookie::build("session", "dummy_session_id")
.domain("www.example.com")
.expires(expires_in)
.finish(),
);
Ok::<_, tsukuyomi::error::Error>(())
}))
.call(|| "Logged in")),
path!("/logout") .to(endpoint::any()
.extract(extractor::ready(|input| {
input.cookies.jar()?.remove(Cookie::named("session"));
Ok::<_, tsukuyomi::error::Error>(())
}))
.call(|| "Logged out")),
])?;
let mut server = tsukuyomi_server::test::server(app)?;
let response = server.perform("/login")?;
let cookie_str = response.header(header::SET_COOKIE)?.to_str()?;
let cookie = Cookie::parse_encoded(cookie_str)?;
assert_eq!(cookie.name(), "session");
assert_eq!(cookie.domain(), Some("www.example.com"));
assert_eq!(
cookie.expires().map(|tm| tm.to_timespec().sec),
Some(expires_in.to_timespec().sec)
);
let response = server.perform(Request::get("/logout").header(header::COOKIE, cookie_str))?;
let cookie_str = response.header(header::SET_COOKIE)?.to_str()?;
let cookie = Cookie::parse_encoded(cookie_str)?;
assert_eq!(cookie.name(), "session");
assert_eq!(cookie.value(), "");
assert_eq!(cookie.max_age(), Some(Duration::zero()));
assert!(cookie.expires().map_or(false, |tm| tm < time::now()));
let response = server.perform("/logout")?;
assert!(!response.headers().contains_key(header::SET_COOKIE));
Ok(())
}
#[test]
fn default_options() -> tsukuyomi_server::Result<()> {
let app = App::create(
path!("/path")
.to(endpoint::allow_only("GET, POST")?.call(|| "reply"))
.modify(tsukuyomi::modifiers::default_options()),
)?;
let mut server = tsukuyomi_server::test::server(app)?;
let response = server.perform("/path")?;
assert_eq!(response.status(), 200);
assert_eq!(response.body().to_utf8()?, "reply");
let response = server.perform(Request::options("/path"))?;
assert_eq!(response.status(), 204);
assert_eq!(response.header(header::ALLOW)?, "GET, POST, OPTIONS");
assert_eq!(response.header(header::CONTENT_LENGTH)?, "0");
Ok(())
}
#[test]
fn map_output() -> tsukuyomi_server::Result<()> {
let app = App::create(
path!("/")
.to(endpoint::reply(42))
.modify(tsukuyomi::modifiers::map_output(|num: u32| num.to_string())),
)?;
let mut server = tsukuyomi_server::test::server(app)?;
let response = server.perform("/")?;
assert_eq!(response.body().to_utf8()?, "42");
Ok(())
}
#[test]
fn scoped_fallback() -> tsukuyomi_server::Result<()> {
use std::sync::{Arc, Mutex};
let marker = Arc::new(Mutex::new(vec![]));
let app = App::create(chain![
path!("*") .to(endpoint::call({
let marker = marker.clone();
move || {
marker.lock().unwrap().push("F1");
"f1"
}
})),
mount("/api/v1/").with(chain![
path!("*") .to(endpoint::call({
let marker = marker.clone();
move || {
marker.lock().unwrap().push("F2");
"f2"
}
})),
path!("/posts") .to(endpoint::post().reply("posts")),
mount("/events").with(
path!("/new") .to(endpoint::post().reply("new_event")),
),
]),
])?;
let mut server = tsukuyomi_server::test::server(app)?;
let _ = server.perform("/")?;
assert_eq!(&**marker.lock().unwrap(), &*vec!["F1"]);
marker.lock().unwrap().clear();
let _ = server.perform("/api/v1/p")?;
assert_eq!(&**marker.lock().unwrap(), &*vec!["F2"]);
marker.lock().unwrap().clear();
let _ = server.perform("/api/v1/posts")?;
assert!(marker.lock().unwrap().is_empty());
marker.lock().unwrap().clear();
let _ = server.perform("/api/v1/events/new")?;
assert!(marker.lock().unwrap().is_empty());
Ok(())
}