From 6deba9024a28606974e85a2f3b1f9b37ce4dffe9 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Salinas Date: Thu, 13 Apr 2023 22:56:13 -0400 Subject: [PATCH] chore: add tests --- Cargo.lock | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/place.rs | 2 +- src/routes.rs | 202 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 413 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90e7efe..6f39b6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,30 @@ dependencies = [ "tower-service", ] +[[package]] +name = "axum-test-helper" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91d349b3174ceac58442ea1f768233c817e59447c0343be2584fca9f0ed71d3a" +dependencies = [ + "axum", + "bytes", + "http", + "http-body", + "hyper", + "reqwest", + "serde", + "tokio", + "tower", + "tower-service", +] + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + [[package]] name = "bitflags" version = "1.3.2" @@ -103,6 +127,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + [[package]] name = "byteorder" version = "1.4.3" @@ -222,6 +252,15 @@ dependencies = [ "serde", ] +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + [[package]] name = "errno" version = "0.3.0" @@ -422,6 +461,25 @@ dependencies = [ "wasi", ] +[[package]] +name = "h2" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.2" @@ -515,6 +573,7 @@ name = "huellas" version = "0.2.0" dependencies = [ "axum", + "axum-test-helper", "dotenvy", "futures", "serde", @@ -536,6 +595,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", @@ -590,6 +650,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + [[package]] name = "itertools" version = "0.10.3" @@ -605,6 +671,15 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -962,6 +1037,43 @@ version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +[[package]] +name = "reqwest" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "winreg", +] + [[package]] name = "rustix" version = "0.37.6" @@ -1393,6 +1505,7 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", + "tracing", ] [[package]] @@ -1611,6 +1724,95 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "wasm-streams" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1756,3 +1958,12 @@ name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] diff --git a/Cargo.toml b/Cargo.toml index 5ba0f40..43168df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ tower-http = { version = "0.4.0", features = ["fs"] } serde = { version = "1.0.159", features = ["derive"] } serde_json = "1.0.95" futures = "0.3.28" +axum-test-helper = "0.2.0" [dependencies.sqlx] version = "0.6.3" diff --git a/src/place.rs b/src/place.rs index 38d2bf2..d1e811e 100644 --- a/src/place.rs +++ b/src/place.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Deserialize, Serialize)] +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] pub struct Place { pub id: Option, pub name: String, diff --git a/src/routes.rs b/src/routes.rs index a8fd1f1..79e242c 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -5,8 +5,6 @@ use axum::Router; use futures::TryStreamExt; use sqlx::sqlite::SqlitePool; -// use rocket::fairing::{self, AdHoc}; - use crate::place::Place; type Result = std::result::Result; @@ -121,3 +119,203 @@ pub fn places_routes(pool: SqlitePool) -> Router { .route("/:id", delete(delete_place)) .with_state(pool) } + +mod tests { + #![cfg(test)] + // ctor crate generates non upper case globals + #![allow(non_upper_case_globals)] + + use crate::place::Place; + use crate::routes; + use axum::http::StatusCode; + use axum::Router; + use axum_test_helper::TestClient; + use sqlx::sqlite::SqlitePool; + + fn client(pool: SqlitePool) -> TestClient { + let router = Router::new().nest("/places", routes::places_routes(pool.clone())); + TestClient::new(router) + } + + #[sqlx::test] + async fn test_add_place(pool: SqlitePool) { + let client = client(pool); + let mut place = Place { + id: None, + name: "Sherlock Holmes".to_owned(), + address: "221 B Baker Street, London".to_owned(), + description: "Museum and Gift Shop".to_owned(), + icon: "museum".to_owned(), + latitude: 51.5237669, + longitude: -0.1627829, + open_hours: "Tu-Su 09:30-18:00".to_owned(), + url: Some("https://www.sherlock-holmes.co.uk/".to_owned()), + }; + // Insert hte place + let res = client.put("/places").json(&place).send().await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + let res_place: Place = serde_json::from_value(res.json().await).unwrap(); + // The inserted place should have an ID + assert!(res_place.id.is_some()); + // Add the returned ID to the original place + place.id = res_place.id; + // And now they should be equal + assert_eq!(place, res_place) + // TODO: actually query the DB to check the place was inserted + } + + #[sqlx::test] + async fn test_get_places(pool: SqlitePool) { + let client = client(pool); + let mut places = vec![ + Place { + id: None, + name: "Sherlock Holmes".to_owned(), + address: "221 B Baker Street, London".to_owned(), + description: "Museum and Gift Shop".to_owned(), + icon: "museum".to_owned(), + latitude: 51.5237669, + longitude: -0.1627829, + open_hours: "Tu-Su 09:30-18:00".to_owned(), + url: Some("https://www.sherlock-holmes.co.uk/".to_owned()), + }, + Place { + id: None, + name: "Museo Nacional de Historia Natural".to_owned(), + address: "Parque Quinta Normal S/N, Santiago".to_owned(), + description: "Museo".to_owned(), + icon: "museum".to_owned(), + latitude: -70.681838888889, + longitude: -33.4421694444449, + open_hours: "Tu-Su 10:00-18:00".to_owned(), + url: Some("https://www.mnhn.gob.cl/".to_owned()), + }, + ]; + // insert the places + for p in &mut places { + let res = client.put("/places").json(&p).send().await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + let res_place: Place = serde_json::from_value(res.json().await).unwrap(); + // The inserted place should have an ID + assert!(res_place.id.is_some()); + // Add the returned ID to the original place + p.id = res_place.id; + } + // and fetch them + let res = client.get("/places").send().await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + let mut res_places: Vec = serde_json::from_value(res.json().await).unwrap(); + // and they should be equal + places.sort_by(|a, b| a.id.cmp(&b.id)); + res_places.sort_by(|a, b| a.id.cmp(&b.id)); + assert_eq!(places, res_places); + } + + #[sqlx::test] + async fn test_delete(pool: SqlitePool) { + let client = client(pool); + let mut places = vec![ + Place { + id: None, + name: "Sherlock Holmes".to_owned(), + address: "221 B Baker Street, London".to_owned(), + description: "Museum and Gift Shop".to_owned(), + icon: "museum".to_owned(), + latitude: 51.5237669, + longitude: -0.1627829, + open_hours: "Tu-Su 09:30-18:00".to_owned(), + url: Some("https://www.sherlock-holmes.co.uk/".to_owned()), + }, + Place { + id: None, + name: "Museo Nacional de Historia Natural".to_owned(), + address: "Parque Quinta Normal S/N, Santiago".to_owned(), + description: "Museo".to_owned(), + icon: "museum".to_owned(), + latitude: -70.681838888889, + longitude: -33.4421694444449, + open_hours: "Tu-Su 10:00-18:00".to_owned(), + url: Some("https://www.mnhn.gob.cl/".to_owned()), + }, + ]; + // insert the places + for p in &mut places { + let res = client.put("/places").json(&p).send().await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + let res_place: Place = serde_json::from_value(res.json().await).unwrap(); + // The inserted place should have an ID + assert!(res_place.id.is_some()); + // Add the returned ID to the original place + p.id = res_place.id; + } + // delete the first one + let res = client + .delete(&format!("/places/{}", places[0].id.unwrap())) + .send() + .await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + + // fetch the remaining places + let res = client.get("/places").send().await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + let res_places: Vec = serde_json::from_value(res.json().await).unwrap(); + // we should only get the second place + assert_eq!(&places[1..], res_places.as_slice()); + } + + #[sqlx::test] + async fn test_update(pool: SqlitePool) { + let client = client(pool); + let mut places = vec![ + Place { + id: None, + name: "Sherlock Holmes".to_owned(), + address: "221 B Baker Street, London".to_owned(), + description: "Museum and Gift Shop".to_owned(), + icon: "museum".to_owned(), + latitude: 51.5237669, + longitude: -0.1627829, + open_hours: "Tu-Su 09:30-18:00".to_owned(), + url: Some("https://www.sherlock-holmes.co.uk/".to_owned()), + }, + Place { + id: None, + name: "Museo Nacional de Historia Natural".to_owned(), + address: "Parque Quinta Normal S/N, Santiago".to_owned(), + description: "Museo".to_owned(), + icon: "museum".to_owned(), + latitude: -70.681838888889, + longitude: -33.4421694444449, + open_hours: "Tu-Su 10:00-18:00".to_owned(), + url: Some("https://www.mnhn.gob.cl/".to_owned()), + }, + ]; + // insert original place + let res = client.put("/places").json(&places[0]).send().await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + let res_place: Place = serde_json::from_value(res.json().await).unwrap(); + // The inserted place should have an ID + assert!(res_place.id.is_some()); + // Add the returned ID to the new place so we can do the update + places[1].id = res_place.id; + // update the place + let res = client.put("/places").json(&places[1]).send().await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + + // fetch the places + let res = client.get("/places").send().await; + // We should get a success on the request + assert_eq!(res.status(), StatusCode::OK); + let res_places: Vec = serde_json::from_value(res.json().await).unwrap(); + // we should get the updated place + assert_eq!(&places[1..], res_places.as_slice()); + } +} -- 2.45.3