Skip to content

Commit 3186493

Browse files
authored
Refactor and test info field styling (#1214)
* Refactor: move info writing logic to `InfoField` This moves the bulk of the logic for writing styled info into the `InfoField` trait as a provided set of methods. This makes each type that implements `InfoField` more testable. * Convert author value tests to styled snapshot tests
1 parent b1cf029 commit 3186493

7 files changed

+123
-90
lines changed

src/info/author.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ impl InfoField for AuthorsInfo {
126126
#[cfg(test)]
127127
mod test {
128128
use super::*;
129+
use crate::ui::text_colors::TextColors;
130+
use insta::assert_snapshot;
131+
use owo_colors::DynColors;
129132

130133
#[test]
131134
fn test_display_author() {
@@ -190,7 +193,7 @@ mod test {
190193
}
191194

192195
#[test]
193-
fn test_author_info_value_with_one_author() {
196+
fn test_author_info_with_one_author() {
194197
let author = Author::new(
195198
"John Doe".into(),
196199
Some("john.doe@email.com".into()),
@@ -202,15 +205,17 @@ mod test {
202205
let authors_info = AuthorsInfo {
203206
authors: vec![author],
204207
};
208+
let colors = TextColors::new(&[], DynColors::Rgb(0xFF, 0xFF, 0xFF));
209+
let mut buffer = String::new();
210+
authors_info
211+
.write_styled(&mut buffer, false, &colors)
212+
.unwrap();
205213

206-
assert_eq!(
207-
authors_info.value(),
208-
"75% John Doe <john.doe@email.com> 1500".to_string()
209-
);
214+
assert_snapshot!(buffer);
210215
}
211216

212217
#[test]
213-
fn test_author_info_value_with_two_authors() {
218+
fn test_author_info_with_two_authors() {
214219
let author = Author::new(
215220
"John Doe".into(),
216221
Some("john.doe@email.com".into()),
@@ -231,16 +236,16 @@ mod test {
231236
authors: vec![author, author_2],
232237
};
233238

234-
assert!(authors_info
235-
.value()
236-
.contains(&"75% John Doe <john.doe@email.com> 1500".to_string()));
239+
let colors = TextColors::new(&[], DynColors::Rgb(0xFF, 0xFF, 0xFF));
240+
let mut buffer = String::new();
241+
authors_info
242+
.write_styled(&mut buffer, false, &colors)
243+
.unwrap();
237244

238-
assert!(authors_info
239-
.value()
240-
.contains(&"80% Roberto Berto 240".to_string()));
245+
assert_snapshot!(buffer);
241246
}
242247
#[test]
243-
fn test_author_info_value_alignment_with_three_authors() {
248+
fn test_author_info_alignment_with_three_authors() {
244249
let author = Author::new(
245250
"John Doe".into(),
246251
Some("john.doe@email.com".into()),
@@ -263,15 +268,12 @@ mod test {
263268
authors: vec![author, author_2, author_3],
264269
};
265270

266-
assert!(authors_info
267-
.value()
268-
.contains(&"75% John Doe <john.doe@email.com> 1500".to_string()));
269-
270-
assert!(authors_info
271-
.value()
272-
.contains(&"80% Roberto Berto 240".to_string()));
271+
let colors = TextColors::new(&[], DynColors::Rgb(0xFF, 0xFF, 0xFF));
272+
let mut buffer = String::new();
273+
authors_info
274+
.write_styled(&mut buffer, false, &colors)
275+
.unwrap();
273276

274-
// Note the extra leading space to right-align the percentages
275-
assert!(authors_info.value().contains(&" 1% Jane Doe 1".to_string()));
277+
assert_snapshot!(buffer);
276278
}
277279
}

src/info/mod.rs

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,7 @@ impl std::fmt::Display for Info {
8787

8888
//Info lines
8989
for info_field in self.info_fields.iter() {
90-
let info_field_value = info_field.value();
91-
if !info_field_value.is_empty() {
92-
write_styled_info_line(
93-
f,
94-
&info_field.title(),
95-
&info_field_value,
96-
self.no_bold,
97-
&self.text_colors,
98-
)?;
99-
}
90+
info_field.write_styled(f, self.no_bold, &self.text_colors)?;
10091
}
10192

10293
//Palette
@@ -418,43 +409,6 @@ impl InfoBuilder {
418409
}
419410
}
420411

421-
fn write_styled_info_line(
422-
f: &mut std::fmt::Formatter,
423-
subtitle: &str,
424-
info: &str,
425-
no_bold: bool,
426-
text_colors: &TextColors,
427-
) -> std::fmt::Result {
428-
writeln!(
429-
f,
430-
"{} {}",
431-
style_subtitle(subtitle, text_colors, no_bold),
432-
style_info(info, text_colors)
433-
)
434-
}
435-
436-
fn style_info(info: &str, text_colors: &TextColors) -> String {
437-
let info_lines: Vec<&str> = info.lines().collect();
438-
let info_style = get_style(false, text_colors.info);
439-
440-
let styled_lines: Vec<String> = info_lines
441-
.iter()
442-
.map(|line| format!("{}", line.style(info_style)))
443-
.collect();
444-
445-
styled_lines.join("\n")
446-
}
447-
448-
fn style_subtitle(subtitle: &str, text_colors: &TextColors, no_bold: bool) -> String {
449-
let subtitle_style = get_style(!no_bold, text_colors.subtitle);
450-
let colon_style = get_style(!no_bold, text_colors.colon);
451-
format!(
452-
"{}{}",
453-
subtitle.style(subtitle_style),
454-
":".style(colon_style)
455-
)
456-
}
457-
458412
fn get_style(is_bold: bool, color: DynColors) -> Style {
459413
let mut style = Style::new().color(color);
460414
if is_bold {
@@ -526,25 +480,4 @@ mod tests {
526480
"1000000"
527481
);
528482
}
529-
530-
#[test]
531-
fn test_info_style_info() {
532-
let text_colors = TextColors::new(&[0, 0, 0, 0, 0, 0], DynColors::Ansi(AnsiColors::Blue));
533-
534-
let info_text = style_info("foo", &text_colors);
535-
// Rendered text: black `foo`
536-
assert_eq!(info_text, "\u{1b}[30mfoo\u{1b}[0m");
537-
}
538-
539-
#[test]
540-
fn test_info_style_subtitle() {
541-
let text_colors = TextColors::new(&[0, 0, 0, 0, 15, 0], DynColors::Ansi(AnsiColors::Blue));
542-
543-
let subtitle_text = style_subtitle("foo", &text_colors, false);
544-
assert_eq!(
545-
subtitle_text,
546-
// Rendered text: black `foo` and bright white colon
547-
"\u{1b}[30;1mfoo\u{1b}[0m\u{1b}[97;1m:\u{1b}[0m"
548-
);
549-
}
550483
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
source: src/info/author.rs
3+
expression: buffer
4+
---
5+
Authors: 75% John Doe <john.doe@email.com> 1500
6+
 80% Roberto Berto 240
7+
 1% Jane Doe 1
8+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
source: src/info/author.rs
3+
expression: buffer
4+
---
5+
Author: 75% John Doe <john.doe@email.com> 1500
6+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
source: src/info/author.rs
3+
expression: buffer
4+
---
5+
Authors: 75% John Doe <john.doe@email.com> 1500
6+
 80% Roberto Berto 240
7+

src/info/utils/info_field.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,59 @@
1+
use super::super::get_style;
2+
use crate::ui::text_colors::TextColors;
3+
use owo_colors::OwoColorize;
4+
use std::fmt;
5+
16
#[typetag::serialize]
27
pub trait InfoField {
38
fn value(&self) -> String;
49
fn title(&self) -> String;
10+
11+
/// Writes the styled info field. If the info doesn't have a value, nothing is
12+
/// written.
13+
fn write_styled(
14+
&self,
15+
w: &mut dyn fmt::Write,
16+
no_bold: bool,
17+
text_colors: &TextColors,
18+
) -> fmt::Result {
19+
if let Some(styled_value) = self.style_value(text_colors) {
20+
writeln!(
21+
w,
22+
"{} {}",
23+
self.style_title(text_colors, no_bold),
24+
styled_value
25+
)
26+
} else {
27+
Ok(())
28+
}
29+
}
30+
31+
/// Returns a styled version of the info field's title.
32+
fn style_title(&self, text_colors: &TextColors, no_bold: bool) -> String {
33+
let subtitle_style = get_style(!no_bold, text_colors.subtitle);
34+
let colon_style = get_style(!no_bold, text_colors.colon);
35+
format!(
36+
"{}{}",
37+
self.title().style(subtitle_style),
38+
":".style(colon_style)
39+
)
40+
}
41+
42+
/// Returns a styled version of the info field's value. This can be `None` if the
43+
/// value is empty.
44+
fn style_value(&self, text_colors: &TextColors) -> Option<String> {
45+
let value = self.value();
46+
if value.is_empty() {
47+
return None;
48+
}
49+
let style = get_style(false, text_colors.info);
50+
let styled_lines: Vec<String> = self
51+
.value()
52+
.lines()
53+
.map(|line| format!("{}", line.style(style)))
54+
.collect();
55+
Some(styled_lines.join("\n"))
56+
}
557
}
658

759
#[derive(Clone, clap::ValueEnum, Debug, Eq, PartialEq)]
@@ -27,6 +79,7 @@ pub enum InfoType {
2779

2880
#[cfg(test)]
2981
mod test {
82+
use owo_colors::DynColors;
3083
use serde::Serialize;
3184

3285
use super::*;
@@ -51,4 +104,22 @@ mod test {
51104
assert_eq!(info.title(), "title".to_string());
52105
assert_eq!(info.value(), "test".to_string());
53106
}
107+
108+
#[test]
109+
fn test_write_styled() {
110+
let colors = TextColors::new(&[], DynColors::Rgb(0xFF, 0xFF, 0xFF));
111+
let info = InfoFieldImpl("test");
112+
let mut buffer = String::new();
113+
info.write_styled(&mut buffer, false, &colors).unwrap();
114+
insta::assert_snapshot!(buffer);
115+
}
116+
117+
#[test]
118+
fn test_write_styled_no_value() {
119+
let colors = TextColors::new(&[], DynColors::Rgb(0xFF, 0xFF, 0xFF));
120+
let info = InfoFieldImpl("");
121+
let mut buffer = String::new();
122+
info.write_styled(&mut buffer, false, &colors).unwrap();
123+
assert_eq!(buffer, "", "It should not write anything");
124+
}
54125
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
source: src/info/utils/info_field.rs
3+
expression: buffer
4+
---
5+
title: test
6+

0 commit comments

Comments
 (0)