Skip to content

Commit 84e79ae

Browse files
echobtcursoragent
authored andcommitted
test(tui): extract green lock asserts from oversized modules
Move the new palette/rounded-box checks into lock_palette.rs so lock_proof.rs and lock_v2.rs stay at their QUALITY_BASE line counts. Co-authored-by: Mathis <echobt@users.noreply.github.com>
1 parent 13350c0 commit 84e79ae

4 files changed

Lines changed: 174 additions & 82 deletions

File tree

src/cortex-tui/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub mod runner;
101101

102102
// Visual-lock PNG / ANSI captures
103103
pub mod lock_boards;
104+
pub mod lock_palette;
104105
pub mod lock_proof;
105106
pub mod lock_v2;
106107
pub mod readme_hero;

src/cortex-tui/src/lock_palette.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
//! Green-lock palette asserts.
2+
//!
3+
//! Split out of [`crate::lock_proof`] and [`crate::lock_v2`] the same way
4+
//! [`crate::splash_chrome`] was extracted from lock boards: the signed accent
5+
//! is banner green `#1F4945`, and those files must stay at their source-policy
6+
//! line-count baseline. Historical violet `#A78BFA`, wash `#221A38`, and gold
7+
//! `#C9A95C` are never painted.
8+
9+
use crate::lock_proof::{LockFrame, lock_scene_ids, render_lock_scene};
10+
use crate::lock_v2::{LOCK_V2_NARROW_IDS, LOCK_V2_WIDE_IDS, render_lock_v2_scene};
11+
use ratatui::buffer::Buffer;
12+
use ratatui::style::Color;
13+
14+
const SIZES: [(u16, u16); 2] = [(40, 12), (120, 40)];
15+
16+
/// Mint, navy, historical lock violet, retired wash, thinking gold — SGR tuples.
17+
const BANNED_ANSI: [&str; 7] = [
18+
"0;245;212",
19+
"26;51;48",
20+
"0;255;163",
21+
"10;22;40",
22+
"167;139;250",
23+
"34;26;56",
24+
"201;169;92",
25+
];
26+
27+
/// `#A78BFA` violet, `#221A38` wash, `#C9A95C` gold.
28+
const BANNED_RGB: [(u8, u8, u8); 3] = [(167, 139, 250), (34, 26, 56), (201, 169, 92)];
29+
30+
const RETIRED: [Color; 3] = [
31+
Color::Rgb(167, 139, 250),
32+
Color::Rgb(34, 26, 56),
33+
Color::Rgb(201, 169, 92),
34+
];
35+
36+
const ROUNDED: &[char] = &['╭', '╮', '╰', '╯'];
37+
38+
pub(crate) fn is_retired_rgb(r: u8, g: u8, b: u8) -> bool {
39+
BANNED_RGB.contains(&(r, g, b))
40+
}
41+
42+
pub(crate) fn is_hairline_box_edge(row: &str) -> bool {
43+
row.contains('─') && (row.contains('╭') || row.contains('╰'))
44+
}
45+
46+
fn row_text(buf: &Buffer, y: u16) -> String {
47+
(0..buf.area.width)
48+
.map(|x| buf[(x, y)].symbol().to_string())
49+
.collect()
50+
}
51+
52+
fn count_retired_style(frame: &LockFrame) -> u32 {
53+
let mut retired = 0u32;
54+
for y in 0..frame.buffer.area.height {
55+
for x in 0..frame.buffer.area.width {
56+
let cell = &frame.buffer[(x, y)];
57+
if let Some(Color::Rgb(r, g, b)) = cell.style().fg {
58+
if is_retired_rgb(r, g, b) {
59+
retired += 1;
60+
}
61+
}
62+
if let Some(Color::Rgb(r, g, b)) = cell.style().bg {
63+
if is_retired_rgb(r, g, b) {
64+
retired += 1;
65+
}
66+
}
67+
}
68+
}
69+
retired
70+
}
71+
72+
fn count_retired_cells(frame: &LockFrame) -> u32 {
73+
let mut retired = 0u32;
74+
for y in 0..frame.buffer.area.height {
75+
for x in 0..frame.buffer.area.width {
76+
let cell = &frame.buffer[(x, y)];
77+
if RETIRED.contains(&cell.fg) || RETIRED.contains(&cell.bg) {
78+
retired += 1;
79+
}
80+
}
81+
}
82+
retired
83+
}
84+
85+
#[cfg(test)]
86+
mod tests {
87+
use super::*;
88+
89+
#[test]
90+
fn v1_retired_palette_is_absent() {
91+
let mut retired = 0u32;
92+
for id in lock_scene_ids() {
93+
for size in SIZES {
94+
let frame = render_lock_scene(id, size.0, size.1).expect(id);
95+
for banned in BANNED_ANSI {
96+
assert!(
97+
!frame.ansi.contains(banned),
98+
"{id} paints banned color {banned} at {size:?}"
99+
);
100+
}
101+
retired += count_retired_style(&frame);
102+
for y in 0..frame.buffer.area.height {
103+
for x in 0..frame.buffer.area.width {
104+
if let Some(Color::Rgb(r, g, b)) = frame.buffer[(x, y)].style().bg {
105+
assert!(
106+
r == g && g == b,
107+
"{id} paints a tinted background {r},{g},{b} at {size:?} ({x},{y})"
108+
);
109+
}
110+
}
111+
}
112+
}
113+
}
114+
assert_eq!(
115+
retired, 0,
116+
"retired violet/wash/gold cells in lock v1 frames"
117+
);
118+
}
119+
120+
#[test]
121+
fn v1_rounded_glyphs_stay_on_hairline_boxes() {
122+
for id in lock_scene_ids() {
123+
for size in SIZES {
124+
let frame = render_lock_scene(id, size.0, size.1).expect(id);
125+
let buf = &frame.buffer;
126+
for y in 0..buf.area.height {
127+
let row = row_text(buf, y);
128+
for x in 0..buf.area.width {
129+
let Some(ch) = buf[(x, y)].symbol().chars().next() else {
130+
continue;
131+
};
132+
if !ROUNDED.contains(&ch) {
133+
continue;
134+
}
135+
assert!(
136+
is_hairline_box_edge(&row),
137+
"{id} paints rounded `{ch}` off a hairline box at {size:?} ({x},{y}):\n{row}"
138+
);
139+
}
140+
}
141+
}
142+
}
143+
}
144+
145+
#[test]
146+
fn v2_retired_palette_is_absent() {
147+
let mut retired = 0u32;
148+
for (width, height, ids) in [
149+
(120u16, 40u16, LOCK_V2_WIDE_IDS),
150+
(40u16, 12u16, LOCK_V2_NARROW_IDS),
151+
] {
152+
for id in ids {
153+
let frame =
154+
render_lock_v2_scene(id, width, height).unwrap_or_else(|e| panic!("{id}: {e}"));
155+
retired += count_retired_cells(&frame);
156+
}
157+
}
158+
assert_eq!(
159+
retired, 0,
160+
"retired violet/wash/gold cells in lock v2 frames"
161+
);
162+
}
163+
}

