use rocket::serde::json::Json; use rocket::{get, put, State}; use super::super::models::note::Note; use super::super::NoteStore; #[get("/", format = "application/json")] pub(crate) async fn index(notes: &State) -> Option>> { let notes = notes.read().unwrap(); Some(Json(notes.clone())) } #[get("/", format = "text/html")] pub(crate) async fn show_html(note_id: String, notes: &State) -> Option { let notes = notes.read().unwrap(); let note = notes.iter().find(|note| note.id == note_id)?; Some(note.to_html()) } #[get("/", format = "application/json", rank = 2)] pub(crate) async fn show_json(note_id: String, notes: &State) -> Option> { let notes = notes.read().unwrap(); let note = notes.iter().find(|note| note.id == note_id)?; Some(Json(note.clone())) } #[put("/", format = "application/json", data = "")] pub(crate) async fn update( note_id: String, new_note: Json, notes: &State, ) -> Option> { let mut notes = notes.write().unwrap(); let note = notes.iter_mut().find(|note| note.id == note_id)?; note.update_data(&new_note.data); Some(Json(note.clone())) } #[cfg(test)] mod tests { use rocket; use rocket::http::{Accept, ContentType, Status}; use rocket::local::blocking::Client; use serde_json::{self, json}; use super::*; #[test] fn index() { let client = Client::untracked(crate::build_rocket(Some("test"))).unwrap(); // Try to get all the notes let res = client.get("/notes").header(Accept::JSON).dispatch(); assert_eq!(res.status(), Status::Ok); let body = res.into_string().unwrap(); let notes = serde_json::from_str::>(body.as_str()).unwrap(); assert_eq!(notes[0].id, "test"); assert_eq!(notes[0].index, 0); assert_eq!(notes[0].name, "Test"); assert_eq!( notes[0].data, "This is a test note\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 notes in HTML format let res = client.get("/notes").header(Accept::HTML).dispatch(); assert_eq!(res.status(), Status::NotFound); } #[test] fn show_html() { let client = Client::untracked(crate::build_rocket(Some("test"))).unwrap(); // Try to get the note and verify the body let res = client.get("/notes/test").header(Accept::HTML).dispatch(); assert_eq!(res.status(), Status::Ok); let body = res.into_string().unwrap(); assert_eq!( body, r#"

This is a test note

  • One
  • Two
  • Three
"# ); } #[test] fn show_json() { let client = Client::untracked(crate::build_rocket(Some("test"))).unwrap(); // Try to get the note and verify the body let res = client.get("/notes/test").header(Accept::JSON).dispatch(); assert_eq!(res.status(), Status::Ok); let body = res.into_string().unwrap(); let note = serde_json::from_str::(body.as_str()).unwrap(); assert_eq!(note.id, "test"); assert_eq!(note.index, 0); assert_eq!(note.name, "Test"); assert_eq!(note.data, "This is a test note\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 note that doesn't exist let res = client .get("/notes/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::untracked(crate::build_rocket(Some("test"))).unwrap(); // Try to get the note and determine what to change it to let res = client .get("/notes/updatable") .header(Accept::JSON) .dispatch(); let body = res.into_string().unwrap(); let note = serde_json::from_str::(body.as_str()).unwrap(); assert_eq!(note.data, "Some content"); // Try to change the note 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/notes/updatablenote" }); let res = client .put("/notes/updatable") .header(ContentType::JSON) .body(new_json.to_string()) .dispatch(); assert_eq!(res.status(), Status::Ok); let res = client .get("/notes/updatable") .header(Accept::JSON) .dispatch(); let body = res.into_string().unwrap(); let note = serde_json::from_str::(body.as_str()).unwrap(); assert_eq!(note.data, new_data); // ... and change it back *new_json.get_mut("data").unwrap() = json!("Some content"); let res = client .put("/notes/updatable") .header(ContentType::JSON) .body(new_json.to_string()) .dispatch(); assert_eq!(res.status(), Status::Ok); // Try to change a note that doesn't exist let res = client .put("/notes/doesntexit") .header(ContentType::JSON) .body(new_json.to_string()) .dispatch(); assert_eq!(res.status(), Status::NotFound); // Try to change a note without a proper body let res = client .put("/notes/updatable") .header(ContentType::JSON) .body(r#"{}"#) .dispatch(); assert_eq!(res.status().code, 422); // Try to change a note without a proper type (i.e. not JSON) let res = client .put("/notes/updatable") .header(ContentType::Plain) .body("foo bar baz") .dispatch(); assert_eq!(res.status(), Status::NotFound); } }