use crate::WebhookSender;
use std::{future::Future, sync::Mutex};
pub struct MockSender<M: Clone> {
captured: Mutex<Vec<M>>,
}
impl<M: Clone> MockSender<M> {
pub fn new() -> Self {
Self {
captured: Mutex::new(Vec::new()),
}
}
pub fn messages(&self) -> Vec<M> {
self.captured.lock().unwrap().clone()
}
pub fn len(&self) -> usize {
self.captured.lock().unwrap().len()
}
pub fn is_empty(&self) -> bool {
self.captured.lock().unwrap().is_empty()
}
pub fn clear(&self) {
self.captured.lock().unwrap().clear();
}
}
impl<M: Clone> Default for MockSender<M> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug)]
pub struct MockError;
impl std::fmt::Display for MockError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "mock sender error (this should never occur)")
}
}
impl std::error::Error for MockError {}
impl<M: Clone + Send> WebhookSender for MockSender<M> {
type Message = M;
type Error = MockError;
fn send(&self, message: &M) -> impl Future<Output = Result<(), MockError>> + Send {
self.captured.lock().unwrap().push(message.clone());
std::future::ready(Ok(()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::WebhookSender;
#[tokio::test]
async fn send_captures_message() {
let sender: MockSender<String> = MockSender::new();
assert!(sender.is_empty());
sender.send(&"hello".to_string()).await.unwrap();
assert_eq!(sender.len(), 1);
assert_eq!(sender.messages(), vec!["hello".to_string()]);
}
#[tokio::test]
async fn send_preserves_order() {
let sender: MockSender<i32> = MockSender::new();
for i in 0..5 {
sender.send(&i).await.unwrap();
}
assert_eq!(sender.messages(), vec![0, 1, 2, 3, 4]);
}
#[tokio::test]
async fn clear_empties_captured_messages() {
let sender: MockSender<i32> = MockSender::new();
sender.send(&1).await.unwrap();
sender.send(&2).await.unwrap();
assert_eq!(sender.len(), 2);
sender.clear();
assert!(sender.is_empty());
assert_eq!(sender.len(), 0);
}
#[tokio::test]
async fn send_batch_captures_all_messages() {
let sender: MockSender<String> = MockSender::new();
let msgs = vec!["a".to_string(), "b".to_string(), "c".to_string()];
let refs: Vec<&String> = msgs.iter().collect();
let results = sender.send_batch(&refs).await;
assert_eq!(results.len(), 3);
assert!(results.iter().all(|r| r.is_ok()));
assert_eq!(sender.len(), 3);
assert_eq!(sender.messages(), msgs);
}
#[test]
fn default_is_empty() {
let sender: MockSender<()> = MockSender::default();
assert!(sender.is_empty());
}
}