#![allow(unused_imports)]
mod admin_tests {
#![allow(clippy::unwrap_used)] use super::super::admin::*;
#[test]
fn test_extract_bearer_token_valid() {
assert_eq!(extract_bearer_token(Some("Bearer abc123")), Some("abc123"));
}
#[test]
fn test_extract_bearer_token_no_header() {
assert_eq!(extract_bearer_token(None), None);
}
#[test]
fn test_extract_bearer_token_wrong_scheme() {
assert_eq!(extract_bearer_token(Some("Basic abc")), None);
}
#[test]
fn test_admin_health_response_serializes() {
let resp = AdminHealthResponse {
uptime_secs: 10,
version: "test".to_string(),
pool_active: Some(1),
pool_idle: Some(4),
pool_max: Some(5),
cache_hit_rate: Some(0.8),
cache_entries: Some(100),
};
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("uptime_secs"));
assert!(json.contains("cache_hit_rate"));
}
#[test]
fn test_admin_schema_response_serializes() {
let resp = AdminSchemaResponse {
schema: serde_json::json!({"types": []}),
};
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"schema\""));
}
}
mod auth_users_tests {
#![allow(clippy::unwrap_used)] use super::super::auth_users::*;
#[test]
fn test_user_list_response_serializes() {
let resp = UserListResponse {
users: vec![],
total: 0,
page: 1,
page_size: 50,
};
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"users\""));
}
#[test]
fn test_user_invite_request_parses() {
let input = r#"{"email":"a@b.com"}"#;
let req: UserInviteRequest = serde_json::from_str(input).unwrap();
assert_eq!(req.email, "a@b.com");
}
}
mod data_tests {
#![allow(clippy::unwrap_used)] use super::super::data::*;
#[test]
fn test_data_query_response_serializes() {
let resp = DataQueryResponse {
rows: vec![serde_json::json!({"id": 1})],
total: 1,
page: 1,
page_size: 50,
};
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"rows\""));
assert!(json.contains("\"total\""));
}
#[test]
fn test_filter_op_round_trips() {
for (raw, expected) in [
("\"eq\"", FilterOp::Eq),
("\"contains\"", FilterOp::Contains),
] {
let op: FilterOp = serde_json::from_str(raw).unwrap();
assert_eq!(op, expected);
}
}
#[test]
fn test_defaults() {
let q: DataBrowserQuery = serde_json::from_str("{}").unwrap();
assert_eq!(q.page, 1);
assert_eq!(q.page_size, 50);
}
}
mod function_ops_tests {
#![allow(clippy::unwrap_used)] use super::super::function_ops::*;
#[test]
fn test_function_list_serializes() {
let resp = FunctionListResponse { functions: vec![] };
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"functions\""));
}
#[test]
fn test_secret_set_request_parses() {
let input = r#"{"value":"s3cr3t"}"#;
let req: SecretSetRequest = serde_json::from_str(input).unwrap();
assert_eq!(req.value, "s3cr3t");
}
}
mod metrics_summary_tests {
#![allow(clippy::unwrap_used)] #![allow(clippy::float_cmp)] use std::sync::atomic::Ordering;
use super::super::metrics_summary::*;
use crate::metrics_server::MetricsCollector;
#[test]
fn test_metrics_summary_serializes() {
let m = MetricsSummary::zero();
let json = serde_json::to_string(&m).unwrap();
assert!(json.contains("\"latency\""));
assert!(json.contains("\"p50_ms\""));
assert!(json.contains("\"errors\""));
assert!(json.contains("\"pool\""));
assert!(json.contains("\"cache\""));
assert!(json.contains("\"subscriptions\""));
assert!(json.contains("\"pool\":null"), "unmeasured pool must be null: {json}");
assert!(
json.contains("\"subscriptions\":null"),
"unmeasured subscription count must be null: {json}"
);
}
#[test]
fn test_build_summary_latency_from_histogram() {
let collector = MetricsCollector::new();
for _ in 0..100 {
collector.http_request_duration.observe_us(4_000);
}
for _ in 0..5 {
collector.http_request_duration.observe_us(80_000);
}
let summary = build_summary(&collector);
assert_eq!(summary.latency.p50_ms, 5);
assert_eq!(summary.latency.p99_ms, 100);
}
#[test]
fn test_build_summary_empty_histogram_returns_zero() {
let collector = MetricsCollector::new();
let summary = build_summary(&collector);
assert_eq!(summary.latency.p50_ms, 0);
assert_eq!(summary.latency.p95_ms, 0);
assert_eq!(summary.latency.p99_ms, 0);
}
#[test]
fn test_build_summary_error_rate() {
let collector = MetricsCollector::new();
collector.queries_total.store(100, Ordering::Relaxed);
collector.queries_error.store(10, Ordering::Relaxed);
let summary = build_summary(&collector);
assert!((summary.errors.lifetime - 0.1).abs() < f64::EPSILON);
assert_eq!(summary.errors.rate_5m, None);
assert_eq!(summary.errors.rate_1h, None);
assert_eq!(summary.errors.rate_24h, None);
}
#[test]
fn test_build_summary_cache_hit_rate() {
let collector = MetricsCollector::new();
collector.cache_hits.store(75, Ordering::Relaxed);
collector.cache_misses.store(25, Ordering::Relaxed);
let summary = build_summary(&collector);
assert!((summary.cache.hit_rate - 0.75).abs() < f64::EPSILON);
}
#[test]
fn test_build_summary_zero_division_safe() {
let collector = MetricsCollector::new();
let summary = build_summary(&collector);
assert_eq!(summary.errors.lifetime, 0.0);
assert_eq!(summary.cache.hit_rate, 0.0);
}
}
mod mod_tests {
use super::super::{mime_for_filename, studio_shell_html};
#[test]
fn test_shell_contains_l_tabs() {
let html = studio_shell_html();
assert!(html.contains("<l-tabs"), "shell must contain <l-tabs>");
}
#[test]
fn test_shell_contains_all_sections() {
let html = studio_shell_html();
for s in [
"Schema",
"Data",
"Auth",
"Storage",
"Functions",
"Observers",
"Logs",
"Metrics",
] {
assert!(html.contains(s), "shell must contain section '{s}'");
}
}
#[test]
fn spa_wires_every_tab_to_its_admin_endpoint() {
const APP_TS: &str = include_str!("../../../studio/src/app.ts");
for (section, endpoint) in [
("renderSchema", "/admin/v1/schema"),
("renderObservers", "/api/observers/dlq"),
("renderObservers", "/api/observers/delivery/health"),
("renderLogs", "/api/observers/logs"),
("renderData", "/admin/v1/schema"),
("renderAuth", "/admin/v1/users"),
("renderStorage", "/admin/v1/storage/buckets"),
("renderFunctions", "/admin/v1/functions"),
("renderMetrics", "/admin/v1/metrics/summary"),
] {
assert!(APP_TS.contains(section), "SPA must define {section}");
assert!(APP_TS.contains(endpoint), "SPA must call {endpoint}");
}
assert!(APP_TS.contains("/retry"), "SPA must wire the DLQ retry action");
assert!(APP_TS.contains("dlq/retry-all"), "SPA must wire retry-all");
for tab in [
"schema",
"data",
"auth",
"storage",
"functions",
"observers",
"logs",
"metrics",
] {
assert!(
APP_TS.contains(&format!("{tab}:")) || APP_TS.contains(&format!("{tab}: ")),
"SECTIONS must route tab '{tab}'"
);
}
}
#[test]
fn test_shell_references_app_js() {
let html = studio_shell_html();
assert!(html.contains("app.js"), "shell must reference app.js");
}
#[test]
fn test_mime_for_js() {
assert!(mime_for_filename("app.js").contains("javascript"));
}
#[test]
fn test_mime_for_css() {
assert!(mime_for_filename("app.css").contains("css"));
}
}
mod storage_browser_tests {
#![allow(clippy::unwrap_used)] use super::super::storage_browser::*;
#[test]
fn test_object_list_response_serializes() {
let resp = ObjectListResponse {
objects: vec![],
total: 0,
page: 1,
page_size: 50,
};
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"objects\""));
}
#[test]
fn test_presign_request_parses() {
let input = r#"{"bucket":"b","key":"k","expires_in_secs":60}"#;
let req: PresignRequest = serde_json::from_str(input).unwrap();
assert_eq!(req.bucket, "b");
assert_eq!(req.expires_in_secs, 60);
}
}