use failure::{format_err, Fallible}; use lazy_static::lazy_static; use reqwest::Client; use serde_cbor::{from_slice, to_vec}; use std::{sync::Mutex, thread}; use url::Url; use webapp::{ config::Config, protocol::{model::Session, request, response}, API_URL_LOGIN_CREDENTIALS, API_URL_LOGIN_SESSION, API_URL_LOGOUT, CONFIG_FILENAME, }; use webapp_backend::Server; lazy_static! { static ref PORT: Mutex = Mutex::new(30000); } fn get_config() -> Fallible { Ok(Config::from_file(&format!("../{}", CONFIG_FILENAME))?) } fn get_next_port() -> u16 { let mut port = PORT.lock().unwrap(); *port += 1; *port } pub fn create_testserver() -> Fallible { // Prepare the configuration let mut config = get_config()?; // Set the test configuration let mut url = Url::parse(&config.server.url)?; url.set_port(Some(get_next_port())) .map_err(|_| format_err!("Unable to set server port"))?; config.server.url = url.to_string(); config.server.redirect_from = vec![]; // Start the server let config_clone = config.clone(); thread::spawn(move || Server::from_config(&config_clone).unwrap().start()); // Wait until the server is up loop { if let Ok(res) = Client::new().get(url.clone()).send() { if res.status().is_success() { break; } } } // Return the server url Ok(url) } #[test] fn succeed_to_create_server_with_common_redirects() -> Fallible<()> { // Given let mut config = get_config()?; let mut url = Url::parse(&config.server.url)?; url.set_port(Some(get_next_port())) .map_err(|_| format_err!("Unable to set server port"))?; config.server.url = url.to_string(); let redirect_url = "http://127.0.0.1:30666".to_owned(); config.server.redirect_from = vec![ redirect_url.clone(), "https://localhost:30667".to_owned(), "invalid".to_owned(), ]; // When let config_clone = config.clone(); thread::spawn(move || Server::from_config(&config_clone).unwrap().start()); loop { if let Ok(res) = Client::new().get(url.clone()).send() { if res.status().is_success() { break; } } } let res = Client::new().get(&redirect_url).send()?; // Then assert_eq!(res.url().as_str().contains(&redirect_url), false); Ok(()) } #[test] fn succeed_to_login_with_credentials() -> Fallible<()> { // Given let mut url = create_testserver()?; url.set_path(API_URL_LOGIN_CREDENTIALS); // When let request = to_vec(&request::LoginCredentials { username: "username".to_owned(), password: "username".to_owned(), })?; let mut res = Client::new().post(url).body(request).send()?; let mut body = vec![]; res.copy_to(&mut body)?; let response::Login(session) = from_slice(&body)?; // Then assert!(res.status().is_success()); assert_eq!(session.token.len(), 211); Ok(()) } #[test] fn fail_to_login_with_wrong_credentials() -> Fallible<()> { // Given let mut url = create_testserver()?; url.set_path(API_URL_LOGIN_CREDENTIALS); // When let request = to_vec(&request::LoginCredentials { username: "username".to_owned(), password: "password".to_owned(), })?; let res = Client::new().post(url).body(request).send()?; // Then assert_eq!(res.status().as_u16(), 401); Ok(()) } #[test] fn succeed_to_login_with_session() -> Fallible<()> { // Given let mut url = create_testserver()?; url.set_path(API_URL_LOGIN_CREDENTIALS); // When let mut request = to_vec(&request::LoginCredentials { username: "username".to_owned(), password: "username".to_owned(), })?; let mut res = Client::new().post(url.clone()).body(request).send()?; let mut body = vec![]; res.copy_to(&mut body)?; let response::Login(session) = from_slice(&body)?; request = to_vec(&request::LoginSession(session))?; url.set_path(API_URL_LOGIN_SESSION); res = Client::new().post(url).body(request).send()?; body.clear(); res.copy_to(&mut body)?; let response::Login(new_session) = from_slice(&body)?; // Then assert!(res.status().is_success()); assert_eq!(new_session.token.len(), 211); Ok(()) } #[test] fn fail_to_login_with_wrong_session() -> Fallible<()> { // Given let mut url = create_testserver()?; url.set_path(API_URL_LOGIN_SESSION); // When let request = to_vec(&request::LoginSession(Session::new("wrong")))?; let res = Client::new().post(url).body(request).send()?; // Then assert_eq!(res.status().as_u16(), 401); Ok(()) } #[test] fn succeed_to_logout() -> Fallible<()> { // Given let mut url = create_testserver()?; url.set_path(API_URL_LOGOUT); // When let request = to_vec(&request::Logout(Session::new("wrong")))?; let res = Client::new().post(url).body(request).send()?; // Then assert!(res.status().is_success()); Ok(()) }