feat: Add jmap-client dependency and integration test for successful email listing
Some checks failed
GBCI / build (push) Has been cancelled

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-06-15 23:53:02 -03:00
parent 0a27030de3
commit 9c4a21379b
7 changed files with 156 additions and 45 deletions

30
.lapce/run.toml Normal file
View file

@ -0,0 +1,30 @@
# The run config is used for both run mode and debug mode
[[configs]]
# the name of this task
name = "task"
# the type of the debugger. If not set, it can't be debugged but can still be run
# type = "lldb"
# the program to run, e.g. "${workspace}\\target\\debug\\check.exe"
program = ""
# the program arguments, e.g. args = ["arg1", "arg2"], optional
# args = []
# current working directory, optional
# cwd = "${workspace}"
# environment variables, optional
# [configs.env]
# VAR1 = "VAL1"
# VAR2 = "VAL2"
# task to run before the run/debug session is started, optional
# [configs.prelaunch]
# program = "cargo"
# args = [
# "build",
# ]

19
Cargo.lock generated
View file

@ -268,6 +268,7 @@ dependencies = [
"cfg-if",
"getrandom 0.2.15",
"once_cell",
"serde",
"version_check",
"zerocopy 0.7.35",
]
@ -3112,6 +3113,7 @@ dependencies = [
"gb-server",
"goose",
"hyper 1.6.0",
"jmap-client",
"minio",
"opentelemetry 0.20.0",
"predicates",
@ -4309,6 +4311,23 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jmap-client"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d478b6514a12725ee2653689846b49c8dd18c215dcc5b84ea02ba9b079bc4f"
dependencies = [
"ahash",
"async-stream",
"base64 0.13.1",
"chrono",
"futures-util",
"parking_lot 0.12.3",
"reqwest 0.11.27",
"serde",
"serde_json",
]
[[package]]
name = "jobserver"
version = "0.1.32"

View file

@ -1,6 +1,6 @@
use log::{info, Level, LevelFilter, Metadata, Record};
use std::io::Write;
use tokio::io::{AsyncWriteExt};
use log::{info, LevelFilter};
use tokio::net::TcpStream;
use actix_web::{middleware, web, App, HttpServer};
@ -21,20 +21,20 @@ async fn main() -> std::io::Result<()> {
.init();
// Configure the logger
log::set_logger(&VectorLogger { stream: TcpStream::connect("127.0.0.1:9000").await? })
.map_err(|_| "Couldn't set logger")?;
log::set_max_level(LevelFilter::Info);
// log::set_logger(&VectorLogger { stream: TcpStream::connect("127.0.0.1:9000").await? })
// .map_err(|_| "Couldn't set logger")?;
// log::set_max_level(LevelFilter::Info);
// Get the Vector agent's address and port
let vector_host = "127.0.0.1";
let vector_port = 9000;
// Start a Vector logger
let mut vector_logger = VectorLogger::new(vector_host, vector_port).await?;
// // Start a Vector logger
// let mut vector_logger = VectorLogger::new(vector_host, vector_port).await?;
// Set the logger
log::set_logger(&vector_logger).map_err(|_| "Couldn't set logger")?;
log::set_max_level(LevelFilter::Info);
// // Set the logger
// log::set_logger(&vector_logger).map_err(|_| "Couldn't set logger")?;
// log::set_max_level(LevelFilter::Info);
// Log some messages
info!("Hello from Rust!");

View file

@ -71,3 +71,6 @@ rstest = { workspace = true }
wiremock = "0.5"
assert_cmd = "2.0"
predicates = "3.0"
jmap-client = "0.1" # Check for the latest version on crates.io

1
gb-testing/README.md Normal file
View file

@ -0,0 +1 @@
cargo test --package gb-testing --test integration_email_list -- test_successful_email_lilst --exact --show-output

View file

@ -0,0 +1,58 @@
use anyhow::Result;
use jmap_client::{
client::{Client, Credentials},
core::query::Filter,
email::{self, Property},
mailbox::{self, Role},
};
#[tokio::test]
async fn test_successful_email_list() -> Result<()> {
// JMAP server configuration
// 1. Authenticate with JMAP server
let client = Client::new()
.credentials(("test@", ""))
.connect("https://mail/jmap/")
.await
.unwrap();
let inbox_id = client
.mailbox_query(
mailbox::query::Filter::role(Role::Inbox).into(),
None::<Vec<_>>,
)
.await
.unwrap()
.take_ids()
.pop()
.unwrap();
let email_id = client
.email_query(
Filter::and([
// email::query::Filter::subject("test"),
email::query::Filter::in_mailbox(&inbox_id),
// email::query::Filter::has_keyword("$draft"),
])
.into(),
[email::query::Comparator::from()].into(),
)
.await
.unwrap()
.take_ids()
.pop()
.unwrap();
// Fetch message
let email = client
.email_get(
&email_id,
[Property::Subject, Property::Preview, Property::Keywords].into(),
)
.await
.unwrap();
Ok(())
}

View file

@ -1,45 +1,45 @@
use log::{info, Level, LevelFilter, Metadata, Record};
use tracing::log::{info, Level, LevelFilter, Metadata, Record};
use std::io::Write;
use tokio::io::{AsyncWriteExt};
use tokio::net::TcpStream;
// A simple logger implementation that sends logs to Vector
struct VectorLogger {
stream: TcpStream,
}
// // A simple logger implementation that sends logs to Vector
// struct VectorLogger {
// stream: TcpStream,
// }
impl VectorLogger {
async fn new(host: &str, port: u16) -> Result<Self, std::io::Error> {
let stream = TcpStream::connect(format!("{}:{}", host, port)).await?;
Ok(VectorLogger { stream })
}
}
// impl VectorLogger {
// async fn new(host: &str, port: u16) -> Result<Self, std::io::Error> {
// let stream = TcpStream::connect(format!("{}:{}", host, port)).await?;
// Ok(VectorLogger { stream })
// }
// }
impl log::Log for VectorLogger {
fn enabled(&self, _metadata: &Metadata) -> bool {
true
}
// impl log::Log for VectorLogger {
// fn enabled(&self, _metadata: &Metadata) -> bool {
// true
// }
fn log(&self, record: &Record) {
let _ = self.log_async(record).await;
}
// fn log(&self, record: &Record) {
// let _ = self.log_async(record).await;
// }
fn flush(&self) {}
}
// fn flush(&self) {}
// }
impl VectorLogger {
async fn log_async(&self, record: &Record) -> Result<(), std::io::Error> {
let log_event = format!(
"{{\"level\":\"{}\", \"message\":\"{}\", \"module\":\"{}\", \"file\":\"{}\", \"line\":{}}}\n",
record.level(),
record.args(),
record.location().module_path(),
record.location().file(),
record.location().line()
);
// impl VectorLogger {
// async fn log_async(&self, record: &Record) -> Result<(), std::io::Error> {
// let log_event = format!(
// "{{\"level\":\"{}\", \"message\":\"{}\", \"module\":\"{}\", \"file\":\"{}\", \"line\":{}}}\n",
// record.level(),
// record.args(),
// record.location().module_path(),
// record.location().file(),
// record.location().line()
// );
self.stream.write_all(log_event.as_bytes()).await?;
Ok(())
}
}
// self.stream.write_all(log_event.as_bytes()).await?;
// Ok(())
// }
// }