docs(app-iced): 值字级注释改真 + probe 只认 buttons/divider + 截图主题钉死回归测试(M229 复审 r2)

1) P1-2 的注释值与量测对齐(四处):`elevated.rs` 的 `PAD`/`Texts::title`/`texts()` 与
   `pages/instances/detail.rs` 还写着「值 14/400」,而实现是 12/400;`PAD` 文档更把 12px 的
   118px 量测挂在「14px 下」。全部改成真值,并把 14px=138px 与 12px=118px 两个量测并列写清。

2) probe 门禁只解决一半:`SECTION=buttons` 绿、`SECTION=all` 仍红(sizes 段的实心块撞「按钮
   40 高」判据),断言文案却写「all 或 buttons」。现在:
   - 只支持 `buttons`(按钮矩阵,实心块判据**只量矩阵区**,后续段不再参与)与 `divider`
     (分隔线两条判据,独立出口);
   - `all` / 其它 / 未给 → 明确失败并给理由(整页比 1180×760 高,分隔线段与按钮矩阵不可能同屏;
     整页图的 chip/卡片会被当按钮量);
   - 模块文档的复现命令补上 `ULL_GALLERY_SECTION`(以前照着跑会 panic);
   - `gallery/mod.rs` 的「五段」→ 七段;`gallery/buttons.rs` 的「8 行 + icon·standard」→ 9 行 + 四式。

3) 截图通道的主题档钉死此前没有回归测试(复审 r2 P2-a)。新增
   `the_screenshot_channel_pins_the_theme_mode_instead_of_reading_the_file`:两份不同的机器配置 +
   同一组截图参数 ⇒ 同一个档位且等于参数;反证非截图通道下两份配置确实分出两档。
   变异自证:把分支改回 `bridge.load().1` → 该测试红(left: Dark, right: Light)。

门禁:fmt --check 0 / check -p unlucky-app-iced --all-targets 0 / test -p unlucky-app-iced 0
(887 passed + 6 integration)/ clippy -p unlucky-app-iced --all-targets -D warnings 0 / 400 行扫描干净。
probe 亲跑:buttons 浅+深两张 sheet OK,divider 一张 OK,`all` 按预期被拒。
This commit is contained in:
AskaEth committed 2026-11-11 01:49:16 +08:00
1 parent 8958b7f67d
commit f5a2610e4d
7 files changed
+205 -69

No files matched your search

+101
View File
@@ -84,3 +84,104 @@ fn the_theme_message_switches_the_board_and_persists_it() {
assert_eq!(app.refreshes, refreshes, "同一档不该再重建视图模型");
std::fs::remove_dir_all(&dir).ok();
}
/// **截图通道把主题档钉死在 `--screenshot-theme`**,不读机器上的 `launcher.json`(D30 可复现)。
///
/// 复审 r2 P2-a 指出:`construct.rs` 里新加的这条分支没有回归测试——于是「哪天有人把它改回
/// `bridge.load().1`」不会有人发现,两次不同配置的机器又会出不同颜色的图。
///
/// 判据:**同一份截图参数 + 两份不同的机器配置 ⇒ 同一个档位**,且等于参数(浅→`Light`、深→`Dark`);
/// 反证:非截图通道下同样两份配置**确实**分出两个档(否则这条测试等于没测到分支)。
#[test]
fn the_screenshot_channel_pins_the_theme_mode_instead_of_reading_the_file() {
use std::path::{Path, PathBuf};
/// 写一份只含 `appearance.theme_mode` 的临时配置,并用它构造 App。
fn with_mode(
dir_name: &str,
json: &str,
options: Options,
flavor: SchemeFlavor,
) -> (App, PathBuf) {
let dir =
std::env::temp_dir().join(format!("ull-shot-theme-{dir_name}-{}", std::process::id()));
std::fs::create_dir_all(dir.join("config")).expect("临时目录");
let path = dir.join("config/launcher.json");
std::fs::write(&path, json).expect("写配置文件");
let app = App::with_presenter(
options,
FAMILIES,
flavor,
Box::new(MockBackend::new()),
SettingsBridge::with_path(&path),
);
(app, dir)
}
fn cleanup(dir: &Path) {
std::fs::remove_dir_all(dir).ok();
}
let dark_file = r#"{"appearance":{"theme_mode":"dark"}}"#;
let light_file = r#"{"appearance":{"theme_mode":"light"}}"#;
// ① 截图参数给浅色:机器配置是 dark 也一样出 Light(钉死值赢)
let shot_light = Options {
screenshot: Some(PathBuf::from("unused.png")),
screenshot_theme: Some(SchemeFlavor::Light),
..Options::default()
};
let (from_dark_file, d1) = with_mode(
"light-a",
dark_file,
shot_light.clone(),
SchemeFlavor::Light,
);
let (from_light_file, d2) = with_mode("light-b", light_file, shot_light, SchemeFlavor::Light);
assert_eq!(
from_dark_file.theme_mode(),
ThemeMode::Light,
"截图模式下档位必须由 --screenshot-theme 决定,不许读文件里的 dark"
);
assert_eq!(
from_dark_file.theme_mode(),
from_light_file.theme_mode(),
"两份机器配置必须出同一个档位"
);
assert_eq!(from_dark_file.board_name(), "silver");
assert_eq!(from_light_file.board_name(), "silver");
// ② 反方向:截图参数给深色 ⇒ 即使文件写 light 也是 Dark/Ink
let shot_dark = Options {
screenshot: Some(PathBuf::from("unused.png")),
screenshot_theme: Some(SchemeFlavor::Dark),
..Options::default()
};
let (from_light_file_dark, d3) = with_mode("dark-a", light_file, shot_dark, SchemeFlavor::Dark);
assert_eq!(from_light_file_dark.theme_mode(), ThemeMode::Dark);
assert_eq!(from_light_file_dark.board_name(), "ink");
// ③ 反证:非截图通道下,同样的两份配置**确实**分出两个档(证明这条分支真的存在)
let (interactive_dark, d4) =
with_mode("plain-a", dark_file, Options::default(), SchemeFlavor::Dark);
let (interactive_light, d5) = with_mode(
"plain-b",
light_file,
Options::default(),
SchemeFlavor::Light,
);
assert_eq!(
interactive_dark.theme_mode(),
ThemeMode::Dark,
"产品路径要读文件"
);
assert_eq!(
interactive_light.theme_mode(),
ThemeMode::Light,
"产品路径要读文件"
);
for dir in [d1, d2, d3, d4, d5] {
cleanup(&dir);
}
}