test(app-iced): M79 r2 —— probe 复跑暴露的两处修正(分隔线判据 / 可见性警告)
真跑 `navigation::probe` 才发现的两件事,都只影响测试代码: 1. **Secondary 分隔线判据错了**:原来按 `SurfaceVariant` 的**精确值**找块, 但 1px 的线画在分数像素上,真实像素是「线色 ⊗ 页面底色」的混合值 (实测 `(221,233,245)`,不是令牌原值)→ 找到 **0 段**,断言假红。 改成:先找「与页面底色不同、横跨 >150px 的那一行」,再用**该行自己的颜色**数连通段 (`probe/scan.rs` 新增 `longest_h_line` / `line_segments` / `differs`)。 现在:r1 基线图 → 实测 **2 段**(红);r2 新图 → **1 段**(绿)。 2. `matches` 原来被写成 `differs` 的正向委托(语义反了),以及 `pub(super) fn shot` 暴露了 更私有的 `Shot`(`private_interfaces` 警告,`-D warnings` 会红):前者改回 `!differs(..)`,后者把 `shot`/`shot_dir` 收回私有(子模块 `probe::long` 仍可见)。 其他:`probe/long.rs` 的 `filter(..).next()` → `find(..)`(clippy::filter_next)。 复跑(真实输出): - `ULL_NAV_DIR=target/m79/r2 cargo test -p unlucky-app-iced navigation::probe` → **5 passed** - `cargo test -p unlucky-app-iced` → **197 passed**(+ gate 6 passed,1 ignored) - `cargo clippy -p unlucky-app-iced --all-targets -- -D warnings` → 干净
This commit is contained in:
1 parent
a36f542f28
commit
55a775fca7
3 files changed
+65
-15
No files matched your search
@@ -40,7 +40,7 @@ mod scan;
|
||||
use scan::{rgb, ui, BBox, Rgb, Shot};
|
||||
|
||||
/// `ULL_NAV_DIR` → 截图目录(相对路径按**工作区根**解释:`cargo test` 的 cwd 是 crate 目录)。
|
||||
pub(super) fn shot_dir() -> Option<PathBuf> {
|
||||
fn shot_dir() -> Option<PathBuf> {
|
||||
let raw = std::env::var_os("ULL_NAV_DIR")?;
|
||||
let path = PathBuf::from(raw);
|
||||
if path.is_absolute() || path.exists() {
|
||||
@@ -65,7 +65,7 @@ macro_rules! require_dir {
|
||||
};
|
||||
}
|
||||
|
||||
pub(super) fn shot(dir: &Path, part: &str, flavor: SchemeFlavor) -> Shot {
|
||||
fn shot(dir: &Path, part: &str, flavor: SchemeFlavor) -> Shot {
|
||||
let slug = match flavor {
|
||||
SchemeFlavor::Light => "light",
|
||||
SchemeFlavor::Dark => "dark",
|
||||
@@ -199,13 +199,16 @@ fn tabs_indicator_tracks_the_selected_tab() {
|
||||
measured.push((bar.width(), ink));
|
||||
}
|
||||
// 6.6:Secondary 的分隔线必须是**一条连续直线**(逐 tab 分段画会在相邻段之间留 1px 亮缝,
|
||||
// 视觉 r1 P2-2 实测 `25..101 | 103..191 | 193..265`)
|
||||
let divider = rgb(ui.color(Role::SurfaceVariant));
|
||||
let segments = shot
|
||||
.blocks(divider)
|
||||
.into_iter()
|
||||
.filter(|b| b.height() <= 2 && b.width() >= 20)
|
||||
.count();
|
||||
// 视觉 r1 P2-2 实测 `25..101 | 103..191 | 193..265`)。
|
||||
//
|
||||
// 判法:1px 的线画在分数像素上 → 真实像素是「线色 ⊗ 页面底色」的**混合值**(实测
|
||||
// `(221,233,245)`,不是 `SurfaceVariant` 的原值),所以不能按精确色找块。改成:
|
||||
// 先找「与页面底色不同、横跨 >150px 的那一行」,再用**该行自己的颜色**数连通段。
|
||||
let surface = rgb(ui.color(Role::Surface));
|
||||
let divider = shot
|
||||
.longest_h_line(surface, 150)
|
||||
.expect("Secondary 那一行应有一条长横线");
|
||||
let segments = shot.line_segments(divider.0, divider.1, divider.2);
|
||||
assert_eq!(
|
||||
segments, 1,
|
||||
"Secondary 分隔线应是一条直线,实测 {segments} 段(分段画会留缝)"
|
||||
|
||||
@@ -55,8 +55,7 @@ fn long_text_stays_single_line() {
|
||||
let bar = shot
|
||||
.blocks(rgb(ui.color(Role::Surface)))
|
||||
.into_iter()
|
||||
.filter(|b| b.width() > 300 && (54..=58).contains(&b.height()))
|
||||
.next()
|
||||
.find(|b| b.width() > 300 && (54..=58).contains(&b.height()))
|
||||
.expect("长文案块应有一条 56 高的页头");
|
||||
assert!(
|
||||
(55..=57).contains(&bar.height()),
|
||||
|
||||
@@ -40,10 +40,13 @@ pub(super) fn rgb(color: iced::Color) -> Rgb {
|
||||
}
|
||||
|
||||
pub(super) fn matches(pixel: Rgb, expected: Rgb) -> bool {
|
||||
pixel
|
||||
.iter()
|
||||
.zip(expected)
|
||||
.all(|(a, b)| a.abs_diff(b) <= TOLERANCE)
|
||||
// **每个通道**都在容差内;`differs` 是它的否定(任一通道超差即「不同」)
|
||||
!differs(pixel, expected, TOLERANCE)
|
||||
}
|
||||
|
||||
/// 两个颜色在**每个通道**上都不超过 `tol`。
|
||||
pub(super) fn differs(pixel: Rgb, expected: Rgb, tol: u8) -> bool {
|
||||
pixel.iter().zip(expected).any(|(a, b)| a.abs_diff(b) > tol)
|
||||
}
|
||||
|
||||
/// 一个外接框(闭区间)。
|
||||
@@ -178,6 +181,51 @@ impl Shot {
|
||||
span
|
||||
}
|
||||
|
||||
/// 全图里**第一行**横跨 ≥ `min_len` 的「与底色不同」的连续像素:返回 `(y, x0, x1)`。
|
||||
///
|
||||
/// 用于找 1px 的分隔线:它的颜色是混合值,不能按精确色找。
|
||||
pub(super) fn longest_h_line(
|
||||
&self,
|
||||
background: Rgb,
|
||||
min_len: usize,
|
||||
) -> Option<(usize, usize, usize)> {
|
||||
for y in 0..self.height {
|
||||
let mut run = 0;
|
||||
let mut start = 0;
|
||||
for x in 0..self.width {
|
||||
if differs(self.at(x, y), background, 6) {
|
||||
if run == 0 {
|
||||
start = x;
|
||||
}
|
||||
run += 1;
|
||||
if run >= min_len {
|
||||
return Some((y, start, x));
|
||||
}
|
||||
} else {
|
||||
run = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// `y` 行 `[x0, x1]` 上「按该行中点的颜色」数的连通段数(分隔线断没断)。
|
||||
pub(super) fn line_segments(&self, y: usize, x0: usize, x1: usize) -> usize {
|
||||
let line = self.at((x0 + x1) / 2, y);
|
||||
let mut segments = 0;
|
||||
let mut in_run = false;
|
||||
for x in x0..=x1 {
|
||||
let on = matches(self.at(x, y), line);
|
||||
if on && !in_run {
|
||||
segments += 1;
|
||||
in_run = true;
|
||||
} else if !on {
|
||||
in_run = false;
|
||||
}
|
||||
}
|
||||
segments
|
||||
}
|
||||
|
||||
/// 矩形内「与底色不同」的像素的左右范围(量文本墨迹用)。
|
||||
///
|
||||
/// 为什么不按精确文字色找:小字号抗锯齿后几乎没有像素落在**精确**色上(容差 3 时实测
|
||||
|
||||
Reference in new issue
Block a user