refactor: rename aim to upm and extract appimage module
This commit is contained in:
parent
af13e98eb3
commit
863c57e473
117 changed files with 2622 additions and 887 deletions
755
crates/upm/tests/end_to_end_cli.rs
Normal file
755
crates/upm/tests/end_to_end_cli.rs
Normal file
|
|
@ -0,0 +1,755 @@
|
|||
use assert_cmd::Command;
|
||||
use predicates::prelude::PredicateBooleanExt;
|
||||
use predicates::str::contains;
|
||||
use tempfile::tempdir;
|
||||
use upm_core::domain::app::{AppRecord, InstallMetadata, InstallScope};
|
||||
use upm_core::registry::model::Registry;
|
||||
use upm_core::registry::store::RegistryStore;
|
||||
|
||||
const FIXTURE_MODE_ENV: &str = "UPM_FIXTURE_MODE";
|
||||
|
||||
#[test]
|
||||
fn list_command_runs_without_registry_entries() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("list")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("No installed apps yet"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_command_reads_registered_apps_from_registry_file() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
std::fs::write(
|
||||
®istry_path,
|
||||
"version = 1\n[[apps]]\nstable_id = \"bat\"\ndisplay_name = \"Bat\"\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("list")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Name"))
|
||||
.stdout(contains("Version"))
|
||||
.stdout(contains("Source"))
|
||||
.stdout(contains("Bat"))
|
||||
.stdout(contains("Bat (bat)").not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_command_removes_registered_app_from_registry_file() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
std::fs::write(
|
||||
®istry_path,
|
||||
"version = 1\n[[apps]]\nstable_id = \"bat\"\ndisplay_name = \"Bat\"\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.args(["remove", "bat"])
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Removed Bat"))
|
||||
.stdout(contains("Removal Summary").not())
|
||||
.stdout(contains("Removed app:").not());
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(!contents.contains("stable_id = \"bat\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_command_uninstalls_managed_files() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let install_home = dir.path().join("install-home");
|
||||
let payload_path = install_home.join(".local/lib/upm/appimages/sharkdp-bat.AppImage");
|
||||
let desktop_path = install_home.join(".local/share/applications/upm-sharkdp-bat.desktop");
|
||||
let icon_path = install_home.join(".local/share/icons/hicolor/256x256/apps/sharkdp-bat.png");
|
||||
|
||||
let mut add_cmd = Command::cargo_bin("upm").unwrap();
|
||||
add_cmd
|
||||
.arg("sharkdp/bat")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
assert!(payload_path.exists());
|
||||
assert!(desktop_path.exists());
|
||||
assert!(icon_path.exists());
|
||||
|
||||
let mut remove_cmd = Command::cargo_bin("upm").unwrap();
|
||||
remove_cmd
|
||||
.args(["remove", "sharkdp-bat"])
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("\nRemoved bat"))
|
||||
.stdout(contains("Removed bat"))
|
||||
.stdout(contains("Removal Summary").not())
|
||||
.stdout(contains("Removed app:").not())
|
||||
.stdout(contains("Removed files"))
|
||||
.stdout(contains("sharkdp-bat.AppImage"))
|
||||
.stdout(contains("upm-sharkdp-bat.desktop"))
|
||||
.stdout(contains("sharkdp-bat.png"));
|
||||
|
||||
assert!(!payload_path.exists());
|
||||
assert!(!desktop_path.exists());
|
||||
assert!(!icon_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn query_command_registers_unambiguous_app_in_registry_file() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("sharkdp/bat")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("\nInstalled bat (user)"))
|
||||
.stdout(contains("Installed bat (user)"))
|
||||
.stdout(contains("Installation Summary").not())
|
||||
.stdout(contains("Source: github sharkdp/bat"))
|
||||
.stdout(contains("Artifact:"))
|
||||
.stdout(contains("Selected artifact").not())
|
||||
.stdout(contains("metadata-guided").not())
|
||||
.stdout(contains("Installed files"))
|
||||
.stdout(contains("sharkdp-bat.AppImage"))
|
||||
.stdout(contains("Completed steps").not());
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(contents.contains("stable_id = \"sharkdp-bat\""));
|
||||
assert!(contents.contains("source_input = \"sharkdp/bat\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn old_release_query_renders_tracking_prompt_without_writing_registry() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("https://github.com/pingdotgg/t3code/releases/download/v0.0.11/T3-Code-0.0.11-x86_64.AppImage")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Choose update tracking"))
|
||||
.stdout(contains("v0.0.11"))
|
||||
.stdout(contains("v0.0.12"));
|
||||
|
||||
assert!(!registry_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn old_release_query_can_track_latest_and_register_app() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("https://github.com/pingdotgg/t3code/releases/download/v0.0.11/T3-Code-0.0.11-x86_64.AppImage")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.env("UPM_TRACKING_PREFERENCE", "latest")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("\nInstalled t3code (user)"))
|
||||
.stdout(contains("Installed t3code (user)"))
|
||||
.stdout(contains("Installation Summary").not())
|
||||
.stdout(contains("Source: github pingdotgg/t3code"))
|
||||
.stdout(contains("Artifact: T3-Code-0.0.12-x86_64.AppImage"))
|
||||
.stdout(contains("Selected artifact").not())
|
||||
.stdout(contains("metadata-guided").not())
|
||||
.stdout(contains("Installed files"))
|
||||
.stdout(contains("pingdotgg-t3code.AppImage"))
|
||||
.stdout(contains("Completed steps").not());
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(contents.contains("stable_id = \"pingdotgg-t3code\""));
|
||||
assert!(contents.contains("locator = \"pingdotgg/t3code\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn old_release_query_ignores_legacy_tracking_preference_env() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("https://github.com/pingdotgg/t3code/releases/download/v0.0.11/T3-Code-0.0.11-x86_64.AppImage")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.env("AIM_TRACKING_PREFERENCE", "latest")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Choose update tracking"))
|
||||
.stdout(contains("v0.0.11"))
|
||||
.stdout(contains("v0.0.12"))
|
||||
.stdout(contains("Installed t3code").not());
|
||||
|
||||
assert!(!registry_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_add_installs_and_renders_resolved_mode() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("sharkdp/bat")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("\nInstalled bat (user)"))
|
||||
.stdout(contains("Installed bat (user)"))
|
||||
.stdout(contains("Artifact:"))
|
||||
.stdout(contains("Installed files"))
|
||||
.stdout(contains("Completed steps").not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn positional_query_falls_back_to_search_for_plain_name_queries() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("firefox")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Search Results"))
|
||||
.stdout(contains(
|
||||
"[appimagehub] Firefox by Mozilla - Official AppImage Edition",
|
||||
))
|
||||
.stdout(contains("Install query: appimagehub/2338455"))
|
||||
.stdout(contains("Installed firefox").not())
|
||||
.stdout(contains("unsupported source query").not());
|
||||
|
||||
assert!(!registry_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn positional_query_falls_back_to_empty_search_when_direct_item_has_no_appimage() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("appimagehub/2337998")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Search Results"))
|
||||
.stdout(contains("No remote matches"))
|
||||
.stdout(contains("No installed matches"))
|
||||
.stdout(contains("unsupported source query").not())
|
||||
.stdout(contains("no installable artifact").not());
|
||||
|
||||
assert!(!registry_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_add_installs_appimagehub_source_with_truthful_origin() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("appimagehub/2338455")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains(
|
||||
"Installed Firefox by Mozilla - Official AppImage Edition (user)",
|
||||
))
|
||||
.stdout(contains(
|
||||
"Source: appimagehub https://www.appimagehub.com/p/2338455",
|
||||
))
|
||||
.stdout(contains(
|
||||
"Artifact: https://files06.pling.com/api/files/download/firefox-x86-64.AppImage",
|
||||
));
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(contents.contains("display_name = \"Firefox by Mozilla - Official AppImage Edition\""));
|
||||
assert!(contents.contains("kind = \"AppImageHub\""));
|
||||
assert!(contents.contains("canonical_locator = \"2338455\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_add_installs_gitlab_source_with_truthful_origin() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("https://gitlab.com/example/team-app")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Installed team-app (user)"))
|
||||
.stdout(contains("Source: gitlab https://gitlab.com/example/team-app"))
|
||||
.stdout(contains(
|
||||
"Artifact: https://gitlab.com/example/team-app/-/releases/permalink/latest/downloads/team-app.AppImage",
|
||||
));
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(contents.contains("source_input = \"https://gitlab.com/example/team-app\""));
|
||||
assert!(contents.contains("kind = \"GitLab\""));
|
||||
assert!(contents.contains("locator = \"https://gitlab.com/example/team-app\""));
|
||||
assert!(contents.contains("canonical_locator = \"example/team-app\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_add_preserves_direct_url_origin_for_provider_like_downloads() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let query = "https://sourceforge.net/projects/team-app/files/team-app-1.0.0.AppImage/download";
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg(query)
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Installed "))
|
||||
.stdout(contains(format!("Source: direct-url {query}")))
|
||||
.stdout(contains(format!("Artifact: {query}")));
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(contents.contains(&format!("source_input = \"{query}\"")));
|
||||
assert!(contents.contains("kind = \"DirectUrl\""));
|
||||
assert!(contents.contains(&format!("locator = \"{query}\"")));
|
||||
assert!(!contents.contains("kind = \"SourceForge\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_add_installs_sourceforge_latest_download_with_truthful_origin() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let query = "https://sourceforge.net/projects/team-app/files/latest/download";
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg(query)
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Installed team-app (user)"))
|
||||
.stdout(contains(format!("Source: sourceforge {query}")))
|
||||
.stdout(contains(format!("Artifact: {query}")));
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(contents.contains(&format!("source_input = \"{query}\"")));
|
||||
assert!(contents.contains("kind = \"SourceForge\""));
|
||||
assert!(contents.contains(&format!("locator = \"{query}\"")));
|
||||
assert!(contents.contains("canonical_locator = \"team-app\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_rejects_insecure_http_direct_urls_by_default() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("http://example.com/team-app.AppImage")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(contains("insecure HTTP sources are disabled"));
|
||||
|
||||
assert!(!registry_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_allows_insecure_http_direct_urls_when_config_enables_it() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let config_path = dir.path().join("config.toml");
|
||||
std::fs::write(&config_path, "allow_http = true\n").unwrap();
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("http://example.com/team-app.AppImage")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env("UPM_CONFIG_PATH", &config_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Installed"))
|
||||
.stdout(contains(
|
||||
"Source: direct-url http://example.com/team-app.AppImage",
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_rejects_insecure_appimagehub_download_urls_even_when_http_is_allowed() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let config_path = dir.path().join("config.toml");
|
||||
std::fs::write(&config_path, "allow_http = true\n").unwrap();
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("appimagehub/2338455")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env("UPM_CONFIG_PATH", &config_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.env("UPM_APPIMAGEHUB_FIXTURE_INSECURE_HTTP", "1")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(contains("insecure appimagehub download url"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_rejects_appimagehub_install_when_md5_does_not_match() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("appimagehub/2338455")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.env("UPM_APPIMAGEHUB_FIXTURE_BAD_MD5", "1")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(contains("weak provider checksum did not match"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_add_installs_sourceforge_release_folder_with_truthful_origin() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let query = "https://sourceforge.net/projects/team-app/files/releases/beta/download";
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg(query)
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Installed team-app (user)"))
|
||||
.stdout(contains(format!("Source: sourceforge {query}")))
|
||||
.stdout(contains(format!("Artifact: {query}")));
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(contents.contains(&format!("source_input = \"{query}\"")));
|
||||
assert!(contents.contains("kind = \"SourceForge\""));
|
||||
assert!(contents.contains(&format!("locator = \"{query}\"")));
|
||||
assert!(contents.contains("canonical_locator = \"team-app\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_add_file_like_sourceforge_release_download_stores_releases_root_and_preserves_artifact() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let query =
|
||||
"https://sourceforge.net/projects/team-app/files/releases/team-app-1.0.0.AppImage/download";
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg(query)
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Installed team-app (user)"))
|
||||
.stdout(contains(
|
||||
"Source: sourceforge https://sourceforge.net/projects/team-app/files/releases",
|
||||
))
|
||||
.stdout(contains(format!("Artifact: {query}")));
|
||||
|
||||
let contents = std::fs::read_to_string(®istry_path).unwrap();
|
||||
assert!(contents.contains(&format!("source_input = \"{query}\"")));
|
||||
assert!(contents.contains("kind = \"SourceForge\""));
|
||||
assert!(
|
||||
contents.contains("locator = \"https://sourceforge.net/projects/team-app/files/releases\"")
|
||||
);
|
||||
assert!(contents.contains("requested_asset_name = \"team-app-1.0.0.AppImage\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_reports_unsupported_source_queries_distinctly() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("https://gitlab.com/example")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Search Results"))
|
||||
.stdout(contains("No remote matches"))
|
||||
.stdout(contains("No installed matches"))
|
||||
.stderr(contains("unsupported source query").not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_reports_supported_sources_without_installable_artifacts_distinctly() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("https://sourceforge.net/projects/team-app/")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Search Results"))
|
||||
.stdout(contains("No remote matches"))
|
||||
.stdout(contains("No installed matches"))
|
||||
.stderr(contains("no installable artifact found").not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_add_emits_live_progress_to_stderr() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("sharkdp/bat")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stderr(contains("Installing sharkdp/bat"))
|
||||
.stderr(contains("Resolving source"))
|
||||
.stderr(contains("Discovering release"))
|
||||
.stderr(contains("Selecting artifact"))
|
||||
.stderr(contains("Downloading artifact"))
|
||||
.stderr(contains("Downloaded"))
|
||||
.stderr(contains("Payload Staged"))
|
||||
.stderr(contains("Desktop Entry Written"))
|
||||
.stderr(contains("Icon Extracted"))
|
||||
.stderr(contains("Desktop Integration Refreshed"))
|
||||
.stderr(contains("Registry Saved"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bare_upm_review_renders_review_heading() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let store = RegistryStore::new(registry_path.clone());
|
||||
store
|
||||
.save(&Registry {
|
||||
version: 1,
|
||||
apps: vec![AppRecord {
|
||||
stable_id: "pingdotgg-t3code".to_owned(),
|
||||
display_name: "t3code".to_owned(),
|
||||
source_input: Some("pingdotgg/t3code".to_owned()),
|
||||
source: None,
|
||||
installed_version: Some("0.0.11".to_owned()),
|
||||
update_strategy: None,
|
||||
metadata: Vec::new(),
|
||||
install: Some(InstallMetadata {
|
||||
scope: InstallScope::User,
|
||||
payload_path: None,
|
||||
desktop_entry_path: None,
|
||||
icon_path: None,
|
||||
}),
|
||||
}],
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Update Review"))
|
||||
.stdout(contains("apps with updates"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_command_emits_live_progress_to_stderr() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
std::fs::write(
|
||||
®istry_path,
|
||||
"version = 1\n[[apps]]\nstable_id = \"bat\"\ndisplay_name = \"Bat\"\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.args(["remove", "bat"])
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.assert()
|
||||
.success()
|
||||
.stderr(contains("Removing bat"))
|
||||
.stderr(contains("Resolving source: resolving bat"))
|
||||
.stderr(contains("Saving registry"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn system_request_on_immutable_host_falls_back_to_user_install() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let os_release_path = dir.path().join("os-release");
|
||||
std::fs::write(&os_release_path, "ID=fedora\nVARIANT_ID=silverblue\n").unwrap();
|
||||
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.args(["--system", "sharkdp/bat"])
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env("UPM_OS_RELEASE_PATH", &os_release_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Installed bat (user)"))
|
||||
.stdout(contains("downgraded to user scope"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_command_applies_updates() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let payload_path = dir
|
||||
.path()
|
||||
.join("install-home/.local/lib/upm/appimages/pingdotgg-t3code.AppImage");
|
||||
let store = RegistryStore::new(registry_path.clone());
|
||||
store
|
||||
.save(&Registry {
|
||||
version: 1,
|
||||
apps: vec![AppRecord {
|
||||
stable_id: "pingdotgg-t3code".to_owned(),
|
||||
display_name: "t3code".to_owned(),
|
||||
source_input: Some("pingdotgg/t3code".to_owned()),
|
||||
source: None,
|
||||
installed_version: Some("0.0.11".to_owned()),
|
||||
update_strategy: None,
|
||||
metadata: Vec::new(),
|
||||
install: Some(InstallMetadata {
|
||||
scope: InstallScope::User,
|
||||
payload_path: None,
|
||||
desktop_entry_path: None,
|
||||
icon_path: None,
|
||||
}),
|
||||
}],
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("update")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("updated apps: 1"))
|
||||
.stdout(contains("updates found:").not());
|
||||
|
||||
let updated = store.load().unwrap();
|
||||
assert_eq!(updated.apps.len(), 1);
|
||||
assert_eq!(updated.apps[0].stable_id, "pingdotgg-t3code");
|
||||
assert_eq!(updated.apps[0].installed_version.as_deref(), Some("0.0.12"));
|
||||
assert!(payload_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_command_emits_live_progress_to_stderr() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let store = RegistryStore::new(registry_path.clone());
|
||||
store
|
||||
.save(&Registry {
|
||||
version: 1,
|
||||
apps: vec![AppRecord {
|
||||
stable_id: "pingdotgg-t3code".to_owned(),
|
||||
display_name: "t3code".to_owned(),
|
||||
source_input: Some("pingdotgg/t3code".to_owned()),
|
||||
source: None,
|
||||
installed_version: Some("0.0.11".to_owned()),
|
||||
update_strategy: None,
|
||||
metadata: Vec::new(),
|
||||
install: Some(InstallMetadata {
|
||||
scope: InstallScope::User,
|
||||
payload_path: None,
|
||||
desktop_entry_path: None,
|
||||
icon_path: None,
|
||||
}),
|
||||
}],
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("update")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.assert()
|
||||
.success()
|
||||
.stderr(contains("Updating 1 apps"))
|
||||
.stderr(contains("Resolving source: resolving pingdotgg-t3code"))
|
||||
.stderr(contains("Saving registry"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_command_reports_when_previous_installation_is_restored() {
|
||||
let dir = tempdir().unwrap();
|
||||
let registry_path = dir.path().join("registry.toml");
|
||||
let install_home = dir.path().join("install-home");
|
||||
let store = RegistryStore::new(registry_path.clone());
|
||||
let stable_id = "url-example.com-downloads-team-app.appimage";
|
||||
let payload_path = install_home.join(format!(".local/lib/upm/appimages/{stable_id}.AppImage"));
|
||||
|
||||
std::fs::create_dir_all(payload_path.parent().unwrap()).unwrap();
|
||||
std::fs::write(&payload_path, b"previous-payload").unwrap();
|
||||
std::fs::create_dir_all(install_home.join(".local/share")).unwrap();
|
||||
std::fs::write(install_home.join(".local/share/applications"), b"blocker").unwrap();
|
||||
|
||||
store
|
||||
.save(&Registry {
|
||||
version: 1,
|
||||
apps: vec![AppRecord {
|
||||
stable_id: stable_id.to_owned(),
|
||||
display_name: "https://example.com/downloads/team-app.AppImage".to_owned(),
|
||||
source_input: Some("https://example.com/downloads/team-app.AppImage".to_owned()),
|
||||
source: Some(upm_core::domain::source::SourceRef {
|
||||
kind: upm_core::domain::source::SourceKind::DirectUrl,
|
||||
locator: "https://example.com/downloads/team-app.AppImage".to_owned(),
|
||||
input_kind: upm_core::domain::source::SourceInputKind::DirectUrl,
|
||||
normalized_kind: upm_core::domain::source::NormalizedSourceKind::DirectUrl,
|
||||
canonical_locator: None,
|
||||
requested_tag: None,
|
||||
requested_asset_name: None,
|
||||
tracks_latest: false,
|
||||
}),
|
||||
installed_version: Some("unresolved".to_owned()),
|
||||
update_strategy: None,
|
||||
metadata: Vec::new(),
|
||||
install: Some(InstallMetadata {
|
||||
scope: InstallScope::User,
|
||||
payload_path: Some(payload_path.display().to_string()),
|
||||
desktop_entry_path: None,
|
||||
icon_path: None,
|
||||
}),
|
||||
}],
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut cmd = Command::cargo_bin("upm").unwrap();
|
||||
|
||||
cmd.arg("update")
|
||||
.env("UPM_REGISTRY_PATH", ®istry_path)
|
||||
.env(FIXTURE_MODE_ENV, "1")
|
||||
.env("DISPLAY", ":99")
|
||||
.env("XDG_CURRENT_DESKTOP", "test")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(contains("Failed:"))
|
||||
.stdout(contains("restored previous installation"));
|
||||
|
||||
assert_eq!(std::fs::read(&payload_path).unwrap(), b"previous-payload");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue