Skip to content

Commit

Permalink
Add more integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sagebind committed Jul 20, 2019
1 parent 821f8e4 commit 586558b
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 51 deletions.
16 changes: 14 additions & 2 deletions .github/main.workflow
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,31 @@ action "checkout-submodules" {
action "test-stable" {
needs = ["checkout-submodules"]
uses = "docker://rust:1.36"
args = "cargo test --features psl"
args = "cargo test --features psl -- --test-threads=8"
env = {
RUST_BACKTRACE = "1"
RUST_LOG = "warn"
}
}

action "test-nightly" {
needs = ["checkout-submodules"]
uses = "docker://rustlang/rust:nightly"
args = "cargo test --features psl,nightly"
args = "cargo test --features psl,nightly -- --test-threads=8"
env = {
RUST_BACKTRACE = "1"
RUST_LOG = "warn"
}
}

action "examples" {
needs = ["checkout-submodules"]
uses = "docker://rust:1.36"
args = "cargo run --release --example simple"
env = {
RUST_BACKTRACE = "1"
RUST_LOG = "warn"
}
}

action "release-published" {
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
.vscode
target
Cargo.lock
/image.jpg
14 changes: 5 additions & 9 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ lazy_static! {
/// .redirect_policy(RedirectPolicy::Limit(10))
/// .preferred_http_version(http::Version::HTTP_2)
/// .build()?;
///
/// let mut response = client.get("https://example.org")?;
/// let body = response.body_mut().text()?;
/// println!("{}", body);
/// # Ok::<(), chttp::Error>(())
/// ```
#[derive(Default)]
Expand Down Expand Up @@ -264,7 +260,7 @@ impl fmt::Debug for HttpClientBuilder {
///
/// ## Examples
///
/// ```
/// ```no_run
/// use chttp::prelude::*;
///
/// // Create a new client using reasonable defaults.
Expand All @@ -280,7 +276,7 @@ impl fmt::Debug for HttpClientBuilder {
///
/// Customizing the client configuration:
///
/// ```
/// ```no_run
/// use chttp::{config::RedirectPolicy, prelude::*};
/// use std::time::Duration;
///
Expand Down Expand Up @@ -395,7 +391,7 @@ impl HttpClient {
///
/// ## Examples
///
/// ```
/// ```no_run
/// use chttp::prelude::*;
///
/// let client = HttpClient::default();
Expand Down Expand Up @@ -431,7 +427,7 @@ impl HttpClient {
///
/// ## Examples
///
/// ```
/// ```no_run
/// use chttp::prelude::*;
///
/// let client = HttpClient::default();
Expand Down Expand Up @@ -511,7 +507,7 @@ impl HttpClient {
///
/// ## Examples
///
/// ```
/// ```no_run
/// use chttp::prelude::*;
///
/// let client = HttpClient::default();
Expand Down
12 changes: 6 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! Sending requests is as easy as calling a single function. Let's make a
//! simple GET request to an example website:
//!
//! ```
//! ```no_run
//! use chttp::prelude::*;
//!
//! let mut response = chttp::get("https://example.org")?;
Expand All @@ -20,14 +20,14 @@
//! Sending a POST request is also easy, and takes an additional argument for
//! the request body:
//!
//! ```
//! ```no_run
//! let response = chttp::post("https://httpbin.org/post", "make me a salad")?;
//! # Ok::<(), chttp::Error>(())
//! ```
//!
//! cHTTP provides several other simple functions for common HTTP request types:
//!
//! ```
//! ```no_run
//! chttp::put("https://httpbin.org/put", "have a salad")?;
//! chttp::head("https://httpbin.org/get")?;
//! chttp::delete("https://httpbin.org/delete")?;
Expand All @@ -39,7 +39,7 @@
//! cHTTP is not limited to canned HTTP verbs; you can customize requests by
//! creating your own `Request` object and then `send`ing that.
//!
//! ```
//! ```no_run
//! use chttp::prelude::*;
//!
//! let response = Request::post("https://httpbin.org/post")
Expand All @@ -60,7 +60,7 @@
//! methods provided by the [`RequestBuilderExt`](prelude::RequestBuilderExt)
//! trait:
//!
//! ```
//! ```no_run
//! use chttp::prelude::*;
//! use std::time::Duration;
//!
Expand Down Expand Up @@ -98,7 +98,7 @@
//! an asynchronous variant that ends with `_async` in the name. Here is our
//! first example rewritten to use async/await syntax (nightly only):
//!
//! ```
//! ```no_run
//! # #![cfg_attr(feature = "nightly", feature(async_await))]
//! # use chttp::prelude::*;
//! #
Expand Down
2 changes: 1 addition & 1 deletion src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub trait ResponseExt<T> {
///
/// ## Examples
///
/// ```
/// ```no_run
/// # use chttp::prelude::*;
/// chttp::get("https://httpbin.org/image/jpeg")?
/// .copy_to_file("image.jpg")?;
Expand Down
28 changes: 28 additions & 0 deletions tests/headers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use mockito::{Matcher, mock, server_url};

speculate::speculate! {
before {
env_logger::try_init().ok();
}

test "accept headers populated by default" {
let m = mock("GET", "/")
.match_header("accept", "*/*")
.match_header("accept-encoding", "deflate, gzip")
.create();

chttp::get(server_url()).unwrap();

m.assert();
}

test "user agent contains expected format" {
let m = mock("GET", "/")
.match_header("user-agent", Matcher::Regex(r"^curl/\S+ chttp/\S+$".into()))
.create();

chttp::get(server_url()).unwrap();

m.assert();
}
}
62 changes: 62 additions & 0 deletions tests/methods.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use chttp::prelude::*;
use mockito::{mock, server_url};

speculate::speculate! {
before {
env_logger::try_init().ok();
}

test "GET request" {
let m = mock("GET", "/").create();

chttp::get(server_url()).unwrap();

m.assert();
}

test "HEAD request" {
let m = mock("HEAD", "/").create();

chttp::head(server_url()).unwrap();

m.assert();
}

test "POST request" {
let m = mock("POST", "/").create();

chttp::post(server_url(), ()).unwrap();

m.assert();
}

test "PUT request" {
let m = mock("PUT", "/").create();

chttp::put(server_url(), ()).unwrap();

m.assert();
}

test "DELETE request" {
let m = mock("DELETE", "/").create();

chttp::delete(server_url()).unwrap();

m.assert();
}

test "arbitrary FOOBAR request" {
let m = mock("FOOBAR", "/").create();

Request::builder()
.method("FOOBAR")
.uri(server_url())
.body(())
.unwrap()
.send()
.unwrap();

m.assert();
}
}
43 changes: 35 additions & 8 deletions tests/redirects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,31 @@ use chttp::config::RedirectPolicy;
use chttp::prelude::*;
use mockito::{mock, server_url};

mod utils;

speculate::speculate! {
before {
utils::logging();
env_logger::try_init().ok();
}

test "response 301 no follow" {
let m = mock("GET", "/")
.with_status(301)
.with_header("Location", "/b")
.with_header("Location", "/2")
.create();

let response = chttp::get(server_url()).unwrap();

assert_eq!(response.status(), 301);
assert_eq!(response.headers()["Location"], "/b");
assert_eq!(response.headers()["Location"], "/2");
m.assert();
}

test "response 301 auto follow" {
let m1 = mock("GET", "/")
.with_status(301)
.with_header("Location", "/b")
.with_header("Location", "/2")
.create();

let m2 = mock("GET", "/b")
let m2 = mock("GET", "/2")
.with_status(200)
.with_body("ok")
.create();
Expand All @@ -47,13 +45,42 @@ speculate::speculate! {
m2.assert();
}

test "redirect limit is respected" {
test "headers are reset every redirect" {
let m1 = mock("GET", "/")
.with_status(301)
.with_header("Location", "/b")
.with_header("X-Foo", "aaa")
.with_header("X-Bar", "zzz")
.create();

let m2 = mock("GET", "/b")
.with_header("X-Foo", "bbb")
.with_header("X-Baz", "zzz")
.create();

let response = Request::get(server_url())
.redirect_policy(RedirectPolicy::Follow)
.body(())
.unwrap()
.send()
.unwrap();

assert_eq!(response.status(), 200);
assert_eq!(response.headers()["X-Foo"], "bbb");
assert_eq!(response.headers()["X-Baz"], "zzz");
assert!(!response.headers().contains_key("X-Bar"));

m1.assert();
m2.assert();
}

test "redirect limit is respected" {
let m1 = mock("GET", "/")
.with_status(301)
.with_header("Location", "/2")
.create();

let m2 = mock("GET", "/2")
.with_status(301)
.with_header("Location", "/")
.create();
Expand Down
16 changes: 7 additions & 9 deletions tests/response.rs → tests/response_body.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
use mockito::{mock, server_url};

mod utils;

speculate::speculate! {
before {
utils::logging();
env_logger::try_init().ok();
}

test "simple response body" {
let mock = mock("GET", "/")
let m = mock("GET", "/")
.with_body("hello world")
.create();

let mut response = chttp::get(server_url()).unwrap();
let response_text = response.body_mut().text().unwrap();
assert_eq!(response_text, "hello world");

mock.assert();
assert_eq!(response_text, "hello world");
m.assert();
}

test "large response body" {
let body = "wow so large ".repeat(1000);

let mock = mock("GET", "/")
let m = mock("GET", "/")
.with_body(&body)
.create();

let mut response = chttp::get(server_url()).unwrap();
let response_text = response.body_mut().text().unwrap();
assert_eq!(response_text, body);

mock.assert();
assert_eq!(response_text, body);
m.assert();
}
}
20 changes: 20 additions & 0 deletions tests/status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use mockito::{mock, server_url};

speculate::speculate! {
before {
env_logger::try_init().ok();
}

test "returns correct response code" {
for status in [200u16, 202, 204, 302, 308, 400, 403, 404, 418, 429, 451, 500, 503].iter() {
let m = mock("GET", "/")
.with_status(*status as usize)
.create();

let response = chttp::get(server_url()).unwrap();

assert_eq!(response.status(), *status);
m.assert();
}
}
}
Loading

0 comments on commit 586558b

Please sign in to comment.