use ares_server::config::Config; use ares_server::{build_app, router}; use futures_util::{SinkExt, StreamExt}; use serde_json::json; use tempfile::tempdir; async fn spawn_server() -> (String, ares_server::state::SharedState) { let dir = tempdir().unwrap(); let cfg = Config { db_path: dir.path().join("t.db").to_string_lossy().into(), ..Default::default() }; let state = build_app(cfg).await; let app = router(state.clone()); let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); let addr = listener.local_addr().unwrap(); tokio::spawn(async move { let _ = axum::serve(listener, app).await; }); (format!("http://{addr}"), state) } fn ws_url(base: &str) -> String { base.replace("http", "ws") } async fn connect_ws(base: &str, peer_id: &str, file_id: &str) -> tokio_tungstenite::WebSocketStream> { let (mut socket, _) = tokio_tungstenite::connect_async(&format!("{}/api/v1/tracker/ws", ws_url(base))).await.unwrap(); socket .send(tokio_tungstenite::tungstenite::Message::Text( json!({"peer_id": peer_id, "file_id": file_id}).to_string(), )).await.unwrap(); socket } #[tokio::test] async fn ws_registers_and_http_peers_lists_it() { let (base, _state) = spawn_server().await; let _socket = connect_ws(&base, "peerA", "abc123").await; tokio::time::sleep(std::time::Duration::from_millis(200)).await; let client = reqwest::Client::new(); let res = client .get(format!("{base}/api/v1/peers/abc123")) .send().await.unwrap(); let body: serde_json::Value = res.json().await.unwrap(); assert_eq!(body["file_id"], "abc123"); assert!(body["peers"].as_array().unwrap().contains(&serde_json::Value::String("peerA".into()))); } #[tokio::test] async fn ws_broadcasts_peer_online() { let (base, _state) = spawn_server().await; let mut a = connect_ws(&base, "peerA", "f1").await; tokio::time::sleep(std::time::Duration::from_millis(150)).await; let _b = connect_ws(&base, "peerB", "f1").await; // peerA deve receber a notificação de que peerB ficou online let timeout = tokio::time::timeout(std::time::Duration::from_secs(2), a.next()); let got = timeout.await.unwrap().expect("peerA fechou").expect("erro ws"); let text = match got { tokio_tungstenite::tungstenite::Message::Text(t) => t.to_string(), other => panic!("esperado Text, recebido: {other:?}"), }; let parsed: serde_json::Value = serde_json::from_str(&text).unwrap(); eprintln!("received: {parsed}"); assert_eq!(parsed["type"], "peer_online"); assert_eq!(parsed["peer_id"], "peerB"); }