🧪 test(message-list): add test-only GmailService mock and end-to-end pagination test (no network)
This commit is contained in:
committed by
Jeremiah Russell
parent
4c5378c90b
commit
34125e7d5c
@@ -642,6 +642,130 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
struct TestClient {
|
||||||
|
label_ids: Vec<String>,
|
||||||
|
query: String,
|
||||||
|
max_results: u32,
|
||||||
|
messages: Vec<MessageSummary>,
|
||||||
|
pages: Mutex<HashMap<Option<String>, ListMessagesResponse>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestClient {
|
||||||
|
fn with_pages(map: HashMap<Option<String>, ListMessagesResponse>) -> Self {
|
||||||
|
Self {
|
||||||
|
label_ids: vec![],
|
||||||
|
query: String::new(),
|
||||||
|
max_results: 200,
|
||||||
|
messages: vec![],
|
||||||
|
pages: Mutex::new(map),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl super::GmailService for TestClient {
|
||||||
|
async fn list_messages_page(
|
||||||
|
&self,
|
||||||
|
_label_ids: &[String],
|
||||||
|
_query: &str,
|
||||||
|
_max_results: u32,
|
||||||
|
page_token: Option<String>,
|
||||||
|
) -> Result<ListMessagesResponse> {
|
||||||
|
let map = self.pages.lock().unwrap();
|
||||||
|
Ok(map
|
||||||
|
.get(&page_token)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(ListMessagesResponse::default))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_message_metadata(&self, _message_id: &str) -> Result<GmailMessage> {
|
||||||
|
Ok(GmailMessage::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageList for TestClient {
|
||||||
|
fn set_max_results(&mut self, value: u32) {
|
||||||
|
self.max_results = value;
|
||||||
|
}
|
||||||
|
fn max_results(&self) -> u32 {
|
||||||
|
self.max_results
|
||||||
|
}
|
||||||
|
fn add_labels(&mut self, _labels: &[String]) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn add_labels_ids(&mut self, label_ids: &[String]) {
|
||||||
|
self.label_ids.extend_from_slice(label_ids);
|
||||||
|
}
|
||||||
|
fn set_query(&mut self, query: &str) {
|
||||||
|
self.query = query.to_string();
|
||||||
|
}
|
||||||
|
fn messages(&self) -> &Vec<MessageSummary> {
|
||||||
|
&self.messages
|
||||||
|
}
|
||||||
|
fn message_ids(&self) -> Vec<String> {
|
||||||
|
self.messages.iter().map(|m| m.id().to_string()).collect()
|
||||||
|
}
|
||||||
|
fn label_ids(&self) -> Vec<String> {
|
||||||
|
self.label_ids.clone()
|
||||||
|
}
|
||||||
|
fn hub(&self) -> Gmail<HttpsConnector<HttpConnector>> {
|
||||||
|
unimplemented!("not used in tests")
|
||||||
|
}
|
||||||
|
async fn get_messages(&mut self, pages: u32) -> Result<()> {
|
||||||
|
let mut list = self.list_messages(None).await?;
|
||||||
|
match pages {
|
||||||
|
1 => {}
|
||||||
|
0 => loop {
|
||||||
|
if list.next_page_token.is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
list = self.list_messages(list.next_page_token).await?;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
for _page in 2..=pages {
|
||||||
|
if list.next_page_token.is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
list = self.list_messages(list.next_page_token).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
async fn list_messages(
|
||||||
|
&mut self,
|
||||||
|
next_page_token: Option<String>,
|
||||||
|
) -> Result<ListMessagesResponse> {
|
||||||
|
let list = self
|
||||||
|
.list_messages_page(
|
||||||
|
&self.label_ids,
|
||||||
|
&self.query,
|
||||||
|
self.max_results,
|
||||||
|
next_page_token,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if list.result_size_estimate.unwrap_or(0) == 0 {
|
||||||
|
return Ok(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(msgs) = &list.messages {
|
||||||
|
let mut list_ids: Vec<MessageSummary> = msgs
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| item.id.as_deref().map(MessageSummary::new))
|
||||||
|
.collect();
|
||||||
|
self.messages.append(&mut list_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
async fn log_messages(&mut self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_query_updates_state() {
|
fn set_query_updates_state() {
|
||||||
let mut ml = MockList::new();
|
let mut ml = MockList::new();
|
||||||
@@ -702,4 +826,41 @@ mod tests {
|
|||||||
let ids: Vec<_> = out.iter().map(|m| m.id().to_string()).collect();
|
let ids: Vec<_> = out.iter().map(|m| m.id().to_string()).collect();
|
||||||
assert_eq!(ids, vec!["m1", "m2"]);
|
assert_eq!(ids, vec!["m1", "m2"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn list_messages_across_pages_collects_ids() {
|
||||||
|
use google_gmail1::api::Message;
|
||||||
|
let page1 = ListMessagesResponse {
|
||||||
|
messages: Some(vec![
|
||||||
|
Message {
|
||||||
|
id: Some("a".into()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Message {
|
||||||
|
id: Some("b".into()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
next_page_token: Some("t2".into()),
|
||||||
|
result_size_estimate: Some(2),
|
||||||
|
};
|
||||||
|
let page2 = ListMessagesResponse {
|
||||||
|
messages: Some(vec![Message {
|
||||||
|
id: Some("c".into()),
|
||||||
|
..Default::default()
|
||||||
|
}]),
|
||||||
|
next_page_token: None,
|
||||||
|
result_size_estimate: Some(1),
|
||||||
|
};
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
map.insert(None, page1);
|
||||||
|
map.insert(Some("t2".into()), page2);
|
||||||
|
|
||||||
|
let mut client = TestClient::with_pages(map);
|
||||||
|
client.set_max_results(2);
|
||||||
|
client.set_query("in:inbox");
|
||||||
|
|
||||||
|
client.get_messages(0).await.unwrap();
|
||||||
|
assert_eq!(client.message_ids(), vec!["a", "b", "c"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user