test(saas): Phase 1 integration tests — billing + scheduled_task + knowledge (68 tests)
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

- Fix TIMESTAMPTZ decode errors: add ::TEXT cast to all SELECT queries
  where Row structs use String for TIMESTAMPTZ columns (~22 locations)
- Fix Axum 0.7 route params: {id} → :id in billing/knowledge/scheduled_task routes
- Fix JSONB bind: scheduled_task INSERT uses ::jsonb cast for input_payload
- Add billing_test.rs (14 tests): plans, subscription, usage, payments, invoices
- Add scheduled_task_test.rs (12 tests): CRUD, validation, isolation
- Add knowledge_test.rs (20 tests): categories, items, versions, search, analytics, permissions
- Fix auth test regression: 6 tests were failing due to TIMESTAMPTZ type mismatch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-04-07 14:25:34 +08:00
parent a5b887051d
commit 7de486bfca
27 changed files with 1317 additions and 187 deletions

View File

@@ -149,7 +149,10 @@ fn build_router(state: AppState) -> Router {
use tower_http::trace::TraceLayer;
let public_routes = zclaw_saas::auth::routes()
.route("/api/health", axum::routing::get(health_handler));
.route("/api/health", axum::routing::get(health_handler))
.merge(zclaw_saas::billing::callback_routes())
.merge(zclaw_saas::billing::mock_routes())
.merge(zclaw_saas::billing::plan_routes());
let protected_routes = zclaw_saas::auth::protected_routes()
.merge(zclaw_saas::account::routes())
@@ -160,6 +163,9 @@ fn build_router(state: AppState) -> Router {
.merge(zclaw_saas::prompt::routes())
.merge(zclaw_saas::agent_template::routes())
.merge(zclaw_saas::telemetry::routes())
.merge(zclaw_saas::billing::protected_routes())
.merge(zclaw_saas::knowledge::routes())
.merge(zclaw_saas::scheduled_task::routes())
.layer(middleware::from_fn_with_state(
state.clone(),
zclaw_saas::middleware::api_version_middleware,
@@ -313,6 +319,14 @@ pub async fn send(app: &Router, req: Request<Body>) -> (StatusCode, serde_json::
(status, json)
}
/// Send request and return (status, body_string). For non-JSON responses (HTML, plain text).
pub async fn send_raw(app: &Router, req: Request<Body>) -> (StatusCode, String) {
let resp = app.clone().oneshot(req).await.unwrap();
let status = resp.status();
let bytes = body_bytes(resp.into_body()).await;
(status, String::from_utf8_lossy(&bytes).to_string())
}
// ── Auth helpers ─────────────────────────────────────────────────
/// Register a new user. Returns (access_token, refresh_token, response_json).
@@ -332,7 +346,7 @@ pub async fn register(
.unwrap();
let status = resp.status();
let json = body_json(resp.into_body()).await;
assert_eq!(status, StatusCode::CREATED, "register failed: {json}");
assert_eq!(status, StatusCode::OK, "register failed: {json}");
let token = json["token"].as_str().unwrap().to_string();
let refresh = json["refresh_token"].as_str().unwrap().to_string();
(token, refresh, json)