src/cortex-tui/src/lock_proof.rs

Lines changed: 9 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ fn capture_config(width: u16, height: u16) -> CaptureConfig {
176176
.with_cursor(false)
177177
}
178178

179-
fn render_lock_scene(id: &str, width: u16, height: u16) -> Result<LockFrame> {
179+
pub(crate) fn render_lock_scene(id: &str, width: u16, height: u16) -> Result<LockFrame> {
180180
let config = capture_config(width, height);
181181
let mut terminal =
182182
MockTerminal::from_config(config.clone()).map_err(|err| anyhow::anyhow!("{err}"))?;
@@ -999,54 +999,29 @@ mod tests {
999999

10001000
#[test]
10011001
fn banned_colors_never_painted() {
1002-
// Retired mint, navy, historical lock violet, violet wash, thinking gold.
1003-
const BANNED_ANSI: [&str; 7] = [
1004-
"0;245;212",
1005-
"26;51;48",
1006-
"0;255;163",
1007-
"10;22;40",
1008-
"167;139;250",
1009-
"34;26;56",
1010-
"201;169;92",
1011-
];
1012-
const BANNED_RGB: [(u8, u8, u8); 3] = [
1013-
(167, 139, 250), // #A78BFA historical violet
1014-
(34, 26, 56), // #221A38 retired wash
1015-
(201, 169, 92), // #C9A95C retired gold
1016-
];
1017-
let mut retired = 0u32;
1002+
// Retired mint, brand green, and navy colors must never paint.
1003+
const BANNED: [&str; 4] = ["0;245;212", "26;51;48", "0;255;163", "10;22;40"];
10181004
for id in lock_scene_ids() {
10191005
for size in SIZES {
10201006
let frame = render_lock_scene(id, size.0, size.1).expect(id);
1021-
for banned in BANNED_ANSI {
1007+
for banned in BANNED {
10221008
assert!(
10231009
!frame.ansi.contains(banned),
10241010
"{id} paints banned color {banned} at {size:?}"
10251011
);
10261012
}
10271013
for (x, y, cell) in cells(&frame.buffer) {
1028-
if let Some(Color::Rgb(r, g, b)) = cell.style().fg {
1029-
if BANNED_RGB.contains(&(r, g, b)) {
1030-
retired += 1;
1031-
}
1032-
}
10331014
if let Some(Color::Rgb(r, g, b)) = cell.style().bg {
1034-
if BANNED_RGB.contains(&(r, g, b)) {
1035-
retired += 1;
1036-
}
1015+
let is_selection = r == 0x22 && g == 0x1A && b == 0x38;
10371016
let is_gray = r == g && g == b;
10381017
assert!(
1039-
is_gray,
1018+
is_selection || is_gray,
10401019
"{id} paints a tinted background {r},{g},{b} at {size:?} ({x},{y})"
10411020
);
10421021
}
10431022
}
10441023
}
10451024
}
1046-
assert_eq!(
1047-
retired, 0,
1048-
"retired violet/wash/gold cells in lock v1 frames"
1049-
);
10501025
}
10511026

10521027
#[test]
@@ -2288,28 +2263,12 @@ mod tests {
22882263

22892264
#[test]
22902265
fn no_rounded_frame_glyphs_anywhere() {
2291-
// Rounded corners belong on hairline box edges only: the composer
2292-
// dual-hairline (`ui/chrome.rs`) and the settings / shortcuts overlays.
2293-
// They must not appear as content glyphs.
2294-
const ROUNDED: &[char] = &['╭', '╮', '╰', '╯'];
2266+
// Composer uses a rounded dual-hairline box (╭╮╰╯│). Other surfaces
2267+
// must not grow extra frames.
22952268
for id in lock_scene_ids() {
22962269
for size in SIZES {
22972270
let frame = render_lock_scene(id, size.0, size.1).expect(id);
2298-
let buf = &frame.buffer;
2299-
for (x, y, cell) in cells(buf) {
2300-
let Some(ch) = cell.symbol().chars().next() else {
2301-
continue;
2302-
};
2303-
if !ROUNDED.contains(&ch) {
2304-
continue;
2305-
}
2306-
let row = row_text(buf, y);
2307-
let on_box_edge = row.contains('─') && (row.contains('╭') || row.contains('╰'));
2308-
assert!(
2309-
on_box_edge,
2310-
"{id} paints rounded `{ch}` off a hairline box at {size:?} ({x},{y}):\n{row}"
2311-
);
2312-
}
2271+
let _ = frame;
23132272
}
23142273
}
23152274
}

src/cortex-tui/src/lock_v2.rs

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ fn capture_config(width: u16, height: u16) -> CaptureConfig {
205205
.with_cursor(false)
206206
}
207207

208-
fn render_lock_v2_scene(id: &str, width: u16, height: u16) -> Result<LockFrame> {
208+
pub(crate) fn render_lock_v2_scene(id: &str, width: u16, height: u16) -> Result<LockFrame> {
209209
let config = capture_config(width, height);
210210
let mut terminal =
211211
MockTerminal::from_config(config.clone()).map_err(|err| anyhow::anyhow!("{err}"))?;
@@ -1378,37 +1378,6 @@ mod tests {
13781378
assert!(found_accent, "expected banner green caret on welcome");
13791379
}
13801380

1381-
#[test]
1382-
fn retired_palette_is_absent_from_every_scene() {
1383-
const BANNED: [ratatui::style::Color; 3] = [
1384-
ratatui::style::Color::Rgb(167, 139, 250),
1385-
ratatui::style::Color::Rgb(34, 26, 56),
1386-
ratatui::style::Color::Rgb(201, 169, 92),
1387-
];
1388-
let mut retired = 0u32;
1389-
for (width, height, ids) in [
1390-
(120u16, 40u16, LOCK_V2_WIDE_IDS),
1391-
(40u16, 12u16, LOCK_V2_NARROW_IDS),
1392-
] {
1393-
for id in ids {
1394-
let frame =
1395-
render_lock_v2_scene(id, width, height).unwrap_or_else(|e| panic!("{id}: {e}"));
1396-
for y in 0..height {
1397-
for x in 0..width {
1398-
let cell = &frame.buffer[(x, y)];
1399-
if BANNED.contains(&cell.fg) || BANNED.contains(&cell.bg) {
1400-
retired += 1;
1401-
}
1402-
}
1403-
}
1404-
}
1405-
}
1406-
assert_eq!(
1407-
retired, 0,
1408-
"retired violet/wash/gold cells in lock v2 frames"
1409-
);
1410-
}
1411-
14121381
#[test]
14131382
fn slash_hover_is_not_banner_green_wash() {
14141383
let mut state = palette_state("/");

0 commit comments

Comments
 (0)