tiny-mailcatcher 0.9.3

A tiny MailCatcher clone
Documentation
use chrono::{TimeZone, Utc};
use reqwest::{Method, Response};
use std::net::{SocketAddr, TcpListener};
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use tiny_mailcatcher::http::run_http_server;
use tiny_mailcatcher::repository::{Message, MessageRepository};
use tokio::task::JoinHandle;

fn create_repository_with_messages(messages: Vec<Message>) -> Arc<Mutex<MessageRepository>> {
    let mut repository = MessageRepository::new();

    for message in messages {
        repository.persist(message);
    }

    Arc::new(Mutex::new(repository))
}

fn launch_test_http_server(repository: Arc<Mutex<MessageRepository>>, port: u16) -> JoinHandle<()> {
    let addr = SocketAddr::from_str(format!("127.0.0.1:{}", port).as_str()).unwrap();
    let tcp_listener = TcpListener::bind(addr).unwrap();

    tokio::spawn(async move {
        run_http_server(tcp_listener, repository.clone())
            .await
            .unwrap()
    })
}

async fn do_request(
    repository: Arc<Mutex<MessageRepository>>,
    method: Method,
    uri: &str,
) -> Response {
    let server = launch_test_http_server(repository, 62043);
    let client = reqwest::Client::new();
    let req = client
        .request(method, "http://127.0.0.1:62043".to_string() + uri)
        .build()
        .unwrap();
    let resp = client.execute(req).await.unwrap();

    server.abort();

    resp
}

#[tokio::test]
async fn test_http_server_is_reachable() {
    let repository = create_repository_with_messages(vec![Message {
        id: Some(1),
        size: 42,
        subject: Some("This is the subject".to_string()),
        sender: Some("sender@example.com".to_string()),
        recipients: vec!["recipient@example.com".to_string()],
        created_at: Utc.timestamp(1431648000, 0),
        typ: "text/plain".to_string(),
        parts: vec![],
        charset: "UTF-8".to_string(),
        source: b"Subject: This is the subject\r\n\r\nHello world!\r\n".to_vec(),
    }]);

    let res = do_request(repository, Method::GET, "/messages").await;
    let json = res.json::<serde_json::Value>().await.unwrap();

    let expected = serde_json::json!([
        {
            "created_at": "2015-05-15T00:00:00+00:00",
            "id": 1,
            "recipients": ["recipient@example.com"],
            "sender": "sender@example.com",
            "size": "42",
            "subject": "This is the subject",
        }
    ]);
    assert_eq!(expected, json);
}