Files
Unlucky-Launcher/crates/app-iced/src/pages/appearance/section/tests.rs
T
AskaEth 0d917e88da feat(settings): M299 选中项收口到 selected_fill + 分组导航改真按钮 + tabs 用 status
- pages/settings/frame.rs:分组导航从 mouse_area 换成 button(四态可辨),
  几何不变(ShapeScale::Full 胶囊),颜色走唯一的 selected_fill;forced 从
  settings::view 递下来,于是 --force-state 能拍到这一处
- language / theme / appearance choice 三处「选中档位」补状态层
- components/selection/paint/chip.rs:选中分支用上 state 参数
- shell/nav.rs / shell/nav/account.rs:两处私有拷贝收口到 selected_fill(几何没动)
- components/navigation/tabs.rs:状态层在样式闭包里跟 button::Status 求值
- 新增门禁 selection/tests/single_entry.rs:11 个站点必须调 selected_fill +
  产品代码里不许再出现 or_else(|| Some(ui.color( 这个私有拷贝形态
- 行数:frame.rs / nav.rs / appearance::section 的单测按「纯搬移」拆出去
2026-11-13 14:41:57 +08:00

119 lines
4.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! `appearance::section` 的单测(M299 从 `mod.rs` 纯搬移,守 400 行硬线)。
//!
//! 判据与注释一字未动,只是**换文件**:`mod.rs` 加了一条「选中的档位跟态走」之后到 438 行。
//! 模块路径仍是 `appearance::section::tests`(`mod.rs` 里改成 `mod tests;`),`super::*` 拿到的
//! 还是 `appearance::section`。
use super::*;
use unlucky_design::color::{SchemeFlavor, StateLayer};
use unlucky_design::typography::Platform;
use crate::theme::Families;
fn ui() -> Ui {
Ui::with_platform(
SchemeFlavor::Light,
Platform::Windows,
Families {
text: "Segoe UI",
display: "Segoe UI",
mono: "Consolas",
},
)
}
fn solid(style: button::Style) -> Color {
match style.background {
Some(Background::Color(color)) => color,
None => panic!("未选中态的 hover/pressed 必须叠状态层"),
Some(other) => panic!("背景必须是实色,得到 {other:?}"),
}
}
/// hover(8%) 与 pressed(10%) 是**两档**,且各自逐值等于令牌表(把 10% 改成 11% 也会红)。
///
/// 抓得住:①回到 `matches!(status, Hovered | Pressed)` 合并分支(两色相等 ⇒ 第一条红);
/// ②pressed 用 hover 的 α、或合成底被换回画布(第二、三条红)。
/// 抓不住:观感;**过渡中间帧**(forced 路径不套 `tracked`,`layer_color` 直落端点值)。
///
/// 底的角色取 `MaterialLayer::Card.surface_role()`(`frame::BASE` 就是它):既盯住「叠的是卡底」
/// 这条语义,也不往 `settings/*.rs` 的接线点计数里多塞一次字面量(`pages/tests/base_wiring.rs`)。
#[test]
fn the_choice_button_draws_pressed_darker_than_hover() {
let ui = ui();
let style = choice_style(
&ui,
false,
ui.color(Role::OnSurfaceVariant),
ui.radius(ShapeScale::Full, ui.metrics().control_height),
None,
);
let theme = ui.theme();
let hover = solid(style(&theme, button::Status::Hovered));
let pressed = solid(style(&theme, button::Status::Pressed));
assert_ne!(hover, pressed, "hover 与 pressed 必须是两档(8% / 10%)");
let base = MaterialLayer::Card.surface_role();
assert_eq!(
hover,
ui.state_over(StateLayer::Hover, Role::OnSurface, base)
);
assert_eq!(
pressed,
ui.state_over(StateLayer::Pressed, Role::OnSurface, base)
);
assert!(
style(&theme, button::Status::Active).background.is_none(),
"静息态不叠状态层"
);
}
/// **选中的档位也跟态走**(M299):底是实色 `SecondaryContainer`,状态层叠在它上面。
///
/// 抓得住:①把选中支改回 `Some(ui.color(SecondaryContainer))`(= 选中就不响应)⇒ hover /
/// pressed 都等于静息,前三条红;②hover 与 pressed 同 α ⇒ 第四条红;③合成底被换掉 ⇒ 后两条
/// 逐值断言红。
/// 抓不住:像素(`DevDocs/artifacts/m299/settings-appearance-*-hover|pressed.png`,`--force-state`
/// 经 `settings::view` → `appearance::section` 的 `forced`);也抓不住「自己抄了一份**正确**的
/// 叠层」——由 `selection/tests/single_entry.rs` 的接线扫描负责。
#[test]
fn a_selected_choice_reacts_to_hover_and_press() {
let ui = ui();
let style = choice_style(
&ui,
true,
ui.color(Role::OnSecondaryContainer),
ui.radius(ShapeScale::Full, ui.metrics().control_height),
None,
);
let theme = ui.theme();
let rest = solid(style(&theme, button::Status::Active));
let hover = solid(style(&theme, button::Status::Hovered));
let pressed = solid(style(&theme, button::Status::Pressed));
assert_eq!(
rest,
ui.color(Role::SecondaryContainer),
"选中静息 = 实色容器"
);
assert_ne!(hover, rest, "选中 + hover 必须与静息不同");
assert_ne!(pressed, rest, "选中 + pressed 必须与静息不同");
assert_ne!(hover, pressed, "8% 与 10% 必须能区分");
assert_eq!(
hover,
ui.state_over(
StateLayer::Hover,
Role::OnSecondaryContainer,
Role::SecondaryContainer
)
);
assert_eq!(
pressed,
ui.state_over(
StateLayer::Pressed,
Role::OnSecondaryContainer,
Role::SecondaryContainer
)
);
}