v0.3.8-pre.002
This commit is contained in:
33
crates/ksp-app-store-desk/tests/dependency_boundary.rs
Normal file
33
crates/ksp-app-store-desk/tests/dependency_boundary.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
// file: crates/ksp-app-store-desk/tests/dependency_boundary.rs
|
||||
// version: 1
|
||||
|
||||
#[test]
|
||||
fn pre_002_manifest_keeps_store_and_transport_runtime_dependencies_out_of_scaffold() {
|
||||
let manifest = include_str!("../Cargo.toml");
|
||||
for forbidden in [
|
||||
"ksp-store-lib",
|
||||
"ksp-store-api",
|
||||
"ksp-store-postgres-lib",
|
||||
"ksp-onchain-transport-lib",
|
||||
"ksp-offchain-transport-lib",
|
||||
"ksp-job-api",
|
||||
"ksp-job-backfill-lib",
|
||||
"reqwest",
|
||||
"tokio-postgres",
|
||||
"deadpool-postgres",
|
||||
] {
|
||||
assert!(!manifest.contains(forbidden), "forbidden pre.002 dependency present: {forbidden}");
|
||||
}
|
||||
for required in ["ksp-config-lib", "ksp-core-lib", "ksp-logging-lib", "tauri-plugin-tracing"] {
|
||||
assert!(manifest.contains(required), "required scaffold dependency missing: {required}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_sources_expose_no_sql_or_physical_store_escape_hatch() {
|
||||
let sources =
|
||||
[include_str!("../src/app_state.rs"), include_str!("../src/bootstrap.rs"), include_str!("../src/tauri.rs"), include_str!("../src/lib.rs")].join("\n");
|
||||
for forbidden in ["Store::open", "tokio_postgres", "deadpool_postgres", "SELECT ", "INSERT ", "UPDATE ", "DELETE ", "ksp_store_api", "ksp_store_postgres"] {
|
||||
assert!(!sources.contains(forbidden), "pre.002 scaffold leaked forbidden Store/runtime surface: {forbidden}");
|
||||
}
|
||||
}
|
||||
92
crates/ksp-app-store-desk/tests/desktop_contract.rs
Normal file
92
crates/ksp-app-store-desk/tests/desktop_contract.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
// file: crates/ksp-app-store-desk/tests/desktop_contract.rs
|
||||
// version: 1
|
||||
|
||||
fn parse_json(source: &str) -> serde_json::Result<serde_json::Value> {
|
||||
serde_json::from_str::<serde_json::Value>(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_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_002_shell_exposes_only_planned_store_desk_views_and_empty_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\""));
|
||||
assert!(html.contains("Aucune capability Store n'est encore invoquée"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_datatables_are_scaffold_only_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}");
|
||||
}
|
||||
}
|
||||
51
crates/ksp-app-store-desk/tests/desktop_security.rs
Normal file
51
crates/ksp-app-store-desk/tests/desktop_security.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
// file: crates/ksp-app-store-desk/tests/desktop_security.rs
|
||||
// version: 1
|
||||
|
||||
fn parse_json(source: &str) -> serde_json::Result<serde_json::Value> {
|
||||
serde_json::from_str::<serde_json::Value>(source)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_capabilities_are_core_and_tracing_only() {
|
||||
let parsed = parse_json(include_str!("../capabilities/default.json"));
|
||||
assert!(parsed.is_ok(), "committed capability JSON must be valid");
|
||||
let capability = match parsed {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let permissions = capability["permissions"].as_array();
|
||||
assert!(permissions.is_some(), "capability permissions must be an array");
|
||||
let permissions = match permissions {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(permissions.len(), 2);
|
||||
assert_eq!(permissions[0], "core:default");
|
||||
assert_eq!(permissions[1], "tracing:default");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_frontend_avoids_network_browser_storage_and_blocking_dialogs() {
|
||||
let frontend = [
|
||||
include_str!("../frontend/ts/frontend_log.ts"),
|
||||
include_str!("../frontend/ts/invoke.ts"),
|
||||
include_str!("../frontend/ts/main.ts"),
|
||||
include_str!("../frontend/ts/splash.ts"),
|
||||
]
|
||||
.join("\n");
|
||||
for forbidden in ["fetch(", "XMLHttpRequest", "localStorage", "sessionStorage", "window.alert", "window.confirm", "window.prompt"] {
|
||||
assert!(!frontend.contains(forbidden), "forbidden frontend primitive present: {forbidden}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_frontend_tracing_covers_navigation_buttons_refresh_and_ipc() {
|
||||
let main = include_str!("../frontend/ts/main.ts");
|
||||
let invoke = include_str!("../frontend/ts/invoke.ts");
|
||||
assert!(main.contains("navigation button clicked"));
|
||||
assert!(main.contains("diagnostics refresh button clicked"));
|
||||
assert!(main.contains("view activated"));
|
||||
assert!(invoke.contains("IPC command requested"));
|
||||
assert!(invoke.contains("IPC command completed"));
|
||||
assert!(invoke.contains("IPC command failed"));
|
||||
}
|
||||
8
crates/ksp-app-store-desk/tests/public_api.rs
Normal file
8
crates/ksp-app-store-desk/tests/public_api.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
// file: crates/ksp-app-store-desk/tests/public_api.rs
|
||||
// version: 1
|
||||
|
||||
#[test]
|
||||
fn pre_002_public_surface_exposes_only_application_run_entry_point() {
|
||||
let run: fn(&[std::ffi::OsString]) -> ksp_core_lib::Result<()> = ksp_app_store_desk_lib::run;
|
||||
let _ = run;
|
||||
}
|
||||
Reference in New Issue
Block a user