#[cfg(feature = "derive")]
mod tests {
use llm_toolkit::ToPrompt;
use serde::{Deserialize, Serialize};
#[derive(ToPrompt, Serialize, Deserialize, Debug, PartialEq)]
#[serde(tag = "type")]
enum AnalysisResult {
Approved,
NeedsRevision {
reasons: Vec<String>,
severity: String,
},
Rejected { reason: String },
}
#[test]
fn test_struct_variant_schema() {
let schema = AnalysisResult::prompt_schema();
assert!(schema.contains("type AnalysisResult ="));
assert!(schema.contains("| \"Approved\""));
assert!(schema.contains("| { type: \"NeedsRevision\""));
assert!(schema.contains("reasons: string[]"));
assert!(schema.contains("severity: string"));
assert!(schema.contains("| { type: \"Rejected\""));
assert!(schema.contains("reason: string"));
assert!(schema.contains("// Analysis approved"));
assert!(schema.contains("// Analysis needs revision"));
assert!(schema.contains("// Analysis rejected"));
}
#[test]
fn test_struct_variant_instance_to_prompt() {
let approved = AnalysisResult::Approved;
let prompt = approved.to_prompt();
assert_eq!(prompt, "Approved: Analysis approved");
let needs_revision = AnalysisResult::NeedsRevision {
reasons: vec!["Missing data".to_string(), "Invalid format".to_string()],
severity: "High".to_string(),
};
let prompt = needs_revision.to_prompt();
assert!(prompt.contains("NeedsRevision"));
assert!(prompt.contains("reasons"));
assert!(prompt.contains("Missing data"));
assert!(prompt.contains("severity"));
assert!(prompt.contains("High"));
}
#[test]
fn test_struct_variant_serde_roundtrip() {
let original = AnalysisResult::NeedsRevision {
reasons: vec!["Issue 1".to_string()],
severity: "Medium".to_string(),
};
let json = serde_json::to_string(&original).unwrap();
assert!(json.contains("\"type\":\"NeedsRevision\""));
assert!(json.contains("\"reasons\""));
assert!(json.contains("\"severity\""));
let deserialized: AnalysisResult = serde_json::from_str(&json).unwrap();
assert_eq!(original, deserialized);
}
#[derive(ToPrompt, Serialize, Deserialize, Debug, PartialEq)]
#[serde(tag = "type")]
enum LightingTechnique {
Chiaroscuro {
contrast_level: String,
light_source: String,
shadow_direction: String,
},
Rembrandt {
triangle_side: String,
fill_ratio: f32,
},
Natural,
}
#[test]
fn test_mixed_variants_schema() {
let schema = LightingTechnique::prompt_schema();
assert!(schema.contains("type LightingTechnique ="));
assert!(schema.contains("| { type: \"Chiaroscuro\""));
assert!(schema.contains("contrast_level: string"));
assert!(schema.contains("light_source: string"));
assert!(schema.contains("shadow_direction: string"));
assert!(schema.contains("| { type: \"Rembrandt\""));
assert!(schema.contains("triangle_side: string"));
assert!(schema.contains("fill_ratio: number"));
assert!(schema.contains("| \"Natural\""));
assert!(schema.contains("// Chiaroscuro (dramatic high-contrast lighting)"));
assert!(schema.contains("// Rembrandt lighting (triangle of light on cheek)"));
assert!(schema.contains("// Simple natural lighting"));
}
#[test]
fn test_struct_variant_with_rename() {
#[derive(ToPrompt, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
enum Action {
#[prompt(rename = "send_msg")]
SendMessage {
to: String,
content: String,
},
DeleteItem {
id: u64,
},
}
let schema = Action::prompt_schema();
assert!(schema.contains("| { type: \"send_msg\""));
assert!(schema.contains("| { type: \"delete_item\""));
assert!(schema.contains("to: string"));
assert!(schema.contains("content: string"));
assert!(schema.contains("id: number"));
}
#[test]
fn test_struct_variant_with_skip() {
#[derive(ToPrompt, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Command {
Execute {
script: String,
},
#[prompt(skip)]
InternalDebug {
details: String,
},
}
let schema = Command::prompt_schema();
assert!(schema.contains("| { type: \"Execute\""));
assert!(schema.contains("script: string"));
assert!(!schema.contains("InternalDebug"));
assert!(!schema.contains("details"));
}
#[test]
fn test_struct_variant_empty_fields() {
#[derive(ToPrompt, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Event {
Started,
Progress { percent: u8 },
Completed,
}
let schema = Event::prompt_schema();
assert!(schema.contains("| \"Started\""));
assert!(schema.contains("| { type: \"Progress\""));
assert!(schema.contains("percent: number"));
assert!(schema.contains("| \"Completed\""));
}
#[test]
fn test_struct_variant_with_vec() {
#[derive(ToPrompt, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Response {
Success { data: Vec<String> },
Error { messages: Vec<String> },
}
let schema = Response::prompt_schema();
assert!(schema.contains("data: string[]"));
assert!(schema.contains("messages: string[]"));
}
#[test]
fn test_struct_variant_with_option() {
#[derive(ToPrompt, Serialize, Deserialize)]
#[serde(tag = "type")]
enum UserAction {
Login {
username: String,
},
Update {
username: String,
email: Option<String>,
},
}
let schema = UserAction::prompt_schema();
assert!(schema.contains("email: string | null"));
}
#[test]
fn test_struct_variant_number_types() {
#[derive(ToPrompt, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Measurement {
Temperature { celsius: f32 },
Distance { meters: u32 },
Count { items: i64 },
}
let schema = Measurement::prompt_schema();
assert!(schema.contains("celsius: number"));
assert!(schema.contains("meters: number"));
assert!(schema.contains("items: number"));
}
#[test]
fn test_struct_variant_bool_type() {
#[derive(ToPrompt, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Config {
Setting { enabled: bool, name: String },
}
let schema = Config::prompt_schema();
assert!(schema.contains("enabled: boolean"));
assert!(schema.contains("name: string"));
}
}