feat(app-iced): Java 页「下载一个 JDK」+ 三个设置键(M197)
用户原话:「我们内置了那么多镜像源 甚至用户不能手动选择指定版本下载。」
「自动下载 jdk17 作为基准版本,后续在设置中提供多版本可供用户下载。」
- core:新增 `game::java::catalog`(8/11/17/21/25 五档 × 能承接的发行版 × 「该装哪档」),
数据全部来自 `JdkVendor::supports` 与 `vendor::order`,不复制第二份真相。
- progress:`SourceFailed` 补一个结构化的 `kind`(在这之前只有中文 `reason`,双语界面
要么放弃语言、要么放弃「哪个源为什么退避」这条用户可见信息)。
- app-iced:`downloads` 模块真下(后台线程 + `ProgressEmitter` + 快照),三态(选择列表 /
下载中 / 失败)都能说出「命中的源 / 退避原因 / 试过哪些源」;成功后重扫并(在
`java.auto_install` 开着且没有默认 JDK 时)把新装的那份设为默认。
- 三个设置键做成可改 UI:`java.installRoot` / `java.vendorPriority` / `java.auto_install`,
各自带「现在生效什么、从哪一层来」(数据目录模式 / 地区默认序),改完回读落盘值。
- `State::satisfied` 换成带方向的 `Fit`:1.12.2 + Java 21 不再被说成「低于要求」。
- i18n:删掉 `SettingsJavaEmptyBody` / `SettingsJavaAddHint` 的 markdown 反引号;
`SettingsJavaNeverScannedBody` 改成不与首屏自动扫矛盾的表述。
- 出图三张(选择列表 / 下载中 / 失败)在 DevDocs/artifacts/m197/。
顺带拆文件守 400 行:`golden/tail.rs` 的 M174 段搬到 `golden/tail_ai.rs`,
`pages/settings/java/{context,prefs,prefs_store,downloads,download_view}` 各自成模块。
This commit is contained in:
1 parent
329c529bea
commit
ce463cc9b5
33 files changed
+3839
-322
No files matched your search
@@ -25,6 +25,10 @@ use super::super::*;
|
||||
|
||||
use crate::pages::settings::java::{Context, Layer, Notice, Requirement};
|
||||
|
||||
/// M197 的两个落点(各自一个 `impl App` 块):真下载一个 JDK / 三个设置键。
|
||||
mod downloads;
|
||||
mod prefs;
|
||||
|
||||
impl App {
|
||||
/// Java 分组的一条消息。
|
||||
pub(super) fn on_settings_java(
|
||||
@@ -55,6 +59,13 @@ impl App {
|
||||
self.touch_java();
|
||||
}
|
||||
Message::Save => self.save_java_settings(),
|
||||
// M197:真下载一个 JDK + 三个设置键。落点各自一个 `impl App` 块(见 `mod` 声明)。
|
||||
Message::Download(major) => return downloads::on_download(self, major),
|
||||
Message::EditInstallRoot(value) => return prefs::on_edit_install_root(self, value),
|
||||
Message::ToggleAutoInstall(on) => return prefs::on_toggle_auto_install(self, on),
|
||||
Message::MoveVendor { index, up } => return prefs::on_move_vendor(self, index, up),
|
||||
Message::ResetPriority => return prefs::on_reset_priority(self),
|
||||
Message::SavePrefs => return prefs::on_save_prefs(self),
|
||||
}
|
||||
|
||||
Task::none()
|
||||
@@ -99,9 +110,17 @@ impl App {
|
||||
let snapshot = pages::settings::java::store::load(&config);
|
||||
self.settings.java.manual = pages::settings::java::store::load_manual(&config);
|
||||
let changed = self.settings.java.hydrate(snapshot);
|
||||
// M197:三个设置键(安装目录 / 发行版顺序 / 缺 JDK 时自动准备)+ 它们的生效值与来源层。
|
||||
let prefs_changed = self
|
||||
.settings
|
||||
.java
|
||||
.prefs
|
||||
.hydrate(pages::settings::java::prefs_store::load(&config));
|
||||
self.settings.java.effective =
|
||||
pages::settings::java::prefs_store::effective(&config, &self.settings.java.prefs);
|
||||
let scan_changed = self.hydrate_java_scan();
|
||||
self.settings.java.context = self.java_context();
|
||||
if changed || scan_changed {
|
||||
if changed || prefs_changed || scan_changed {
|
||||
self.view_dirty = true;
|
||||
}
|
||||
// 自动扫一次(首屏就该有真数据)。`cfg!(test)` 只关掉**这条生产入口的自动发起**
|
||||
@@ -126,9 +145,16 @@ impl App {
|
||||
}
|
||||
|
||||
/// 把后台扫描的快照灌进状态。返回是否变了。
|
||||
///
|
||||
/// M197 起这一拍**也**灌一次下载作业的快照:`app/update/clock.rs` 每拍只调这一个入口,
|
||||
/// 而复用它比改心跳的调用点便宜(`clock.rs` 不在本 mission 的 scope 里)。
|
||||
/// 代价写在 `settings/java/downloads.rs`:下载期间进度按 1 Hz 刷新。
|
||||
pub(in crate::app) fn hydrate_java_scan(&mut self) -> bool {
|
||||
let report = self.settings.java.scan.report();
|
||||
let changed = self.settings.java.apply_scan(&report);
|
||||
let mut changed = self.settings.java.apply_scan(&report);
|
||||
if self.hydrate_java_downloads() {
|
||||
changed = true;
|
||||
}
|
||||
if changed {
|
||||
self.view_dirty = true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
//! 「下载一个 JDK」的 App 层落点(M197)。
|
||||
//!
|
||||
//! 三件事:
|
||||
//!
|
||||
//! | 函数 | 谁调 | 干什么 |
|
||||
//! |---|---|---|
|
||||
//! | [`App::start_java_download`] | `Download(major)` 消息 | 本地判据(目录/承接方/落点/是否已在跑)→ 起后台作业 |
|
||||
//! | [`App::hydrate_java_downloads`] | 心跳那一拍(经 `hydrate_java_scan`) | 把作业快照灌成视图差量;**刚成功**时重扫 + 按 `java.auto_install` 决定要不要设为默认 |
|
||||
//!
|
||||
//! ## 为什么轮询挂在 `hydrate_java_scan` 上
|
||||
//!
|
||||
//! M175 的扫描已经是「后台线程 + 快照 + 心跳比对」的形状,`app/update/clock.rs` 每拍只调
|
||||
//! `hydrate_java_scan()` 这一个入口。下载作业是同一族东西(后台线程 + 快照),所以复用那一拍,
|
||||
//! `clock.rs` 一个字节都不用改——代价是**下载期间进度按 1 Hz 刷新**(帧时钟的判据在
|
||||
//! `app/subscription.rs` 的 `needs_frames`,那是本 mission scope 之外的文件)。百分比一秒动一次
|
||||
//! 对一次 100 MB 级的下载是够的;要紧的是它**会动**,而不是每秒动 60 次。
|
||||
//!
|
||||
//! ## 装完之后为什么要重扫
|
||||
//!
|
||||
//! 列表里那一行「已安装:…」来自**真扫盘的结论**(M175 的 `ScanSlot`),不是另存的安装记录。
|
||||
//! 装完不重扫,界面上就会出现「下载成功」与「列表里没有它」并存——正是本仓最忌讳的那种自相矛盾。
|
||||
|
||||
use iced::Task;
|
||||
|
||||
use crate::app::message::Message;
|
||||
use crate::app::state::App;
|
||||
use crate::pages;
|
||||
|
||||
use unlucky_core::game::java::catalog;
|
||||
|
||||
use crate::pages::settings::java::{prefs_store, store};
|
||||
|
||||
impl App {
|
||||
/// 下载并安装某个大版本(`Download(major)` 的落点)。
|
||||
///
|
||||
/// 四道本地判据,任何一道不过都在下载区顶上写清原因(点了没反应是禁止的):
|
||||
/// ① 目录里有这个大版本;② 没有别的作业在跑;③ 有可写的设置文件与能解析的落点;
|
||||
/// ④ 这一档在这台机器上真有一家发行版承接(纯判据,不联网)。
|
||||
pub(super) fn start_java_download(&mut self, major: u32) {
|
||||
use pages::settings::java::downloads::{Refusal, Request};
|
||||
|
||||
self.settings.java.download_notice = None;
|
||||
self.settings.java.notice = None;
|
||||
self.view_dirty = true;
|
||||
|
||||
if catalog::find(major).is_none() {
|
||||
self.settings.java.download_notice = Some(Refusal::UnknownMajor);
|
||||
return;
|
||||
}
|
||||
if self.settings.java.downloads.busy() {
|
||||
self.settings.java.download_notice = Some(Refusal::Busy);
|
||||
return;
|
||||
}
|
||||
let Some(config) = store::config_of(&self.bridge) else {
|
||||
self.settings.java.download_notice = Some(Refusal::NoStorage);
|
||||
return;
|
||||
};
|
||||
let priority = self.settings.java.priority_vendors();
|
||||
let domestic = self.settings.java.effective.domestic;
|
||||
if catalog::vendors_for(major, &priority, domestic).is_empty() {
|
||||
self.settings.java.download_notice = Some(Refusal::NoVendor);
|
||||
return;
|
||||
}
|
||||
let saved_root = self.settings.java.prefs.saved_install_root.clone();
|
||||
let Some(cache_root) = prefs_store::cache_root(&config) else {
|
||||
self.settings.java.download_notice = Some(Refusal::NoStorage);
|
||||
return;
|
||||
};
|
||||
let Some(install_root) = prefs_store::install_root(&config, &saved_root) else {
|
||||
// 有设置文件但解析不出落点(standard 模式读不到系统目录):说这一句,
|
||||
// 而不是含糊的「没有可用的设置文件」。
|
||||
self.settings.java.download_notice = Some(Refusal::RootUnresolved);
|
||||
return;
|
||||
};
|
||||
let started = self.settings.java.downloads.start(Request {
|
||||
major,
|
||||
cache_root,
|
||||
install_root,
|
||||
priority,
|
||||
});
|
||||
if !started {
|
||||
self.settings.java.download_notice = Some(Refusal::Busy);
|
||||
}
|
||||
}
|
||||
|
||||
/// 把作业快照灌成视图差量(心跳那一拍调)。返回是否变了。
|
||||
pub(in crate::app) fn hydrate_java_downloads(&mut self) -> bool {
|
||||
let report = self.settings.java.downloads.report();
|
||||
if report == self.settings.java.download_seen {
|
||||
return false;
|
||||
}
|
||||
let fresh = report
|
||||
.success
|
||||
.clone()
|
||||
.filter(|success| self.settings.java.download_seen.success.as_ref() != Some(success));
|
||||
self.settings.java.download_seen = report;
|
||||
if let Some(success) = fresh {
|
||||
// 新装上的一份:先重扫(列表要出现它),再按 `java.auto_install` 决定默认值。
|
||||
let _ = self.start_java_scan();
|
||||
if self.settings.java.prefs.saved_auto_install
|
||||
&& self.settings.java.selected.trim().is_empty()
|
||||
{
|
||||
self.select_java_default(&success.binary);
|
||||
}
|
||||
}
|
||||
self.view_dirty = true;
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// 消息→落点的那一层(`java.rs` 的 match 里一行转发)。
|
||||
pub(super) fn on_download(app: &mut App, major: u32) -> Task<Message> {
|
||||
app.start_java_download(major);
|
||||
Task::none()
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
//! 三个设置键的 App 层落点(M197):`java.installRoot` / `java.vendorPriority` / `java.auto_install`。
|
||||
//!
|
||||
//! ## 为什么这三项单独一个「保存」
|
||||
//!
|
||||
//! M175 的「保存」只写内存 + JVM 参数(`java.default_memory_mb` / `java.extra_args`),那是**运行时
|
||||
//! 参数**;这三项是**装到哪、按什么顺序找、缺 JDK 时怎么准备**——改了它们的副作用是「下一次下载 /
|
||||
//! 下一次扫描的落点变了」,与内存那两项混在一个按钮里,用户就不清楚自己刚保存的到底是哪一半。
|
||||
//! 于是两段各有自己的脏标记与保存按钮,各回读各的键。
|
||||
//!
|
||||
//! ## 保存之后为什么立刻重扫
|
||||
//!
|
||||
//! `java.installRoot` 改了 ⇒ 托管根的集合变了 ⇒ 「已检测到的 JDK」那份列表可能整份不同。
|
||||
//! 保存成功就重扫一次,界面不会出现「落点写着新目录,列表还是旧目录里的 JDK」。
|
||||
//!
|
||||
//! ## 回读校验
|
||||
//!
|
||||
//! `prefs_store::save` 返回的是**落盘后从磁盘读回来**的真值,[`Prefs::adopt`] 把草稿与
|
||||
//! 「落盘真值」两半都对齐到它:用户看到的就是磁盘上那份(要是 schema 把值规整过,界面显示的是
|
||||
//! 规整后的结果,而不是他刚敲的那串——这一条正是「改完回读验证已落盘」)。
|
||||
|
||||
use iced::Task;
|
||||
|
||||
use crate::app::message::Message;
|
||||
use crate::app::state::App;
|
||||
use crate::pages;
|
||||
|
||||
use super::super::java::write_notice;
|
||||
|
||||
impl App {
|
||||
/// `java.installRoot` 草稿(只改草稿,不写盘)。
|
||||
pub(super) fn edit_java_install_root(&mut self, value: String) {
|
||||
self.settings.java.prefs.install_root = value;
|
||||
self.settings.java.notice = None;
|
||||
self.settings.java.download_notice = None;
|
||||
self.view_dirty = true;
|
||||
}
|
||||
|
||||
/// `java.auto_install` 开关(只改草稿)。
|
||||
pub(super) fn toggle_java_auto_install(&mut self, on: bool) {
|
||||
self.settings.java.prefs.auto_install = on;
|
||||
self.settings.java.notice = None;
|
||||
self.view_dirty = true;
|
||||
}
|
||||
|
||||
/// 发行版顺序上移 / 下移一行。
|
||||
pub(super) fn move_java_vendor(&mut self, index: usize, up: bool) {
|
||||
let domestic = self.settings.java.effective.domestic;
|
||||
if up {
|
||||
self.settings.java.prefs.move_up(index, domestic);
|
||||
} else {
|
||||
self.settings.java.prefs.move_down(index, domestic);
|
||||
}
|
||||
self.settings.java.notice = None;
|
||||
self.view_dirty = true;
|
||||
}
|
||||
|
||||
/// 恢复地区默认序(= 把这个键写回空,让地区那一层重新生效)。
|
||||
pub(super) fn reset_java_priority(&mut self) {
|
||||
self.settings.java.prefs.reset_priority();
|
||||
self.settings.java.notice = None;
|
||||
self.view_dirty = true;
|
||||
}
|
||||
|
||||
/// 保存三个键:本地校验 → 落盘 → **用读回的真值**刷新草稿与生效值 → 重扫一次。
|
||||
pub(super) fn save_java_prefs(&mut self) {
|
||||
use pages::settings::java::Notice;
|
||||
|
||||
self.view_dirty = true;
|
||||
if let Err(refusal) = self.settings.java.prefs.validate() {
|
||||
self.settings.java.notice = Some(Notice::Refused(refusal));
|
||||
return;
|
||||
}
|
||||
let Some(config) = pages::settings::java::store::config_of(&self.bridge) else {
|
||||
self.settings.java.notice = Some(Notice::NoStorage);
|
||||
return;
|
||||
};
|
||||
match pages::settings::java::prefs_store::save(&config, &self.settings.java.prefs) {
|
||||
Ok(snapshot) => {
|
||||
self.settings.java.prefs.adopt(snapshot);
|
||||
self.settings.java.effective = pages::settings::java::prefs_store::effective(
|
||||
&config,
|
||||
&self.settings.java.prefs,
|
||||
);
|
||||
// 落点 / 顺序变了:托管根的集合可能整份不同,立刻重扫一次。
|
||||
// 顺序要紧:`start_java_scan` 会清 `notice`,所以回执写在它之后。
|
||||
let _ = self.start_java_scan();
|
||||
self.settings.java.notice = Some(Notice::PrefsSaved);
|
||||
}
|
||||
Err(error) => self.settings.java.notice = Some(write_notice(error)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 消息→落点的那一层(`java.rs` 的 match 里一行转发)。
|
||||
pub(super) fn on_edit_install_root(app: &mut App, value: String) -> Task<Message> {
|
||||
app.edit_java_install_root(value);
|
||||
Task::none()
|
||||
}
|
||||
|
||||
/// `ToggleAutoInstall` 的转发。
|
||||
pub(super) fn on_toggle_auto_install(app: &mut App, on: bool) -> Task<Message> {
|
||||
app.toggle_java_auto_install(on);
|
||||
Task::none()
|
||||
}
|
||||
|
||||
/// `MoveVendor` 的转发。
|
||||
pub(super) fn on_move_vendor(app: &mut App, index: usize, up: bool) -> Task<Message> {
|
||||
app.move_java_vendor(index, up);
|
||||
Task::none()
|
||||
}
|
||||
|
||||
/// `ResetPriority` 的转发。
|
||||
pub(super) fn on_reset_priority(app: &mut App) -> Task<Message> {
|
||||
app.reset_java_priority();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
/// `SavePrefs` 的转发。
|
||||
pub(super) fn on_save_prefs(app: &mut App) -> Task<Message> {
|
||||
app.save_java_prefs();
|
||||
Task::none()
|
||||
}
|
||||
@@ -161,3 +161,142 @@ fn a_schema_rejection_surfaces_as_a_page_key_not_the_core_sentence() {
|
||||
);
|
||||
std::fs::remove_dir_all(path.parent().unwrap().parent().unwrap()).ok();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------- M197:三个设置键 + 真下载的落点
|
||||
|
||||
/// 三键改完点保存:**真落盘**、草稿被读回值收尾、不再脏,并且保存顺手重扫一次。
|
||||
///
|
||||
/// 变异证明:`save_java_prefs` 里不调 `prefs.adopt(snapshot)` ⇒ 草稿还是 `" D:/JDKs "`、
|
||||
/// `dirty` 仍为真 ⇒ 本条红;不调 `start_java_scan` ⇒ `scan.report().running` 那条红。
|
||||
#[test]
|
||||
fn saving_the_three_keys_writes_them_and_reads_them_back() {
|
||||
use pages::settings::java::prefs_store;
|
||||
|
||||
let (mut app, path) = bridged_app("java-prefs");
|
||||
// 落点用这个临时数据根下的绝对路径:Windows / macOS / Linux 上都是绝对的,
|
||||
// 断言于是与平台无关(写 "D:/JDKs" 在非 Windows 上是相对路径,会被解析到数据根下)。
|
||||
let home = path.parent().unwrap().parent().unwrap().to_path_buf();
|
||||
let jdks = home.join("JDKs").display().to_string();
|
||||
let _ = app.update(java(pages::settings::java::Message::EditInstallRoot(
|
||||
format!(" {jdks} "),
|
||||
)));
|
||||
let _ = app.update(java(pages::settings::java::Message::ToggleAutoInstall(
|
||||
false,
|
||||
)));
|
||||
let _ = app.update(java(pages::settings::java::Message::MoveVendor {
|
||||
index: 0,
|
||||
up: false,
|
||||
}));
|
||||
assert!(app.settings.java.prefs.dirty(), "改过三键就该是脏的");
|
||||
|
||||
let _ = app.update(java(pages::settings::java::Message::SavePrefs));
|
||||
|
||||
assert_eq!(
|
||||
app.settings.java.notice,
|
||||
Some(pages::settings::java::Notice::PrefsSaved)
|
||||
);
|
||||
assert!(
|
||||
!app.settings.java.prefs.dirty(),
|
||||
"保存并把读回值当草稿之后不该还脏"
|
||||
);
|
||||
assert_eq!(
|
||||
app.settings.java.prefs.install_root, jdks,
|
||||
"草稿必须等于磁盘上那份(trim 过的),不是用户刚敲的原样"
|
||||
);
|
||||
assert!(
|
||||
!app.settings.java.prefs.saved_auto_install,
|
||||
"auto_install 要真变成关"
|
||||
);
|
||||
|
||||
// 冷读:另起一次 load,确认三个键都在文件里。
|
||||
let snapshot = prefs_store::load(&path);
|
||||
assert_eq!(snapshot.install_root, jdks);
|
||||
assert!(!snapshot.auto_install);
|
||||
assert_eq!(snapshot.priority.len(), 4, "下移之后落盘的是整条链");
|
||||
assert_ne!(snapshot.priority[0], "temurin", "顺序真的被改过");
|
||||
assert!(
|
||||
app.settings.java.scan.report().running,
|
||||
"改了落点必须重扫一次,否则列表还停在旧目录里"
|
||||
);
|
||||
// 生效值也跟着换了层级(设了 installRoot ⇒ 落点来自设置)。
|
||||
assert_eq!(
|
||||
app.settings.java.effective.root, jdks,
|
||||
"生效落点必须是刚保存的那一个"
|
||||
);
|
||||
std::fs::remove_dir_all(path.parent().unwrap().parent().unwrap()).ok();
|
||||
}
|
||||
|
||||
/// `java.auto_install` 开着且还没有默认 JDK:装完之后自动把新装的那份设为默认。
|
||||
///
|
||||
/// 变异证明:把 `hydrate_java_downloads` 里那段 `saved_auto_install && selected.is_empty()`
|
||||
/// 的判据删掉 ⇒ 本条红(`selected` 还是空);把关掉那一档的断言反过来说明判据不是恒真。
|
||||
#[test]
|
||||
fn auto_install_adopts_the_fresh_jdk_when_no_default_is_set() {
|
||||
use pages::settings::java::downloads::{Report, Success};
|
||||
|
||||
let (mut app, path) = bridged_app("java-adopt");
|
||||
app.settings.java.prefs.saved_auto_install = true;
|
||||
app.settings.java.selected = String::new();
|
||||
app.settings.java.downloads.seed_report(Report {
|
||||
job: None,
|
||||
tries: Vec::new(),
|
||||
failure: None,
|
||||
success: Some(Success {
|
||||
major: 21,
|
||||
vendor: "Eclipse Temurin",
|
||||
root: "D:/jdks/temurin/21".to_string(),
|
||||
binary: "D:/jdks/temurin/21/bin/java.exe".to_string(),
|
||||
source: Some("tuna".to_string()),
|
||||
reused: false,
|
||||
}),
|
||||
});
|
||||
assert!(app.hydrate_java_downloads(), "快照变了就要重建视图");
|
||||
assert_eq!(
|
||||
app.settings.java.selected, "D:/jdks/temurin/21/bin/java.exe",
|
||||
"auto_install 开着 + 没有默认 JDK ⇒ 新装的那份自动成为默认"
|
||||
);
|
||||
let snapshot = pages::settings::java::store::load(&path);
|
||||
assert_eq!(
|
||||
snapshot.selected, "D:/jdks/temurin/21/bin/java.exe",
|
||||
"而且真写进了 java.selected_path"
|
||||
);
|
||||
|
||||
// 关掉 auto_install 时同样的成功快照**不**改默认。
|
||||
let (mut app, path) = bridged_app("java-adopt-off");
|
||||
app.settings.java.prefs.saved_auto_install = false;
|
||||
app.settings.java.selected = String::new();
|
||||
app.settings.java.downloads.seed_report(Report {
|
||||
job: None,
|
||||
tries: Vec::new(),
|
||||
failure: None,
|
||||
success: Some(Success {
|
||||
major: 17,
|
||||
vendor: "Eclipse Temurin",
|
||||
root: "D:/jdks/temurin/17".to_string(),
|
||||
binary: "D:/jdks/temurin/17/bin/java.exe".to_string(),
|
||||
source: None,
|
||||
reused: true,
|
||||
}),
|
||||
});
|
||||
assert!(app.hydrate_java_downloads());
|
||||
assert_eq!(app.settings.java.selected, "", "关掉就不许替用户改默认");
|
||||
std::fs::remove_dir_all(path.parent().unwrap().parent().unwrap()).ok();
|
||||
}
|
||||
|
||||
/// 点一个目录里没有的大版本:立刻在下载区顶上写清原因,**不**起线程。
|
||||
///
|
||||
/// 变异证明:把 `start_java_download` 里 `catalog::find(major).is_none()` 那道判据删掉 ⇒
|
||||
/// `download_notice` 为 `None`,本条红(点了却什么都不说是禁止的)。
|
||||
#[test]
|
||||
fn an_unknown_major_is_refused_on_the_spot() {
|
||||
use pages::settings::java::downloads::Refusal;
|
||||
|
||||
let (mut app, path) = bridged_app("java-dl-refuse");
|
||||
let _ = app.update(java(pages::settings::java::Message::Download(99)));
|
||||
assert_eq!(
|
||||
app.settings.java.download_notice,
|
||||
Some(Refusal::UnknownMajor)
|
||||
);
|
||||
assert!(!app.settings.java.downloads.busy(), "不该起任何作业");
|
||||
std::fs::remove_dir_all(path.parent().unwrap().parent().unwrap()).ok();
|
||||
}
|
||||
Reference in new issue
Block a user