rocket-pinboard/src/handlers/list.rs

173 lines
5.9 KiB
Rust

use rocket::State;
use rocket_contrib::Json;
use super::super::ListStore;
use super::super::models::list::List;
#[get("/", format = "application/json")]
fn index(lists: State<ListStore>) -> Option<Json<Vec<List>>> {
let lists = lists.read().unwrap();
Some(Json(lists.clone()))
}
#[get("/<list_id>", format = "text/html")]
fn show_html(list_id: String, lists: State<ListStore>) -> Option<String> {
let lists = lists.read().unwrap();
let list = lists.iter().find( |list| list.id == list_id )?;
Some(list.to_html())
}
#[get("/<list_id>", format = "application/json")]
fn show_json(list_id: String, lists: State<ListStore>) -> Option<Json<List>> {
let lists = lists.read().unwrap();
let list = lists.iter().find( |list| list.id == list_id )?;
Some(Json(list.clone()))
}
#[put("/<list_id>", format = "application/json", data = "<new_list>")]
fn update(list_id: String, new_list: Json<List>, lists: State<ListStore>) -> Option<Json<List>> {
let mut lists = lists.write().unwrap();
let list = lists.iter_mut().find( |list| list.id == list_id )?;
list.update_data(&new_list.data);
Some(Json(list.clone()))
}
#[cfg(test)]
mod tests {
use rocket;
use rocket::http::{Accept, ContentType, Status};
use rocket::local::Client;
use serde_json;
use super::*;
#[test]
fn index() {
let client = Client::new(rocket(Some("test"))).unwrap();
// Try to get all the lists
let mut res = client.get("/lists").header(Accept::JSON).dispatch();
assert_eq!(res.status(), Status::Ok);
let body = res.body_string().unwrap();
let lists = serde_json::from_str::<Vec<List>>(body.as_str()).unwrap();
assert_eq!(lists[0].id, "test");
assert_eq!(lists[0].index, 0);
assert_eq!(lists[0].name, "Test");
assert_eq!(lists[0].data, "This is a test list\n\n* One\n* Two\n* Three\n");
// The mtime field can vary, don't test for it
// The path field is private, also don't test for it
// Cannot get the lists in HTML format
let res = client.get("/lists").header(Accept::HTML).dispatch();
assert_eq!(res.status(), Status::NotFound);
}
#[test]
fn show_html() {
let client = Client::new(rocket(Some("test"))).unwrap();
// Try to get the list and verify the body
let mut res = client.get("/lists/test").header(Accept::HTML).dispatch();
assert_eq!(res.status(), Status::Ok);
let body = res.body_string().unwrap();
assert_eq!(body,
r#"<p>This is a test list</p>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
"#);
}
#[test]
fn show_json() {
let client = Client::new(rocket(Some("test"))).unwrap();
// Try to get the list and verify the body
let mut res = client.get("/lists/test").header(Accept::JSON).dispatch();
assert_eq!(res.status(), Status::Ok);
let body = res.body_string().unwrap();
let list = serde_json::from_str::<List>(body.as_str()).unwrap();
assert_eq!(list.id, "test");
assert_eq!(list.index, 0);
assert_eq!(list.name, "Test");
assert_eq!(list.data, "This is a test list\n\n* One\n* Two\n* Three\n");
// The mtime field can vary, don't test for it
// The path field is private, also don't test for it
// Try to get a list that doesn't exist
let res = client.get("/lists/doesntexit").header(Accept::JSON).dispatch();
assert_eq!(res.status(), Status::NotFound);
// FIXME: Test that there is some kind of error in the JSON
}
#[test]
fn update() {
let client = Client::new(rocket(Some("test"))).unwrap();
// Try to get the list and determine what to change it to
let mut res = client.get("/lists/updatable").header(Accept::JSON).dispatch();
let body = res.body_string().unwrap();
let list = serde_json::from_str::<List>(body.as_str()).unwrap();
assert_eq!(list.data, "Some content");
// Try to change the list data, then verify it was changed
let new_data = "New content";
let mut new_json: serde_json::Value = json!({
"id": "updatable",
"index": 1,
"data": new_data,
"mtime": {
"secs_since_epoch": 0,
"nanos_since_epoch": 0
},
"name": "Updatable",
"path": "test/lists/updatablelist"
});
let res = client.put("/lists/updatable")
.header(ContentType::JSON)
.body(new_json.to_string())
.dispatch();
assert_eq!(res.status(), Status::Ok);
let mut res = client.get("/lists/updatable")
.header(Accept::JSON)
.dispatch();
let body = res.body_string().unwrap();
let list = serde_json::from_str::<List>(body.as_str()).unwrap();
assert_eq!(list.data, new_data);
// ... and change it back
*new_json.get_mut("data").unwrap() = json!("Some content");
let res = client.put("/lists/updatable")
.header(ContentType::JSON)
.body(new_json.to_string())
.dispatch();
assert_eq!(res.status(), Status::Ok);
// Try to change a list that doesn't exist
let res = client.put("/lists/doesntexit")
.header(ContentType::JSON)
.body(new_json.to_string())
.dispatch();
assert_eq!(res.status(), Status::NotFound);
// Try to change a list without a proper body
let res = client.put("/lists/updatable")
.header(ContentType::JSON)
.body(r#"{}"#)
.dispatch();
assert_eq!(res.status(), Status::BadRequest);
// Try to change a list without a proper type (i.e. not JSON)
let res = client.put("/lists/updatable")
.header(ContentType::Plain)
.body("foo bar baz")
.dispatch();
assert_eq!(res.status(), Status::NotFound);
}
}