254 lines
12 KiB
Rust
254 lines
12 KiB
Rust
// file: crates/ksp-app-backfill-desk/tests/desktop_contract.rs
|
|
// version: 6
|
|
|
|
//! Structural desktop contract checks for the Backfill Desk scaffold.
|
|
|
|
#![forbid(unsafe_code)]
|
|
#![deny(unreachable_pub)]
|
|
#![warn(missing_docs)]
|
|
|
|
fn app_root() -> std::path::PathBuf {
|
|
return std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
}
|
|
|
|
fn workspace_root() -> std::path::PathBuf {
|
|
return app_root().join("../..");
|
|
}
|
|
|
|
fn read_text(path: &std::path::Path) -> String {
|
|
let source = std::fs::read_to_string(path);
|
|
assert!(source.is_ok(), "unable to read {}", path.display());
|
|
return match source {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => String::new(),
|
|
};
|
|
}
|
|
|
|
fn read_json(path: &std::path::Path) -> serde_json::Value {
|
|
let source = read_text(path);
|
|
let parsed = serde_json::from_str(source.as_str());
|
|
assert!(parsed.is_ok(), "unable to parse {}", path.display());
|
|
return match parsed {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => serde_json::Value::Null,
|
|
};
|
|
}
|
|
|
|
fn read_bytes(path: &std::path::Path) -> std::vec::Vec<u8> {
|
|
let source = std::fs::read(path);
|
|
assert!(source.is_ok(), "unable to read {}", path.display());
|
|
return match source {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => std::vec::Vec::new(),
|
|
};
|
|
}
|
|
|
|
#[test]
|
|
fn pre_002_rust_package_is_mixed_lib_bin_and_workspace_member() {
|
|
let root = app_root();
|
|
let manifest = read_text(root.join("Cargo.toml").as_path());
|
|
assert!(manifest.contains("name = \"ksp-app-backfill-desk\""));
|
|
assert!(manifest.contains("name = \"ksp_app_backfill_desk_lib\""));
|
|
assert!(manifest.contains("[[bin]]"));
|
|
let workspace = read_text(workspace_root().join("Cargo.toml").as_path());
|
|
assert!(workspace.contains("crates/ksp-app-backfill-desk"));
|
|
let launcher = read_text(root.join("src/main.rs").as_path());
|
|
assert!(launcher.contains("ksp_app_backfill_desk_lib::run"));
|
|
assert!(launcher.contains("try_lock_exclusive"));
|
|
}
|
|
|
|
#[test]
|
|
fn pre_002_vite_and_tauri_identity_use_reserved_ports_and_crate_local_hooks() {
|
|
let root = app_root();
|
|
let vite = read_text(root.join("vite.config.ts").as_path());
|
|
assert!(vite.contains("port: 1436"));
|
|
assert!(vite.contains("port: 1437"));
|
|
assert!(vite.contains("strictPort: true"));
|
|
let tauri = read_text(root.join("tauri.conf.json").as_path());
|
|
assert!(tauri.contains("KSP Backfill Desk"));
|
|
assert!(tauri.contains("com.sasedev.ksp-app-backfill-desk"));
|
|
assert!(tauri.contains("http://localhost:1436"));
|
|
assert!(tauri.contains("npm run dev"));
|
|
assert!(tauri.contains("npm run build"));
|
|
assert!(tauri.contains("../../../builds/khadhroony-solana-project/ksp-app-backfill-desk/dist"));
|
|
}
|
|
|
|
#[test]
|
|
fn pre_002_package_dependencies_match_desk_baseline() {
|
|
let package = read_text(app_root().join("package.json").as_path());
|
|
for required in [
|
|
"@fltsci/tauri-plugin-tracing",
|
|
"@fortawesome/fontawesome-free",
|
|
"@tauri-apps/api",
|
|
"bootstrap",
|
|
"resize-observer-polyfill",
|
|
"simplebar",
|
|
"@tauri-apps/cli",
|
|
"@types/bootstrap",
|
|
"@types/node",
|
|
"sass-embedded",
|
|
"typescript",
|
|
"vite",
|
|
] {
|
|
assert!(package.contains(required), "missing Desk package baseline dependency {required}");
|
|
}
|
|
assert!(!package.contains("package-lock"));
|
|
}
|
|
|
|
#[test]
|
|
fn pre_002_splash_assets_and_styles_match_existing_desk_template() {
|
|
let root = app_root();
|
|
let reference = workspace_root().join("crates/ksp-app-solprices-desk");
|
|
for relative in ["frontend/fonts/DOS_Amazigh.ttf", "frontend/imgs/logo.png", "frontend/imgs/splash.png", "icons/favicon.png", "icons/favicon.ico"] {
|
|
assert_eq!(read_bytes(root.join(relative).as_path()), read_bytes(reference.join(relative).as_path()), "Desk asset differs: {relative}");
|
|
}
|
|
let splash = read_text(root.join("frontend/splash.html").as_path());
|
|
assert!(splash.contains("imgs/splash.png"));
|
|
assert!(splash.contains("Backfill Desk"));
|
|
let splash_style = read_text(root.join("frontend/sass/splash.scss").as_path());
|
|
let reference_style = read_text(reference.join("frontend/sass/splash.scss").as_path());
|
|
let normalized = splash_style.replace("crates/ksp-app-backfill-desk", "crates/ksp-app-solprices-desk").replace("// version: 1", "// version: 2");
|
|
assert_eq!(normalized, reference_style);
|
|
}
|
|
|
|
#[test]
|
|
fn pre_002_shell_and_splash_use_shared_frontend_tooling() {
|
|
let root = app_root();
|
|
let shell = read_text(root.join("frontend/main.html").as_path());
|
|
for required in ["app-header", "app-sidebar", "app-sidebar-scroll", "app-content", "app-footer", "data-simplebar"] {
|
|
assert!(shell.contains(required), "Backfill Desk shell is missing template marker {required}");
|
|
}
|
|
let main = read_text(root.join("frontend/ts/main.ts").as_path());
|
|
assert!(main.contains("resize-observer-polyfill"));
|
|
assert!(main.contains("simplebar"));
|
|
assert!(main.contains("bootstrap"));
|
|
assert!(main.contains("Backfill Desk frontend control clicked"));
|
|
assert!(main.contains("Backfill Desk navigation tab clicked"));
|
|
assert!(main.contains("Backfill Desk runtime status refresh button clicked"));
|
|
let splash = read_text(root.join("frontend/ts/splash.ts").as_path());
|
|
assert!(splash.contains("Splash opacity animation started"));
|
|
assert!(splash.contains("Backfill Desk splash frontend loaded"));
|
|
}
|
|
|
|
#[test]
|
|
fn pre_003_composite_packaging_follows_atomic_config_registry_contract() {
|
|
let root = app_root();
|
|
let config = read_json(root.join("tauri.conf.json").as_path());
|
|
let resources = config
|
|
.get("bundle")
|
|
.and_then(|value| {
|
|
return value.get("resources");
|
|
})
|
|
.and_then(serde_json::Value::as_object);
|
|
assert!(resources.is_some());
|
|
let resources = match resources {
|
|
std::option::Option::Some(value) => value,
|
|
std::option::Option::None => return,
|
|
};
|
|
assert_eq!(resources.len(), 14);
|
|
for required in [
|
|
"../../config/composite.ksp-app-backfill-desk.json",
|
|
"../../config/composite.ksp-app-solprices-desk.json",
|
|
"../../config/composite.ksp-app-wallet-desk.json",
|
|
"../../config/std.logging.json",
|
|
"../../config/std.offchain_transport.json",
|
|
"../../config/std.store.json",
|
|
"../../config/std.transport.json",
|
|
"../../config/std.wallet.json",
|
|
"../../config/schemas/composite.schema.json",
|
|
"../../config/schemas/std.logging.schema.json",
|
|
"../../config/schemas/std.offchain_transport.schema.json",
|
|
"../../config/schemas/std.store.schema.json",
|
|
"../../config/schemas/std.transport.schema.json",
|
|
"../../config/schemas/std.wallet.schema.json",
|
|
] {
|
|
assert!(resources.contains_key(required), "missing packaged Config resource {required}");
|
|
}
|
|
let tauri = read_text(root.join("src/tauri.rs").as_path());
|
|
assert!(tauri.contains("prepare_packaged_runtime"));
|
|
assert!(tauri.contains("resource_dir"));
|
|
assert!(tauri.contains("set_current_dir"));
|
|
}
|
|
|
|
#[test]
|
|
fn pre_003_bootstrap_keeps_logging_composition_separate_from_transport_runtime() {
|
|
let root = app_root();
|
|
let bootstrap = read_text(root.join("src/bootstrap.rs").as_path());
|
|
assert!(bootstrap.contains("FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK"));
|
|
assert!(bootstrap.contains("COMPOSITE_COMPONENT_ID_LOGGING"));
|
|
assert!(bootstrap.contains("COMPOSITE_COMPONENT_ID_TRANSPORT"));
|
|
assert!(bootstrap.contains("COMPOSITE_COMPONENT_ID_STORE"));
|
|
assert!(bootstrap.contains("LogFilterLevel::Trace"));
|
|
for forbidden in ["HttpTransportPool", "Store::open", "BackfillJobRuntime", "BackfillRequest"] {
|
|
assert!(!bootstrap.contains(forbidden), "bootstrap.rs absorbs another runtime responsibility: {forbidden}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn pre_004_transport_runtime_builds_pool_and_validates_both_required_rpc_methods() {
|
|
let root = app_root();
|
|
let transport = read_text(root.join("src/transport_runtime.rs").as_path());
|
|
assert!(transport.contains("HttpTransportPool::new"));
|
|
assert!(transport.contains("getSignaturesForAddress"));
|
|
assert!(transport.contains("getTransaction"));
|
|
assert!(transport.contains("select_for_method"));
|
|
assert!(transport.contains("configured_networks"));
|
|
assert!(transport.contains("compatible_backfill_http_routes"));
|
|
assert!(transport.contains("endpoint.provider()"));
|
|
for forbidden in ["url()", "Store::open", "BackfillJobRuntime", "BackfillRequest"] {
|
|
assert!(!transport.contains(forbidden), "pre.004 opens or projects forbidden surface {forbidden}");
|
|
}
|
|
let tauri = read_text(root.join("src/tauri.rs").as_path());
|
|
assert!(tauri.contains("backfill_options"));
|
|
}
|
|
|
|
#[test]
|
|
fn pre_005_store_readiness_proves_network_before_open_and_closes_on_main_window_exit() {
|
|
let root = app_root();
|
|
let store = read_text(root.join("src/store_runtime.rs").as_path());
|
|
let coherence = store.find("validate_network_coherence(store_network.as_str(), transport_network.as_str())");
|
|
let open = store.find("ksp_store_lib::Store::open");
|
|
assert!(coherence.is_some());
|
|
assert!(open.is_some());
|
|
if let (std::option::Option::Some(coherence), std::option::Option::Some(open)) = (coherence, open) {
|
|
assert!(coherence < open, "Store network coherence must be proven before physical Store open");
|
|
}
|
|
assert!(store.contains("store.health().await"));
|
|
assert!(store.contains("store.close().await"));
|
|
assert!(store.contains("StoreHealthState::Ready"));
|
|
assert!(store.contains("StoreHealthState::NotReady"));
|
|
assert!(!store.contains("BackfillJobRuntime"));
|
|
assert!(!store.contains("BackfillRequest"));
|
|
let app_state = read_text(root.join("src/app_state.rs").as_path());
|
|
assert!(app_state.contains("initialize_store"));
|
|
assert!(app_state.contains("composition_ready"));
|
|
assert!(app_state.contains("close_store"));
|
|
let tauri = read_text(root.join("src/tauri.rs").as_path());
|
|
for required in ["on_window_event", "WindowEvent::CloseRequested", "prevent_close", "async_runtime::spawn", "close_store", "app_handle.exit(0)"] {
|
|
assert!(tauri.contains(required), "missing bounded Store shutdown lifecycle marker {required}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn pre_006_mainnet_default_and_http_route_selector_are_explicit_without_start_runtime() {
|
|
let root = app_root();
|
|
let workspace = root.join("../..");
|
|
let composite = read_text(workspace.join("config/composite.ksp-app-backfill-desk.json").as_path());
|
|
assert!(composite.contains("\"default_profile\": \"mainnet\""));
|
|
assert!(composite.contains("\"profile_id\": \"mainnet_backfill_pool\""));
|
|
let transport = read_text(workspace.join("config/std.transport.json").as_path());
|
|
for required in ["mainnet_backfill_pool", "backfill_pool", "backfill_publicnode", "backfill_solana_public", "solana-rpc.publicnode.com"] {
|
|
assert!(transport.contains(required), "missing Backfill HTTP route marker {required}");
|
|
}
|
|
let app_state = read_text(root.join("src/app_state.rs").as_path());
|
|
assert!(app_state.contains("pre.006-mainnet-http-routing"));
|
|
let frontend = read_text(root.join("frontend/ts/main.ts").as_path());
|
|
assert!(frontend.contains("Backfill Desk HTTP route selection changed"));
|
|
assert!(frontend.contains("backfill_options"));
|
|
let html = read_text(root.join("frontend/main.html").as_path());
|
|
assert!(html.contains("backfillHttpRoute"));
|
|
for forbidden in ["backfill_start", "BackfillJobRuntime", "grpc", "websocket"] {
|
|
assert!(!frontend.contains(forbidden), "pre.006 frontend opens deferred runtime marker {forbidden}");
|
|
}
|
|
}
|