Add testing module that exposes parse methods (#262)

This commit is contained in:
Edward Rudd 2023-08-25 12:47:03 -04:00 committed by GitHub
parent 8148edf6ff
commit 3ca961a282
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 220 additions and 2 deletions

View file

@ -16,6 +16,8 @@ categories = ["email", "network-programming"]
[features]
rustls-tls = ["rustls-connector"]
default = ["native-tls"]
# Used to expose helpers in the imap::testing module to build response objects
test_helpers = []
# Used to activate full integration tests when running against a more complete IMAP server
test-full-imap = []
@ -69,3 +71,6 @@ required-features = ["default"]
[[test]]
name = "imap_integration"
required-features = ["default"]
[package.metadata.docs.rs]
all-features = true

View file

@ -95,5 +95,8 @@ pub use error::{Error, Result};
pub mod extensions;
#[cfg(feature = "test_helpers")]
pub mod testing;
#[cfg(test)]
mod mock_stream;

210
src/testing.rs Normal file
View file

@ -0,0 +1,210 @@
//! Enable the test_helpers feature to expose helper methods to build
//! mock response structures for testing your code that uses the imap crate
//!
//! To use add a dev-dependency on the imap extension adding the feature "test_helpers"
//! e.g.
//!
//! ```toml
//! [dependencies]
//! imap = { version = "3.0" }
//!
//! [dev-dependencies]
//! # mirror the same configuration your dependencies and add test_helpers
//! imap = { version = "3.0", features = ["test_helpers"] }
//! ```
//!
/// Methods to build a [`Capabilities`] response object
pub mod capabilities {
use crate::types::Capabilities;
use std::sync::mpsc;
/// Builds an [`Capabilities`] based on the provided input
///
/// Example input.
///
/// ```
/// let input = "* CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI LOGINDISABLED\r\n";
/// let response = imap::testing::capabilities::parse(input);
/// ```
pub fn parse(input: impl Into<Vec<u8>>) -> Capabilities {
let (mut tx, _rx) = mpsc::channel();
Capabilities::parse(input.into(), &mut tx).unwrap()
}
}
/// Methods to build a [`Fetches`] response object
pub mod fetches {
use crate::types::Fetches;
use std::sync::mpsc;
/// Builds an [`Fetches`] based on the provided input
///
/// Example input.
///
/// ```
/// let input = "\
/// * 24 FETCH (FLAGS (\\Seen) UID 4827943)\r\n\
/// * 25 FETCH (FLAGS (\\Seen))\r\n\
/// ";
/// let response = imap::testing::fetches::parse(input);
/// ```
pub fn parse(input: impl Into<Vec<u8>>) -> Fetches {
let (mut tx, _rx) = mpsc::channel();
Fetches::parse(input.into(), &mut tx).unwrap()
}
}
/// Methods to build a [`Names`] response object
pub mod names {
use crate::types::Names;
use std::sync::mpsc;
/// Builds an [`Names`] based on the provided input
/// Example input.
///
/// ```
/// let input = "\
/// * LIST (\\HasNoChildren) \".\" \"INBOX\"\r\n\
/// ";
/// let response = imap::testing::names::parse(input);
///```
pub fn parse(input: impl Into<Vec<u8>>) -> Names {
let (mut tx, _rx) = mpsc::channel();
Names::parse(input.into(), &mut tx).unwrap()
}
}
/// Methods to build a [`ExtendedNames`] response object
pub mod extended_names {
use crate::extensions::list_status::ExtendedNames;
use std::sync::mpsc;
/// Builds an [`ExtendedNames`] based on the provided input
///
/// Example input.
///
/// ```
/// let input = "\
/// * LIST () \".\" foo\r\n\
/// * STATUS foo (HIGHESTMODSEQ 122)\r\n\
/// * LIST () \".\" foo.bar\r\n\
/// * STATUS foo.bar (HIGHESTMODSEQ 132)\r\n\
/// * LIST (\\UnMarked) \".\" feeds\r\n\
/// * LIST () \".\" feeds.test\r\n\
/// * STATUS feeds.test (HIGHESTMODSEQ 757)\r\n\
/// ";
/// let response = imap::testing::extended_names::parse(input);
/// ```
pub fn parse(input: impl Into<Vec<u8>>) -> ExtendedNames {
let (mut tx, _rx) = mpsc::channel();
ExtendedNames::parse(input.into(), &mut tx).unwrap()
}
}
/// Methods to build a [`AclResponse`] response object
pub mod acl_response {
use crate::types::AclResponse;
use std::sync::mpsc;
/// Builds an [`AclResponse`] based on the provided input
///
/// Example input.
///
/// ```
/// let input = "* ACL INBOX user1 lr user2 lrx\r\n";
/// let response = imap::testing::acl_response::parse(input);
/// ```
pub fn parse(input: impl Into<Vec<u8>>) -> AclResponse {
let (mut tx, _rx) = mpsc::channel();
AclResponse::parse(input.into(), &mut tx).unwrap()
}
}
/// Methods to build a [`ListRightsResponse`] response object
pub mod list_rights_response {
use crate::types::ListRightsResponse;
use std::sync::mpsc;
/// Builds an [`ListRightsResponse`] based on the provided input
///
/// Example input.
///
/// ```
/// let input = "* LISTRIGHTS INBOX myuser lr x k\r\n";
/// let response = imap::testing::list_rights_response::parse(input);
///```
pub fn parse(input: impl Into<Vec<u8>>) -> ListRightsResponse {
let (mut tx, _rx) = mpsc::channel();
ListRightsResponse::parse(input.into(), &mut tx).unwrap()
}
}
/// Methods to build a [`MyRightsResponse`] response object
pub mod my_rights_response {
use crate::types::MyRightsResponse;
use std::sync::mpsc;
/// Builds an [`MyRightsResponse`] based on the provided input
///
/// Example input.
///
/// ```
/// let input = "* MYRIGHTS INBOX lrxk\r\n";
/// let response = imap::testing::my_rights_response::parse(input);
/// ```
pub fn parse(input: impl Into<Vec<u8>>) -> MyRightsResponse {
let (mut tx, _rx) = mpsc::channel();
MyRightsResponse::parse(input.into(), &mut tx).unwrap()
}
}
/// Methods to build a [`QuotaResponse`] response object
pub mod quota_response {
use crate::types::QuotaResponse;
use std::sync::mpsc;
/// Builds an [`QuotaResponse`] based on the provided input
///
/// Example input.
///
/// ```
/// let input = "* QUOTA my_root (STORAGE 10 500)\r\n";
/// let response = imap::testing::quota_response::parse(input);
/// ```
pub fn parse(input: impl Into<Vec<u8>>) -> QuotaResponse {
let (mut tx, _rx) = mpsc::channel();
QuotaResponse::parse(input.into(), &mut tx).unwrap()
}
}
/// Methods to build a [`QuotaRootResponse`] response object
pub mod quota_root_response {
use crate::types::QuotaRootResponse;
use std::sync::mpsc;
/// Builds an [`QuotaRootResponse`] based on the provided input
///
/// Example input.
///
/// ```
/// let input = "\
/// * QUOTAROOT INBOX my_root\r\n\
/// * QUOTA my_root (STORAGE 10 500)\r\n\
/// ";
/// let response = imap::testing::quota_root_response::parse(input);
/// ```
pub fn parse(input: impl Into<Vec<u8>>) -> QuotaRootResponse {
let (mut tx, _rx) = mpsc::channel();
QuotaRootResponse::parse(input.into(), &mut tx).unwrap()
}
}

View file

@ -93,7 +93,7 @@ pub struct QuotaResponse {
impl QuotaResponse {
/// Parse the [`Quota`] response from a response buffer.
pub fn parse(
pub(crate) fn parse(
owned: Vec<u8>,
unsolicited: &mut mpsc::Sender<UnsolicitedResponse>,
) -> Result<Self, Error> {
@ -188,7 +188,7 @@ pub(crate) struct InnerQuotaRootResponse<'a> {
impl QuotaRootResponse {
/// Parse the [`QuotaRoot`] response from a response buffer.
pub fn parse(
pub(crate) fn parse(
owned: Vec<u8>,
unsolicited: &mut mpsc::Sender<UnsolicitedResponse>,
) -> Result<Self, Error> {