use crate::prelude::*;
use anyhow::Result;
use colorize::*;
use std::sync::Arc;
use std::time::Duration;
use test::TestDescAndFn;
use web_time::Instant;
pub struct RunnerLogger {
start_time: Instant,
case_logger: CaseLoggerEnum,
config: Arc<TestRunnerConfig>,
cases: Vec<TestDescAndResult>,
}
fn clear() {
#[cfg(target_arch = "wasm32")]
web_sys::console::clear();
#[cfg(not(target_arch = "wasm32"))]
beet_utils::prelude::terminal::clear().unwrap();
}
impl RunnerLogger {
pub const SWEET_AS: &'static str = "🤘 sweet as 🤘";
pub fn start(
config: Arc<TestRunnerConfig>,
tests: &[&TestDescAndFn],
) -> Self {
let case_logger = CaseLoggerEnum::new(config.clone(), tests);
if !config.quiet && config.watch {
clear();
}
if !config.quiet {
beet_utils::cross_log!("\n{}\n\n{config}", Self::SWEET_AS)
}
Self {
start_time: Instant::now(),
cases: Vec::new(),
case_logger,
config,
}
}
pub fn on_result(&mut self, mut result: TestDescAndResult) -> Result<()> {
if !self.config.quiet {
self.case_logger.on_result(&mut result)?;
}
self.cases.push(result);
Ok(())
}
pub fn end(mut self) {
let result_count = ResultCount::from_case_results(&self.cases);
if !self.config.quiet {
beet_utils::cross_log!("{}", self.case_results(&result_count));
}
self.on_results_printed();
if !self.config.watch && !result_count.succeeded() {
#[cfg(target_arch = "wasm32")]
beet_utils::js_runtime::exit(1);
#[cfg(not(target_arch = "wasm32"))]
std::process::exit(1);
}
}
fn on_results_printed(&mut self) {}
fn case_results(&mut self, results: &ResultCount) -> String {
let mut post_run = String::from("\n");
if results.is_empty() {
post_run += "No Tests Found\n".red().as_str();
return post_run;
} else if results.succeeded() {
post_run +=
"All tests passed\n".bold().cyan().underlined().as_str();
}
if let Some(case_logger_end_str) = self.case_logger.end_str() {
post_run += case_logger_end_str.as_str();
post_run.push('\n');
}
post_run += results.pretty_print("Tests").as_str();
post_run.push('\n');
post_run += print_time(self.start_time.elapsed()).as_str();
post_run
}
}
fn print_time(duration: Duration) -> String {
let millis = duration.as_millis();
let prefix = "Time: \t\t".bold();
if millis < 100 {
format!("{}{} ms\n\n", prefix, millis)
} else {
format!("{}{:.2} s\n\n", prefix, millis as f32 * 0.001)
}
}