use async_trait::async_trait;
use super::{Reporter, ReporterEvent};
use crate::model::TestStatus;
pub struct GithubReporter {
delegate: Box<dyn Reporter>,
enabled: bool,
}
impl GithubReporter {
#[must_use]
pub fn new(delegate: Box<dyn Reporter>) -> Self {
let enabled = std::env::var("GITHUB_ACTIONS").is_ok();
Self { delegate, enabled }
}
pub fn with_enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
}
#[async_trait]
impl Reporter for GithubReporter {
async fn on_event(&mut self, event: &ReporterEvent) {
if self.enabled {
if let ReporterEvent::TestFinished { test_id, outcome } = event {
if matches!(outcome.status, TestStatus::Failed | TestStatus::TimedOut) {
let title = test_id.full_name().replace(['\r', '\n'], " ");
let message = outcome
.error
.as_ref()
.map(|e| escape(&e.message))
.unwrap_or_else(|| "test failed".to_string());
let file = test_id.file.replace(['\r', '\n'], " ");
let line = test_id.line.unwrap_or(1);
println!("::error file={file},line={line},title={title}::{message}");
}
}
}
self.delegate.on_event(event).await;
}
async fn finalize(&mut self) -> ferridriver::error::Result<()> {
self.delegate.finalize().await
}
}
fn escape(s: &str) -> String {
s.replace('%', "%25").replace('\r', "%0D").replace('\n', "%0A")
}