use llm_toolkit::ToPrompt;
use serde::Serialize;
use serde_json::Value;
#[derive(ToPrompt, Default, Serialize)]
#[prompt(mode = "schema_only")]
struct Concept {
#[prompt(example = "a cinematic, dynamic shot of a futuristic city at night")]
prompt: String,
#[serde(default)]
negative_prompt: Option<String>,
#[prompt(example = "anime")]
style: String,
}
#[test]
fn test_struct_schema_only_mode() {
let concept = Concept {
prompt: "test prompt".to_string(),
negative_prompt: None,
style: "test style".to_string(),
};
let schema = concept.to_prompt_parts_with_mode("schema_only");
assert_eq!(schema.len(), 1);
if let llm_toolkit::prompt::PromptPart::Text(text) = &schema[0] {
assert!(text.contains("type Concept = {"));
assert!(text.contains("A concept for image generation"));
assert!(text.contains("prompt: string;"));
assert!(text.contains("negative_prompt: string | null;"));
assert!(text.contains("style: string;"));
assert!(text.contains("The main idea for the art to be generated"));
assert!(text.contains("Elements to exclude from the generation"));
assert!(text.contains("The style of the generation"));
} else {
panic!("Expected Text variant");
}
}
#[test]
fn test_struct_to_prompt_with_mode() {
let concept = Concept {
prompt: "test prompt".to_string(),
negative_prompt: Some("test negative".to_string()),
style: "test style".to_string(),
};
let schema_str = concept.to_prompt_with_mode("schema_only");
assert!(schema_str.contains("type Concept = {"));
assert!(schema_str.contains("prompt: string;"));
}
#[derive(ToPrompt, Serialize)]
#[prompt(mode = "schema_only")]
struct UserProfile {
id: u64,
name: String,
email: Option<String>,
is_active: bool,
}
#[test]
fn test_struct_without_example_attribute() {
let profile = UserProfile {
id: 123,
name: "Alice".to_string(),
email: Some("alice@example.com".to_string()),
is_active: true,
};
let schema = profile.to_prompt_with_mode("schema_only");
assert!(schema.contains("type UserProfile = {"));
assert!(schema.contains("id: number;"));
assert!(schema.contains("name: string;"));
assert!(schema.contains("email: string | null;"));
assert!(schema.contains("is_active: boolean;"));
}
#[test]
fn test_example_only_mode_with_examples() {
let concept = Concept::default();
let example_str = concept.to_prompt_with_mode("example_only");
let json: Value = serde_json::from_str(&example_str).expect("Invalid JSON");
assert_eq!(
json["prompt"].as_str(),
Some("a cinematic, dynamic shot of a futuristic city at night")
);
assert_eq!(json["style"].as_str(), Some("anime"));
assert_eq!(json["negative_prompt"], Value::Null);
}
#[test]
fn test_full_mode_combines_schema_and_example() {
let concept = Concept::default();
let full_output = concept.to_prompt_with_mode("full");
assert!(full_output.contains("type Concept = {"));
assert!(full_output.contains("### Example"));
assert!(full_output.contains("Here is an example of a valid `Concept` object"));
assert!(full_output.contains("prompt: string;"));
assert!(full_output.contains("negative_prompt: string | null;"));
assert!(full_output.contains("a cinematic, dynamic shot of a futuristic city at night"));
assert!(full_output.contains("anime"));
}
#[derive(ToPrompt, Default, Serialize)]
#[prompt(mode = "schema_only")]
struct ServiceConfig {
#[prompt(example = "my-service")]
name: String,
port: u16,
debug: bool,
}
#[test]
fn test_default_fallback_for_fields_without_example() {
let config = ServiceConfig::default();
let example_str = config.to_prompt_with_mode("example_only");
let json: Value = serde_json::from_str(&example_str).expect("Invalid JSON");
assert_eq!(json["name"].as_str(), Some("my-service"));
assert_eq!(json["port"].as_u64(), Some(0)); assert_eq!(json["debug"].as_bool(), Some(false)); }
#[derive(ToPrompt, Serialize)]
#[prompt(mode = "schema_only")]
struct TaskWithoutDefault {
#[prompt(example = "task-123")]
task_id: String,
priority: u32,
}
#[test]
fn test_struct_without_default_uses_actual_values() {
let task = TaskWithoutDefault {
task_id: "actual-task-456".to_string(),
priority: 5,
};
let example_str = task.to_prompt_with_mode("example_only");
let json: Value = serde_json::from_str(&example_str).expect("Invalid JSON");
assert_eq!(json["task_id"].as_str(), Some("task-123"));
assert_eq!(json["priority"].as_u64(), Some(5));
}