use super::*;
#[test]
fn splash_rows_are_padded_to_one_width() {
for art in [&SPLASH_ART[..], &SPLASH_ART_COMPACT[..]] {
let width = art[0].chars().count();
for row in art {
assert_eq!(row.chars().count(), width, "ragged row: {row:?}");
}
}
}
#[test]
fn splash_art_yields_to_the_text_when_the_terminal_is_short() {
assert_eq!(splash_art(40, 11).map(|a| a.len()), Some(SPLASH_ART.len()));
assert_eq!(
splash_art(11 + SPLASH_ART.len(), 11).map(|a| a.len()),
Some(SPLASH_ART_COMPACT.len())
);
assert!(splash_art(11 + SPLASH_ART_COMPACT.len(), 11).is_none());
assert!(splash_art(0, 11).is_none());
}
#[test]
fn first_run_guidance_names_no_config_path() {
for line in NO_DATABASE_STEPS
.iter()
.chain([&NO_DATABASE_HEADLINE, &NO_DATABASE_FOOTER])
{
assert!(
!line.contains(".saya"),
"guidance must let `config init` report the path: {line}"
);
}
}
#[test]
fn first_run_guidance_names_real_commands() {
let all = NO_DATABASE_STEPS.join(" ") + NO_DATABASE_FOOTER;
for command in [
"saya config init",
"saya connection test",
"saya config doctor",
] {
assert!(all.contains(command), "guidance should offer `{command}`");
}
}
#[test]
fn unbound_workspace_line_names_the_fact_and_the_remedy() {
let all = NO_WORKSPACE_LINES.join(" ");
assert!(
all.contains("No workspace is bound"),
"the line states the fact: {all}"
);
assert!(
all.contains("file tools are unavailable"),
"the line names why the file tools are absent: {all}"
);
assert!(
all.contains("--workspace <dir>"),
"the line names the explicit-bind remedy: {all}"
);
assert!(
all.contains("git worktree"),
"the line names the worktree remedy: {all}"
);
}
#[test]
fn first_run_guidance_fits_a_narrow_terminal() {
for line in NO_DATABASE_STEPS
.iter()
.chain([&NO_DATABASE_HEADLINE, &NO_DATABASE_FOOTER])
.chain(&NO_WORKSPACE_LINES)
{
assert!(line.chars().count() <= 64, "too wide to centre: {line}");
}
}
#[test]
fn both_pupils_are_styled_as_cursors() {
for art in [&SPLASH_ART[..], &SPLASH_ART_COMPACT[..]] {
let lines = art_lines(art);
let bold: Vec<String> = lines
.iter()
.flat_map(|line| &line.spans)
.filter(|span| span.style.add_modifier.contains(Modifier::BOLD))
.map(|span| span.content.to_string())
.collect();
assert_eq!(
bold,
vec!["\u{2590}", "\u{258c}"],
"expected exactly two pupils"
);
}
}
#[test]
fn styling_preserves_every_glyph_in_the_row() {
for art in [&SPLASH_ART[..], &SPLASH_ART_COMPACT[..]] {
for (row, line) in art.iter().zip(art_lines(art)) {
let rendered: String = line.spans.iter().map(|s| s.content.as_ref()).collect();
assert_eq!(&rendered, row, "row must survive styling unchanged");
}
}
}
#[test]
fn beak_and_talons_recede_behind_the_body() {
let secondary_style = Style::default().fg(secondary());
for ch in ['\u{25bc}', '\u{2580}'] {
assert_eq!(glyph_style(ch), secondary_style, "{ch} should recede");
}
assert_eq!(glyph_style('\u{2588}'), Style::default().fg(accent()));
}