// file: crates/ksp-app-store-desk/tests/desktop_contract.rs // version: 3 //! Desktop template and frontend contract tests for the Store Desk scaffold. fn parse_json(source: &str) -> serde_json::Result { return serde_json::from_str::(source); } #[test] fn pre_002_tauri_package_and_ports_match_store_desk_identity() { let parsed = parse_json(include_str!("../tauri.conf.json")); assert!(parsed.is_ok(), "committed Tauri JSON must be valid"); let config = match parsed { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(config["productName"], "KSP Store Desk"); assert_eq!(config["identifier"], "com.sasedev.ksp-app-store-desk"); assert_eq!(config["build"]["devUrl"], "http://localhost:1438"); assert!(config.get("version").is_none()); let vite = include_str!("../vite.config.ts"); assert!(vite.contains("port: 1438")); assert!(vite.contains("strictPort: true")); assert!(vite.contains("port: 1439")); } #[test] fn pre_002_fix_001_vite_config_matches_ksp_desk_template_except_identity_ports_and_header() { let store = include_str!("../vite.config.ts") .replace("crates/ksp-app-store-desk/vite.config.ts", "crates/ksp-app-backfill-desk/vite.config.ts") .replace("// version: 2", "// version: 1") .replace("ksp-app-store-desk", "ksp-app-backfill-desk") .replace("1438", "1436") .replace("1439", "1437"); let reference = include_str!("../../ksp-app-backfill-desk/vite.config.ts"); assert_eq!(store, reference); } #[test] fn pre_002_frontend_dependency_baseline_is_ksp_owned_and_select_free() { let parsed = parse_json(include_str!("../package.json")); assert!(parsed.is_ok(), "committed package JSON must be valid"); let package = match parsed { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let dependencies = &package["dependencies"]; for required in [ "@fltsci/tauri-plugin-tracing", "@fortawesome/fontawesome-free", "@tauri-apps/api", "bootstrap", "datatables.net-bs5", "resize-observer-polyfill", "simplebar", ] { assert!(dependencies.get(required).is_some(), "required frontend dependency missing: {required}"); } assert!(dependencies.get("datatables.net-select-bs5").is_none()); let dev_dependencies = &package["devDependencies"]; let expected = ["@tauri-apps/cli", "@types/bootstrap", "@types/node", "sass-embedded", "typescript", "vite"]; let count = match dev_dependencies.as_object() { std::option::Option::Some(value) => value.len(), std::option::Option::None => 0, }; assert_eq!(count, expected.len()); for dependency in expected { assert!(dev_dependencies.get(dependency).is_some(), "required dev dependency missing: {dependency}"); } } #[test] fn pre_002_binary_assets_reuse_the_ksp_desktop_template_byte_exact() { assert_eq!(include_bytes!("../frontend/imgs/logo.png"), include_bytes!("../../ksp-app-backfill-desk/frontend/imgs/logo.png")); assert_eq!(include_bytes!("../frontend/imgs/splash.png"), include_bytes!("../../ksp-app-backfill-desk/frontend/imgs/splash.png")); assert_eq!(include_bytes!("../frontend/fonts/DOS_Amazigh.ttf"), include_bytes!("../../ksp-app-backfill-desk/frontend/fonts/DOS_Amazigh.ttf")); assert_eq!(include_bytes!("../icons/favicon.png"), include_bytes!("../../ksp-app-backfill-desk/icons/favicon.png")); assert_eq!(include_bytes!("../icons/favicon.ico"), include_bytes!("../../ksp-app-backfill-desk/icons/favicon.ico")); } #[test] fn pre_006_shell_exposes_planned_views_store_overview_and_unconnected_raw_table_skeletons() { let html = include_str!("../frontend/main.html"); for view in ["overview", "transactions", "accounts", "diagnostics"] { assert!(html.contains(&format!("data-view=\"{view}\""))); assert!(html.contains(&format!("data-view-panel=\"{view}\""))); } assert!(html.contains("id=\"rawTransactionsTable\"")); assert!(html.contains("id=\"rawAccountsTable\"")); for overview_id in ["refreshOverview", "overviewStoreProfile", "overviewStoreTarget", "overviewStoreHealth", "overviewStorePool", "overviewStoreMigration"] { assert!(html.contains(&format!("id=\"{overview_id}\"")), "missing Store Overview field: {overview_id}"); } assert!(html.contains("jusqu'à pre.007")); assert!(html.contains("jusqu'à pre.008")); } #[test] fn pre_006_datatables_remain_unconnected_with_one_pager_owner_and_no_store_pager() { let source = include_str!("../frontend/ts/main.ts"); assert!(source.contains("datatables.net-bs5")); assert!(source.contains("paging: true")); assert!(source.contains("pageLength: 25")); assert!(source.contains("lengthMenu: [25, 50, 100]")); assert!(source.contains("serverSide: false")); let html = include_str!("../frontend/main.html"); for forbidden in ["Premier", "Précédent", "Suivant", "storePager", "store-pagination"] { assert!(!html.contains(forbidden), "second Store pager marker present: {forbidden}"); } } #[test] fn pre_006_composite_and_packaged_resources_cover_store_desk_and_the_complete_config_registry() { let composite = parse_json(include_str!("../../../config/composite.ksp-app-store-desk.json")); assert!(composite.is_ok(), "Store Desk composite JSON must be valid"); if let std::result::Result::Ok(composite) = composite { assert_eq!(composite["default_profile"], "mainnet"); let profiles = composite["profiles"].as_array(); assert!(profiles.is_some()); if let std::option::Option::Some(profiles) = profiles { assert_eq!(profiles.len(), 3); for profile in profiles { let documents = profile["documents"].as_array(); assert!(documents.is_some()); if let std::option::Option::Some(documents) = documents { assert_eq!(documents.len(), 2); assert_eq!(documents[0]["component_id"], "logging"); assert_eq!(documents[0]["file_id"], "cfg.std.logging"); assert_eq!(documents[0]["profile_id"], "supertrace"); assert_eq!(documents[1]["component_id"], "store"); assert_eq!(documents[1]["file_id"], "cfg.std.store"); assert_eq!(documents[1]["profile_id"], profile["profile_id"]); } } } } let tauri = parse_json(include_str!("../tauri.conf.json")); assert!(tauri.is_ok(), "Store Desk Tauri JSON must be valid"); if let std::result::Result::Ok(tauri) = tauri { let resources = tauri["bundle"]["resources"].as_object(); assert!(resources.is_some()); if let std::option::Option::Some(resources) = resources { assert_eq!(resources.len(), 15); assert!(resources.contains_key("../../config/composite.ksp-app-store-desk.json")); assert!(resources.contains_key("../../config/std.store.json")); assert!(resources.contains_key("../../config/schemas/std.store.schema.json")); } } } #[test] fn pre_006_store_lifecycle_is_composite_managed_health_visible_and_bounded_on_window_close() { let bootstrap = include_str!("../src/bootstrap.rs"); let store = include_str!("../src/store_runtime.rs"); let tauri = include_str!("../src/tauri.rs"); assert!(bootstrap.contains("FILE_ID_COMPOSITE_KSP_APP_STORE_DESK")); assert!(bootstrap.contains("COMPOSITE_COMPONENT_ID_STORE")); assert!(store.contains("ksp_store_lib::Store::open")); assert!(store.contains("store.runtime_snapshot()")); assert!(store.contains("store.health().await")); assert!(store.contains("store.close().await")); assert!(tauri.contains("CloseRequested")); assert!(tauri.contains("api.prevent_close()")); assert!(tauri.contains("begin_shutdown")); assert!(tauri.contains("close_store().await")); assert!(tauri.contains("app_handle.exit(0)")); assert!(tauri.contains("store_runtime_status")); }