storebound/apps/desktop/src-tauri/tests/d5.rs

104 lines
5.1 KiB
Rust

//! D5 release pipeline: one version everywhere, the updater's key and endpoints, the `storebound://open?path=` deep
//! link and the self-test the release runs on the exact artifact.
use std::fs;
use std::path::PathBuf;
use base64::Engine;
use serde_json::Value;
use storebound_desktop::policy::deep_link_open_path;
use storebound_desktop::{selftest, updates};
use url::Url;
fn root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
fn conf() -> Value {
serde_json::from_str(&fs::read_to_string(root().join("tauri.conf.json")).unwrap()).unwrap()
}
#[test]
fn one_version_from_the_root_package_json() {
let pkg: Value = serde_json::from_str(&fs::read_to_string(root().join("../../../package.json")).unwrap()).unwrap();
let want = pkg["desktopVersion"].as_str().expect("package.json desktopVersion");
assert_eq!(env!("CARGO_PKG_VERSION"), want, "Cargo.toml (bun tools/desktop-version.ts --set {want})");
assert_eq!(conf()["version"], want, "tauri.conf.json");
let app: Value = serde_json::from_str(&fs::read_to_string(root().join("../package.json")).unwrap()).unwrap();
assert_eq!(app["version"], want, "apps/desktop/package.json");
}
#[test]
fn updater_has_a_real_minisign_key_and_only_storebound_dev() {
let c = conf();
let key = c["plugins"]["updater"]["pubkey"].as_str().unwrap();
let text = String::from_utf8(base64::engine::general_purpose::STANDARD.decode(key).expect("base64 pubkey")).unwrap();
let mut lines = text.lines();
assert!(lines.next().unwrap().starts_with("untrusted comment: minisign public key"));
let raw = base64::engine::general_purpose::STANDARD.decode(lines.next().unwrap()).unwrap();
assert_eq!(raw.len(), 42, "Ed + key id + 32-byte key");
assert_eq!(&raw[..2], b"Ed");
assert_eq!(c["plugins"]["updater"]["endpoints"], serde_json::json!([updates::STABLE]));
// updater bundles are signed by tools/desktop-release.ts on the release Mac, never by a CI runner
assert_eq!(c["bundle"]["createUpdaterArtifacts"], false);
for ch in ["stable", "beta", "nightly", ""] {
assert!(updates::endpoint_allowed(&Url::parse(updates::endpoint(ch)).unwrap()), "{ch}");
}
assert_eq!(updates::endpoint("beta"), updates::BETA);
assert_eq!(updates::endpoint("anything"), updates::STABLE);
for bad in ["http://storebound.dev/desktop/latest.json", "https://storebound.dev:8443/desktop/latest.json", "https://evil.test/desktop/latest.json", "https://storebound.dev/latest.json"] {
assert!(!updates::endpoint_allowed(&Url::parse(bad).unwrap()), "{bad}");
}
assert!(updates::error_text("signature verification failed").contains("not installed"));
}
#[test]
fn open_deep_link_takes_one_plain_absolute_path() {
let p = |s: &str| deep_link_open_path(&Url::parse(s).unwrap());
let abs = if cfg!(windows) { "C:%5Cgames%5CDemo App" } else { "%2FUsers%2Fyou%2Fgames%2FDemo App" };
let want = if cfg!(windows) { "C:\\games\\Demo App" } else { "/Users/you/games/Demo App" };
assert_eq!(p(&format!("storebound://open?path={abs}")), Some(PathBuf::from(want)));
assert_eq!(p(&format!("storebound://open/?path={abs}")), Some(PathBuf::from(want)));
for bad in [
"storebound://open?path=games%2FDemo App".to_string(),
"storebound://open?path=".to_string(),
"storebound://open".to_string(),
format!("storebound://open?path={abs}&path={abs}"),
format!("storebound://open?path={abs}&run=1"),
format!("storebound://open?path={abs}%2F..%2F..%2Fetc"),
format!("storebound://open?path={abs}%0A"),
format!("storebound://open/x?path={abs}"),
format!("storebound://open?path={abs}#f"),
format!("storebound://user@open?path={abs}"),
format!("storebound://apps?path={abs}"),
format!("https://open?path={abs}"),
format!("storebound://open?path={}", "a".repeat(5000)),
] {
assert_eq!(p(&bad), None, "{bad}");
}
}
#[test]
fn self_test_looks_for_the_sidecar_next_to_the_executable() {
let p = selftest::sidecar_path().unwrap();
let exe = std::env::current_exe().unwrap();
assert_eq!(p.parent(), exe.parent());
assert_eq!(p.file_name().unwrap().to_string_lossy(), format!("storebound{}", std::env::consts::EXE_SUFFIX));
assert_eq!(selftest::FLAG, "--self-test");
// the flag is handled in main before Tauri starts, so no window opens
let main = fs::read_to_string(root().join("src/main.rs")).unwrap();
let flag = main.find("selftest::FLAG").unwrap();
assert!(flag < main.find("storebound_desktop::run()").unwrap());
}
#[test]
fn deep_links_to_folders_ask_before_adding() {
let cmds = fs::read_to_string(root().join("src/commands.rs")).unwrap();
let at = cmds.find("async fn open_folder(").unwrap();
let body = &cmds[at..];
let confirm = body.find("confirm_dialog_with(").unwrap();
let add = body.find("add_folder(").unwrap();
assert!(confirm < add, "the native dialog comes before add_folder");
let at = cmds.find("pub async fn update_install(").unwrap();
let body = &cmds[at..];
assert!(body.find("confirm_dialog_with(").unwrap() < body.find("download_and_install(").unwrap());
}