pub(crate) mod changelog;
use super::modal;
use super::update_check::INSTALLED_VERSION;
use super::App;
use crate::config::persistence;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PostUpgradeAction {
Nothing,
StampSilently,
Show,
}
pub(crate) fn post_upgrade_action(
last_version_seen: &str,
installed: &str,
show_welcome: bool,
) -> PostUpgradeAction {
if last_version_seen == installed {
return PostUpgradeAction::Nothing;
}
if last_version_seen.is_empty() && show_welcome {
return PostUpgradeAction::StampSilently;
}
PostUpgradeAction::Show
}
pub(crate) fn startup_notice(
last_version_seen: &str,
show_welcome: bool,
) -> Option<modal::PostUpgradeModal> {
if !persistence::config_writes_allowed() {
return None;
}
match post_upgrade_action(last_version_seen, INSTALLED_VERSION, show_welcome) {
PostUpgradeAction::Show => modal::PostUpgradeModal::for_upgrade(),
PostUpgradeAction::Nothing | PostUpgradeAction::StampSilently => None,
}
}
impl App {
pub(super) fn stamp_last_version_seen(&mut self) {
if self.config.editor.last_version_seen == INSTALLED_VERSION {
return;
}
self.config.editor.last_version_seen = INSTALLED_VERSION.to_owned();
self.save_update_bookkeeping("last-version-seen");
}
pub fn open_post_upgrade_modal(&mut self) {
if self.modal_stack.contains::<modal::PostUpgradeModal>() {
return;
}
self.modal_stack
.push(Box::new(modal::PostUpgradeModal::on_demand()));
self.needs_draw = true;
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::app::test_utils::make_app;
const OLDER: &str = "0.0.1";
#[test]
fn the_running_version_owes_nothing() {
assert_eq!(
post_upgrade_action(INSTALLED_VERSION, INSTALLED_VERSION, false),
PostUpgradeAction::Nothing
);
assert_eq!(
post_upgrade_action(INSTALLED_VERSION, INSTALLED_VERSION, true),
PostUpgradeAction::Nothing
);
}
#[test]
fn a_fresh_install_is_stamped_but_not_greeted() {
assert_eq!(
post_upgrade_action("", INSTALLED_VERSION, true),
PostUpgradeAction::StampSilently
);
}
#[test]
fn an_upgrade_from_before_the_field_existed_is_shown() {
assert_eq!(
post_upgrade_action("", INSTALLED_VERSION, false),
PostUpgradeAction::Show
);
}
#[test]
fn an_ordinary_upgrade_is_shown_whatever_the_welcome_says() {
assert_eq!(
post_upgrade_action(OLDER, INSTALLED_VERSION, false),
PostUpgradeAction::Show
);
assert_eq!(
post_upgrade_action(OLDER, INSTALLED_VERSION, true),
PostUpgradeAction::Show
);
}
#[test]
fn a_downgrade_is_shown_too() {
assert_eq!(
post_upgrade_action("999.0.0", INSTALLED_VERSION, false),
PostUpgradeAction::Show
);
}
#[test]
fn no_config_refuses_the_notice_outright() {
let _iso = crate::test_env::config_isolation();
assert!(
startup_notice("", false).is_none(),
"writes are suppressed, so nothing may be shown"
);
}
#[test]
fn stamping_records_the_running_version() {
let _iso = crate::test_env::config_isolation();
let mut app = make_app();
app.config.editor.last_version_seen = OLDER.to_owned();
app.stamp_last_version_seen();
assert_eq!(app.config.editor.last_version_seen, INSTALLED_VERSION);
}
#[test]
fn stamping_an_already_current_version_changes_nothing() {
let _iso = crate::test_env::config_isolation();
let mut app = make_app();
app.config.editor.last_version_seen = INSTALLED_VERSION.to_owned();
app.stamp_last_version_seen();
assert_eq!(app.config.editor.last_version_seen, INSTALLED_VERSION);
}
#[test]
fn the_explicit_opening_writes_no_bookkeeping() {
let _iso = crate::test_env::config_isolation();
let mut app = make_app();
app.config.editor.last_version_seen = OLDER.to_owned();
app.open_post_upgrade_modal();
assert!(app.modal_stack.contains::<modal::PostUpgradeModal>());
assert_eq!(app.config.editor.last_version_seen, OLDER);
}
fn returning_user_app(last_version_seen: &str) -> App {
use crate::config::{Config, KeyBindingOverrides, Theme};
use crate::terminal::{Capabilities, ColorDepth};
let caps = Capabilities {
color_depth: ColorDepth::TrueColor,
..Capabilities::default()
};
let mut config = Config::default();
config.editor.show_welcome = false;
config.editor.last_version_seen = last_version_seen.to_owned();
App::new(
config,
KeyBindingOverrides::default(),
(&Theme::default()).into(),
None,
caps,
Vec::new(),
)
.expect("build app")
}
#[test]
fn a_returning_user_on_a_new_build_is_shown_the_notice_at_startup() {
let _lock = crate::test_env::env_lock();
let app = returning_user_app("0.0.1");
assert_eq!(
app.modal_stack.contains::<modal::PostUpgradeModal>(),
changelog::notes_for_version(INSTALLED_VERSION).is_some(),
"shown exactly when this version has changelog notes"
);
}
#[test]
fn a_launch_on_the_recorded_version_raises_nothing() {
let _lock = crate::test_env::env_lock();
let app = returning_user_app(INSTALLED_VERSION);
assert!(!app.modal_stack.contains::<modal::PostUpgradeModal>());
}
#[test]
fn a_first_run_is_never_greeted_with_release_notes() {
let _lock = crate::test_env::env_lock();
let app = make_app();
assert!(!app.modal_stack.contains::<modal::PostUpgradeModal>());
}
#[test]
fn opening_it_twice_does_not_stack_it() {
let _iso = crate::test_env::config_isolation();
let mut app = make_app();
app.open_post_upgrade_modal();
app.open_post_upgrade_modal();
assert_eq!(app.modal_stack.count::<modal::PostUpgradeModal>(), 1);
}
}