kxio 3.0.0

Provides injectable Filesystem and Network resources to make code more testable
Documentation
//! Provides a generic interface for network operations.
//!
//!
//! Provides a testable interface over the [reqwest] crate.
//!
//! ## Overview
//!
//! The `net` module provides a testable interface for network operations.
//! It includes implementations for both real network interactions and mocked network operations for testing purposes.
//!
//! ## Key methods and types:
//!
//! - [kxio::net::new()][new()]: Creates a new `Net` instance
//! - [kxio::net::mock()][mock()]: Creates a new `MockNet` instance for use in tests
//! - [Error]: enum for network-related errors
//! - [Result]: an alias for `core::result::Result<T, Error>`
//! - [Net]: struct for real and mocked network operations
//! - [MockNet]: struct for defining behaviours of mocked network operations
//!
//! ## Usage
//!
//! Write your program to take a reference to [Net].
//!
//! Use the [Net::client] functionto create a [RequestBuilder] which you should then pass to the [Net::send] method.
//! This is rather than building the request and calling its own `send` method, doing so would result in the network request being sent, even under-test.
//!
//! ```rust
//! use kxio::net;
//! async fn get_example(net: &net::Net) -> net::Result<()> {
//!     let response = net.send(net.client().get("https://example.com")).await?;
//!     ///...
//!     Ok(())
//! }
//! ```
//!
//! ### Real Network Operations
//!
//! In your production code you will want to make real network requests.
//!
//! Construct a [Net] using [kxio::net::new()][new()]. Then pass as a reference to your program.
//!
//! ```rust
//! use kxio::net;
//! # #[tokio::main]
//! # async fn main() -> net::Result<()> {
//! let net = net::new();
//!
//! get_example(&net).await?;
//! # Ok(())
//! # }
//! # async fn get_example(net: &net::Net) -> net::Result<()> {Ok(())}
//! ```
//!
//! ### Mocked Network Operations
//!
//! In your tests you will want to mock your network requests and responses.
//!
//! Construct a [MockNet] using [kxio::net::mock()][mock()].
//!
//! ```rust
//! use kxio::net;
//! let mock_net = net::mock();
//! ```
//!
//! Create a [Client] using [MockNet::client()].
//!
//! ```rust
//! # let mock_net = kxio::net::mock();
//! let client = mock_net.client();
//! // this is the same as:
//! let client = kxio::net::Client::new();
//! // this is also the same as:
//! let client = reqwest::Client::new();
//! ```
//!
//! Define the expected responses for each request, using the [MockNet::on],
//! that you expect you program to make during the test. You can choose what each request should be
//! matched against. The default is to the match when both the Method and Url are the same.
//!
//! ```rust
//! use kxio::net;
//! use kxio::net::StatusCode;
//! # #[tokio::main]
//! # async fn main() -> net::Result<()> {
//! # let mock_net = net::mock();
//! mock_net.on().get("https://example.com")
//!     .respond(StatusCode::OK).body("");
//! mock_net.on().get("https://example.com/foo")
//!     .respond(StatusCode::INTERNAL_SERVER_ERROR).body("Mocked response");
//! # mock_net.reset();
//! # Ok(())
//! # }
//! ```
//!
//! Once you have defined all your expected responses, convert the [MockNet] into a [Net].
//!
//! ```rust
//! # use kxio::net;
//! # let mock_net = net::mock();
//! let net: net::Net = mock_net.into();
//! // or
//! # let mock_net = net::mock();
//! let net = net::Net::from(mock_net);
//! ```
//!
//! Now you can pass a reference to `net` to your program.
//!
//! ```rust
//! # use kxio::net;
//! # #[tokio::main]
//! # async fn main() -> net::Result<()> {
//! # let mock_net = net::mock();
//! # let net = net::Net::from(mock_net);
//! get_example(&net).await?;
//! # Ok(())
//! # }
//! # async fn get_example(net: &net::Net) -> net::Result<()> {Ok(())}
//! ```
//!
//! When your test is finished, the [MockNet] will check that all the expected requests were
//! actually made. If there were any missed, then the test will [panic].
//!
//! If you don't want this to happen, then call [MockNet::reset] before your test finishes.
//! You will need to recover the [MockNet] from the [Net].
//!
//! ```rust
//! # use kxio::net;
//! # #[tokio::main]
//! # async fn main() -> net::Result<()> {
//! # let mock_net = net::mock();
//! # let net = net::Net::from(mock_net);
//! let mock_net = kxio::net::MockNet::try_from(net).await.expect("recover mock");
//! mock_net.reset();
//! # Ok(())
//! # }
//! ````
//!
//! ## Error Handling
//!
//! The module uses a custom [Result] type that wraps `core::result::Result` with the custom [Error] enum,
//! allowing for specific error handling related to network operations.
//! Provides a testable interface over the [reqwest] crate.

mod result;
mod system;

pub use result::{Error, Result};

pub use system::{MockNet, Net};

pub use http::HeaderMap;
pub use http::Method;
pub use http::StatusCode;
pub use reqwest::Client;
pub use reqwest::Error as RequestError;
pub use reqwest::Request;
pub use reqwest::RequestBuilder;
pub use reqwest::Response;

/// Creates a new `Net`.
pub const fn new() -> Net {
    Net::new()
}

/// Creates a new `MockNet` for use in tests.
pub fn mock() -> MockNet {
    Default::default()
}