Skip to content

Commit

Permalink
Add tests for some endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
bouzuya committed Jan 12, 2024
1 parent 76b2431 commit 79574d5
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 20 deletions.
26 changes: 14 additions & 12 deletions backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ tokio = { version = "1.35.1", features = ["full"] }

[patch.crates-io]
expo_push_notification_client = { git = "https://github.com/katayama8000/expo-push-notification-client-rust", branch = "main" }

[dev-dependencies]
serde_json = "1.0.111"
tower = { version = "0.4.13", features = ["util"] }
102 changes: 94 additions & 8 deletions backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct App {
expo_push_tokens: Arc<Mutex<HashSet<String>>>,
}

#[derive(Debug, serde::Deserialize)]
#[derive(Debug, serde::Deserialize, serde::Serialize)]
struct CreateExpoPushTokenRequestBody {
expo_push_token: String,
}
Expand All @@ -23,16 +23,18 @@ async fn create_expo_push_token(
Json(CreateExpoPushTokenRequestBody { expo_push_token }): Json<CreateExpoPushTokenRequestBody>,
) -> StatusCode {
let mut expo_push_tokens = expo_push_tokens.lock().await;
// TODO: already exists
expo_push_tokens.insert(expo_push_token);
StatusCode::CREATED
}

async fn delete_expo_push_token(
State(App { expo_push_tokens }): State<App>,
Path(expo_push_token_id): Path<String>,
Path(expo_push_token): Path<String>,
) -> StatusCode {
let mut expo_push_tokens = expo_push_tokens.lock().await;
expo_push_tokens.remove(&expo_push_token_id);
// TODO: not found
expo_push_tokens.remove(&expo_push_token);
StatusCode::NO_CONTENT
}

Expand All @@ -59,17 +61,101 @@ async fn get_root() -> &'static str {
"OK"
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let router = Router::new()
fn route(app: App) -> Router {
Router::new()
.route("/", routing::get(get_root))
.route("/expo_push_tokens", routing::post(create_expo_push_token))
.route(
"/expo_push_tokens/:expo_push_token_id",
"/expo_push_tokens/:expo_push_token",
routing::delete(delete_expo_push_token),
)
.route("/notifications", routing::post(create_notification))
.with_state(App::default());
.with_state(app)
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let router = route(App::default());
let listener = TcpListener::bind("0.0.0.0:3000").await?;
Ok(axum::serve(listener, router).await?)
}

#[cfg(test)]
mod tests {
use axum::{
async_trait,
body::Body,
http::{header::CONTENT_TYPE, Request},
response::Response,
};
use tower::ServiceExt;

use super::*;

#[tokio::test]
async fn test_get_root() -> anyhow::Result<()> {
let router = route(App::default());
let request = Request::builder()
.method("GET")
.uri("/")
.body(Body::empty())?;
let response = router.oneshot(request).await?;
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(response.into_body_string().await?, "OK");
Ok(())
}

#[tokio::test]
async fn test_create_expo_push_token() -> anyhow::Result<()> {
let router = route(App::default());
let request = Request::builder()
.method("POST")
.uri("/expo_push_tokens")
.header(CONTENT_TYPE, "application/json")
.body(Body::from(serde_json::to_string(
&CreateExpoPushTokenRequestBody {
expo_push_token: "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]".to_string(),
},
)?))?;
let response = router.oneshot(request).await?;
assert_eq!(response.status(), StatusCode::CREATED);
assert_eq!(response.into_body_string().await?, "");
Ok(())
}

#[tokio::test]
async fn test_delete_expo_push_token() -> anyhow::Result<()> {
let router = route(App::default());
let request = Request::builder()
.method("DELETE")
.uri("/expo_push_tokens/ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]")
.header(CONTENT_TYPE, "application/json")
.body(Body::empty())?;
let response = router.oneshot(request).await?;
assert_eq!(response.status(), StatusCode::NO_CONTENT);
assert_eq!(response.into_body_string().await?, "");
Ok(())
}

#[tokio::test]
async fn test_create_notifications() -> anyhow::Result<()> {
// TODO
Ok(())
}

#[async_trait]
trait ResponseExt {
async fn into_body_string(self) -> anyhow::Result<String>;
}

#[async_trait]
impl ResponseExt for Response {
async fn into_body_string(self) -> anyhow::Result<String> {
Ok(String::from_utf8(
axum::body::to_bytes(self.into_body(), usize::MAX)
.await?
.to_vec(),
)?)
}
}
}

0 comments on commit 79574d5

Please sign in to comment.