Files
zclaw_openfang/crates/zclaw-saas/tests/prompt_test.rs
iven 5fdf96c3f5 chore: 提交所有工作进度 — SaaS 后端增强、Admin UI、桌面端集成
包含大量 SaaS 平台改进、Admin 管理后台更新、桌面端集成完善、
文档同步、测试文件重构等内容。为 QA 测试准备干净工作树。
2026-03-29 10:46:41 +08:00

175 lines
6.7 KiB
Rust

mod common;
use axum::http::StatusCode;
use common::*;
// ═══════════════════════════════════════════════════════════════════
// OTA check
// ═══════════════════════════════════════════════════════════════════
#[tokio::test]
async fn prompt_ota_check() {
let (app, _pool) = build_test_app().await;
let token = register_token(&app, "otacheck").await;
let (status, body) = send(
&app,
post(
"/api/v1/prompts/check",
&token,
serde_json::json!({
"device_id": "test-device-001",
"versions": { "reflection": 0, "compaction": 0, "extraction": 0 }
}),
),
).await;
assert_eq!(status, StatusCode::OK);
assert!(body["updates"].is_array());
assert!(body["server_time"].is_string());
// 3 builtin templates should have updates
assert_eq!(body["updates"].as_array().unwrap().len(), 3);
}
// ═══════════════════════════════════════════════════════════════════
// Prompt list (admin only)
// ═══════════════════════════════════════════════════════════════════
#[tokio::test]
async fn prompt_list_requires_permission() {
let (app, _pool) = build_test_app().await;
let token = register_token(&app, "promptuser").await;
let (status, _) = send(&app, get("/api/v1/prompts", &token)).await;
// Regular user has prompt:read via user role → may succeed or fail based on permissions
// User role has prompt:read → should succeed
assert_eq!(status, StatusCode::OK);
}
#[tokio::test]
async fn prompt_list_shows_builtins() {
let (app, pool) = build_test_app().await;
let admin = admin_token(&app, &pool, "promptlist").await;
let (status, body) = send(&app, get("/api/v1/prompts", &admin)).await;
assert_eq!(status, StatusCode::OK);
let items = body["items"].as_array().unwrap_or_else(|| {
// Fallback: some handlers may return bare array
body.as_array().unwrap()
});
assert!(items.len() >= 3, "should have 3 builtin templates, got {}: {body}", items.len());
}
// ═══════════════════════════════════════════════════════════════════
// Prompt CRUD
// ═══════════════════════════════════════════════════════════════════
#[tokio::test]
async fn prompt_create_and_get() {
let (app, pool) = build_test_app().await;
let admin = admin_token(&app, &pool, "promptcreate").await;
// Create
let (status, body) = send(
&app,
post(
"/api/v1/prompts",
&admin,
serde_json::json!({
"name": "test-prompt",
"category": "test",
"description": "A test prompt",
"system_prompt": "You are a test assistant.",
"user_prompt_template": "Hello {{name}}",
"variables": [{ "name": "name", "required": true }]
}),
),
).await;
assert_eq!(status, StatusCode::OK, "create prompt: {body}");
// Get by name
let (status, body) = send(&app, get("/api/v1/prompts/test-prompt", &admin)).await;
assert_eq!(status, StatusCode::OK);
assert_eq!(body["name"], "test-prompt");
// Update metadata
let (status, body) = send(
&app,
put(
"/api/v1/prompts/test-prompt",
&admin,
serde_json::json!({ "description": "Updated description" }),
),
).await;
assert_eq!(status, StatusCode::OK);
assert_eq!(body["description"], "Updated description");
}
// ═══════════════════════════════════════════════════════════════════
// Prompt versions
// ═══════════════════════════════════════════════════════════════════
#[tokio::test]
async fn prompt_version_publish_and_list() {
let (app, pool) = build_test_app().await;
let admin = admin_token(&app, &pool, "promptver").await;
// Create template first
send(
&app,
post(
"/api/v1/prompts",
&admin,
serde_json::json!({
"name": "versioned-prompt",
"category": "test",
"system_prompt": "Version 1 system prompt"
}),
),
).await;
// Publish a new version
let (status, body) = send(
&app,
post(
"/api/v1/prompts/versioned-prompt/versions",
&admin,
serde_json::json!({
"system_prompt": "Version 2 system prompt",
"changelog": "Updated for testing"
}),
),
).await;
assert_eq!(status, StatusCode::OK, "publish version: {body}");
// List versions
let (status, body) = send(&app, get("/api/v1/prompts/versioned-prompt/versions", &admin)).await;
assert_eq!(status, StatusCode::OK);
assert!(body.is_array());
assert!(body.as_array().unwrap().len() >= 2);
}
// ═══════════════════════════════════════════════════════════════════
// Prompt archive
// ═══════════════════════════════════════════════════════════════════
#[tokio::test]
async fn prompt_archive() {
let (app, pool) = build_test_app().await;
let sa = super_admin_token(&app, &pool, "promptarchive").await;
// Create
send(
&app,
post(
"/api/v1/prompts",
&sa,
serde_json::json!({
"name": "to-archive",
"category": "test",
"system_prompt": "Will be archived"
}),
),
).await;
// Archive (delete)
let (status, _) = send(&app, delete("/api/v1/prompts/to-archive", &sa)).await;
assert_eq!(status, StatusCode::OK);
}