From c1d76bfac7bc8c227f1a848154abff67d6ed3baa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Audiger?= <31616285+jaudiger@users.noreply.github.com> Date: Thu, 2 Mar 2023 20:05:18 +0100 Subject: [PATCH] Add unit tests for HTTP commands. (#8267) # Description Following the comment from @fdncred: https://github.com/nushell/nushell/pull/8144#issuecomment-1442514338. I added some unit tests for HTTP commands. The tests are not exhaustive, but at least, this is a first good step IMO. # User-Facing Changes None. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --- Cargo.lock | 89 +++++++++++++++++++ crates/nu-command/Cargo.toml | 1 + .../tests/commands/network/http/delete.rs | 44 +++++++++ .../tests/commands/network/http/get.rs | 44 +++++++++ .../tests/commands/network/http/head.rs | 45 ++++++++++ .../tests/commands/network/http/mod.rs | 6 ++ .../tests/commands/network/http/patch.rs | 82 +++++++++++++++++ .../tests/commands/network/http/post.rs | 82 +++++++++++++++++ .../tests/commands/network/http/put.rs | 82 +++++++++++++++++ .../nu-command/tests/commands/network/mod.rs | 1 + 10 files changed, 476 insertions(+) create mode 100644 crates/nu-command/tests/commands/network/http/delete.rs create mode 100644 crates/nu-command/tests/commands/network/http/get.rs create mode 100644 crates/nu-command/tests/commands/network/http/head.rs create mode 100644 crates/nu-command/tests/commands/network/http/mod.rs create mode 100644 crates/nu-command/tests/commands/network/http/patch.rs create mode 100644 crates/nu-command/tests/commands/network/http/post.rs create mode 100644 crates/nu-command/tests/commands/network/http/put.rs diff --git a/Cargo.lock b/Cargo.lock index 80613a7468..4c92a51b67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -182,6 +182,16 @@ dependencies = [ "zstd", ] +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "assert_cmd" version = "2.0.4" @@ -618,6 +628,17 @@ dependencies = [ "encoding_rs", ] +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + [[package]] name = "comfy-table" version = "6.1.4" @@ -984,6 +1005,25 @@ dependencies = [ "parking_lot_core 0.9.3", ] +[[package]] +name = "deadpool" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "421fe0f90f2ab22016f32a9881be5134fdd71c65298917084b0c7477cbc3856e" +dependencies = [ + "async-trait", + "deadpool-runtime", + "num_cpus", + "retain_mut", + "tokio", +] + +[[package]] +name = "deadpool-runtime" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaa37046cc0f6c3cc6090fbdbf73ef0b8ef4cfcc37f6befc0020f63e8cf121e1" + [[package]] name = "derive_more" version = "0.99.17" @@ -2412,6 +2452,28 @@ dependencies = [ "windows-sys 0.36.1", ] +[[package]] +name = "mockito" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09908a0c0e8c956c1360268b54c0f7eeefc7ef98020cfb81077fa71761a18d29" +dependencies = [ + "assert-json-diff", + "async-trait", + "colored", + "deadpool", + "futures", + "hyper", + "lazy_static", + "log", + "rand 0.8.5", + "regex", + "serde_json", + "serde_urlencoded", + "similar", + "tokio", +] + [[package]] name = "multiversion" version = "0.6.1" @@ -2710,6 +2772,7 @@ dependencies = [ "md-5", "mime", "mime_guess", + "mockito", "notify", "nu-ansi-term", "nu-cmd-lang", @@ -4284,6 +4347,12 @@ dependencies = [ "winreg 0.10.1", ] +[[package]] +name = "retain_mut" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" + [[package]] name = "riscv" version = "0.7.0" @@ -4798,6 +4867,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +[[package]] +name = "similar" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" + [[package]] name = "simplelog" version = "0.12.0" @@ -5296,11 +5371,25 @@ dependencies = [ "memchr", "mio", "num_cpus", + "parking_lot 0.12.1", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.42.0", ] +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-native-tls" version = "0.3.0" diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index dde10ed3b0..b2cdb257ac 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -156,6 +156,7 @@ which-support = ["which"] [dev-dependencies] nu-test-support = { path = "../nu-test-support", version = "0.76.1" } +mockito = "0.32.3" dirs-next = "2.0.0" hamcrest2 = "0.3.0" diff --git a/crates/nu-command/tests/commands/network/http/delete.rs b/crates/nu-command/tests/commands/network/http/delete.rs new file mode 100644 index 0000000000..96eb505645 --- /dev/null +++ b/crates/nu-command/tests/commands/network/http/delete.rs @@ -0,0 +1,44 @@ +use mockito::Server; +use nu_test_support::{nu, pipeline}; +use reqwest::StatusCode; + +#[test] +fn http_delete_is_success() { + let mut server = Server::new(); + + let _mock = server.mock("DELETE", "/").create(); + + let actual = nu!(pipeline( + format!( + r#" + http delete {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.out.is_empty()) +} + +#[test] +fn http_delete_failed_due_to_server_error() { + let mut server = Server::new(); + + let _mock = server + .mock("DELETE", "/") + .with_status(StatusCode::BAD_REQUEST.as_u16() as usize) + .create(); + + let actual = nu!(pipeline( + format!( + r#" + http delete {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Bad request (400)")) +} diff --git a/crates/nu-command/tests/commands/network/http/get.rs b/crates/nu-command/tests/commands/network/http/get.rs new file mode 100644 index 0000000000..2adeab3571 --- /dev/null +++ b/crates/nu-command/tests/commands/network/http/get.rs @@ -0,0 +1,44 @@ +use mockito::Server; +use nu_test_support::{nu, pipeline}; +use reqwest::StatusCode; + +#[test] +fn http_get_is_success() { + let mut server = Server::new(); + + let _mock = server.mock("GET", "/").with_body("foo").create(); + + let actual = nu!(pipeline( + format!( + r#" + http get {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert_eq!(actual.out, "foo") +} + +#[test] +fn http_get_failed_due_to_server_error() { + let mut server = Server::new(); + + let _mock = server + .mock("GET", "/") + .with_status(StatusCode::BAD_REQUEST.as_u16() as usize) + .create(); + + let actual = nu!(pipeline( + format!( + r#" + http get {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Bad request (400)")) +} diff --git a/crates/nu-command/tests/commands/network/http/head.rs b/crates/nu-command/tests/commands/network/http/head.rs new file mode 100644 index 0000000000..64f3ec464d --- /dev/null +++ b/crates/nu-command/tests/commands/network/http/head.rs @@ -0,0 +1,45 @@ +use mockito::Server; +use nu_test_support::{nu, pipeline}; +use reqwest::StatusCode; + +#[test] +fn http_head_is_success() { + let mut server = Server::new(); + + let _mock = server.mock("HEAD", "/").with_header("foo", "bar").create(); + + let actual = nu!(pipeline( + format!( + r#" + http head {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.out.contains("foo")); + assert!(actual.out.contains("bar")); +} + +#[test] +fn http_head_failed_due_to_server_error() { + let mut server = Server::new(); + + let _mock = server + .mock("HEAD", "/") + .with_status(StatusCode::BAD_REQUEST.as_u16() as usize) + .create(); + + let actual = nu!(pipeline( + format!( + r#" + http head {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Bad request (400)")) +} diff --git a/crates/nu-command/tests/commands/network/http/mod.rs b/crates/nu-command/tests/commands/network/http/mod.rs new file mode 100644 index 0000000000..2d8f4f19a8 --- /dev/null +++ b/crates/nu-command/tests/commands/network/http/mod.rs @@ -0,0 +1,6 @@ +mod delete; +mod get; +mod head; +mod patch; +mod post; +mod put; diff --git a/crates/nu-command/tests/commands/network/http/patch.rs b/crates/nu-command/tests/commands/network/http/patch.rs new file mode 100644 index 0000000000..32ccd6eb80 --- /dev/null +++ b/crates/nu-command/tests/commands/network/http/patch.rs @@ -0,0 +1,82 @@ +use mockito::Server; +use nu_test_support::{nu, pipeline}; +use reqwest::StatusCode; + +#[test] +fn http_patch_is_success() { + let mut server = Server::new(); + + let _mock = server.mock("PATCH", "/").match_body("foo").create(); + + let actual = nu!(pipeline( + format!( + r#" + http patch {url} "foo" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.out.is_empty()) +} + +#[test] +fn http_patch_failed_due_to_server_error() { + let mut server = Server::new(); + + let _mock = server + .mock("PATCH", "/") + .with_status(StatusCode::BAD_REQUEST.as_u16() as usize) + .create(); + + let actual = nu!(pipeline( + format!( + r#" + http patch {url} "body" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Bad request (400)")) +} + +#[test] +fn http_patch_failed_due_to_missing_body() { + let mut server = Server::new(); + + let _mock = server.mock("PATCH", "/").create(); + + let actual = nu!(pipeline( + format!( + r#" + http patch {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Usage: http patch")) +} + +#[test] +fn http_patch_failed_due_to_unexpected_body() { + let mut server = Server::new(); + + let _mock = server.mock("PATCH", "/").match_body("foo").create(); + + let actual = nu!(pipeline( + format!( + r#" + http patch {url} "bar" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Cannot make request")) +} diff --git a/crates/nu-command/tests/commands/network/http/post.rs b/crates/nu-command/tests/commands/network/http/post.rs new file mode 100644 index 0000000000..8cc31bd4f2 --- /dev/null +++ b/crates/nu-command/tests/commands/network/http/post.rs @@ -0,0 +1,82 @@ +use mockito::Server; +use nu_test_support::{nu, pipeline}; +use reqwest::StatusCode; + +#[test] +fn http_post_is_success() { + let mut server = Server::new(); + + let _mock = server.mock("POST", "/").match_body("foo").create(); + + let actual = nu!(pipeline( + format!( + r#" + http post {url} "foo" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.out.is_empty()) +} + +#[test] +fn http_post_failed_due_to_server_error() { + let mut server = Server::new(); + + let _mock = server + .mock("POST", "/") + .with_status(StatusCode::BAD_REQUEST.as_u16() as usize) + .create(); + + let actual = nu!(pipeline( + format!( + r#" + http post {url} "body" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Bad request (400)")) +} + +#[test] +fn http_post_failed_due_to_missing_body() { + let mut server = Server::new(); + + let _mock = server.mock("POST", "/").create(); + + let actual = nu!(pipeline( + format!( + r#" + http post {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Usage: http post")) +} + +#[test] +fn http_post_failed_due_to_unexpected_body() { + let mut server = Server::new(); + + let _mock = server.mock("POST", "/").match_body("foo").create(); + + let actual = nu!(pipeline( + format!( + r#" + http post {url} "bar" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Cannot make request")) +} diff --git a/crates/nu-command/tests/commands/network/http/put.rs b/crates/nu-command/tests/commands/network/http/put.rs new file mode 100644 index 0000000000..6b4a8958dd --- /dev/null +++ b/crates/nu-command/tests/commands/network/http/put.rs @@ -0,0 +1,82 @@ +use mockito::Server; +use nu_test_support::{nu, pipeline}; +use reqwest::StatusCode; + +#[test] +fn http_put_is_success() { + let mut server = Server::new(); + + let _mock = server.mock("PUT", "/").match_body("foo").create(); + + let actual = nu!(pipeline( + format!( + r#" + http put {url} "foo" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.out.is_empty()) +} + +#[test] +fn http_put_failed_due_to_server_error() { + let mut server = Server::new(); + + let _mock = server + .mock("PUT", "/") + .with_status(StatusCode::BAD_REQUEST.as_u16() as usize) + .create(); + + let actual = nu!(pipeline( + format!( + r#" + http put {url} "body" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Bad request (400)")) +} + +#[test] +fn http_put_failed_due_to_missing_body() { + let mut server = Server::new(); + + let _mock = server.mock("PUT", "/").create(); + + let actual = nu!(pipeline( + format!( + r#" + http put {url} + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Usage: http put")) +} + +#[test] +fn http_put_failed_due_to_unexpected_body() { + let mut server = Server::new(); + + let _mock = server.mock("PUT", "/").match_body("foo").create(); + + let actual = nu!(pipeline( + format!( + r#" + http put {url} "bar" + "#, + url = server.url() + ) + .as_str() + )); + + assert!(actual.err.contains("Cannot make request")) +} diff --git a/crates/nu-command/tests/commands/network/mod.rs b/crates/nu-command/tests/commands/network/mod.rs index 87ed03c5a4..33b80e9504 100644 --- a/crates/nu-command/tests/commands/network/mod.rs +++ b/crates/nu-command/tests/commands/network/mod.rs @@ -1 +1,2 @@ +mod http; mod port;