1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
use crate::{
    http::request::Builder as RequestBuilder,
    http::HeaderValue,
    mime::Mime,
    url::{ParseError, Url},
};

#[derive(Clone)]
pub struct Helper {
    pub base_url: Option<Url>,
    pub request_initializer: fn() -> RequestBuilder,
    pub mime_matcher: fn(&Mime, &HeaderValue) -> bool,
}

impl Helper {
    pub fn new() -> Self {
        Self {
            base_url: None,
            request_initializer: RequestBuilder::new,
            mime_matcher: |expect, actual| match actual.to_str() {
                Ok(value) => expect == &value,
                Err(_) => false,
            },
        }
    }
}

impl Default for Helper {
    fn default() -> Self {
        Self::new()
    }
}

impl Helper {
    pub fn with_base_url(self, base_url: Url) -> Self {
        Self {
            base_url: Some(base_url),
            ..self
        }
    }

    pub fn with_request_initializer(self, request_initializer: fn() -> RequestBuilder) -> Self {
        Self {
            request_initializer,
            ..self
        }
    }

    pub fn with_mime_matcher(self, mime_matcher: fn(&Mime, &HeaderValue) -> bool) -> Self {
        Self {
            mime_matcher,
            ..self
        }
    }

    pub fn parse_uri(&self, raw_url: &str) -> Result<Url, ParseError> {
        match self.base_url {
            Some(ref base_url) => base_url.join(raw_url),
            None => raw_url.parse(),
        }
    }

    pub fn request(&self) -> RequestBuilder {
        (self.request_initializer)()
    }

    pub fn match_mime(&self, expect: &Mime, actual: &HeaderValue) -> bool {
        (self.mime_matcher)(expect, actual)
    }
}

#[cfg(test)]
mod tests {
    use super::{Helper, ParseError, RequestBuilder};
    use crate::http::{header::USER_AGENT, Error, Version};

    #[test]
    fn test_with_request_initializer() -> Result<(), Error> {
        let helper = Helper::new()
            .with_request_initializer(|| {
                let mut builder = RequestBuilder::new();
                builder
                    .version(Version::HTTP_10)
                    .header(USER_AGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36");
                builder
            });
        let request = (helper.request_initializer)()
            .method("get")
            .uri("https://github.com")
            .body(())?;
        Ok(*request.body())
    }

    #[test]
    fn with_base_url() -> Result<(), ParseError> {
        let helper = Helper::new().with_base_url("https://github.com".parse()?);
        assert_eq!(
            helper.parse_uri("path")?.as_str(),
            "https://github.com/path"
        );
        Ok(())
    }
}