runx_runtime/dev/
presentation.rs1use crate::dev::types::{DevFixtureStatus, DevReport, DevReportStatus};
2
3#[derive(Clone, Debug, PartialEq, Eq)]
4pub struct DevRenderTheme {
5 pub success: &'static str,
6 pub failure: &'static str,
7 pub skipped: &'static str,
8 pub needs_approval: &'static str,
9}
10
11impl Default for DevRenderTheme {
12 fn default() -> Self {
13 Self {
14 success: "โ",
15 failure: "โ",
16 skipped: "ยท",
17 needs_approval: "โ",
18 }
19 }
20}
21
22#[must_use]
23pub fn render_dev_result(result: &DevReport) -> String {
24 render_dev_result_with_theme(result, &DevRenderTheme::default())
25}
26
27#[must_use]
28pub fn render_dev_result_with_theme(result: &DevReport, theme: &DevRenderTheme) -> String {
29 let mut lines = vec![
30 String::new(),
31 format!(
32 " {} dev {} fixture(s)",
33 status_icon(&result.status, theme),
34 result.fixtures.len()
35 ),
36 ];
37 for fixture in &result.fixtures {
38 lines.push(format!(
39 " {} {:<14} {} {}ms",
40 fixture_status_icon(&fixture.status, theme),
41 fixture.lane,
42 fixture.name,
43 fixture.duration_ms
44 ));
45 for assertion in fixture.assertions.iter().take(3) {
46 lines.push(format!(" {}: {}", assertion.path, assertion.message));
47 }
48 }
49 if let Some(receipt_id) = &result.receipt_id {
50 lines.push(format!(" receipt {receipt_id}"));
51 }
52 lines.push(String::new());
53 lines.join("\n")
54}
55
56fn status_icon(status: &DevReportStatus, theme: &DevRenderTheme) -> &'static str {
57 match status {
58 DevReportStatus::Success => theme.success,
59 DevReportStatus::Failure => theme.failure,
60 DevReportStatus::Skipped => theme.skipped,
61 DevReportStatus::NeedsApproval => theme.needs_approval,
62 }
63}
64
65fn fixture_status_icon(status: &DevFixtureStatus, theme: &DevRenderTheme) -> &'static str {
66 match status {
67 DevFixtureStatus::Success => theme.success,
68 DevFixtureStatus::Failure => theme.failure,
69 DevFixtureStatus::Skipped => theme.skipped,
70 }
71}