use serde::Deserialize;
use tryparse::parse;
#[derive(Deserialize, Debug, PartialEq)]
struct User {
name: String,
age: u32,
}
#[test]
fn test_json_in_prose() {
let response = r#"
Sure! Here's the user data: {"name": "Alice", "age": 30}
Hope that helps!
"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should extract JSON from prose");
}
#[test]
#[ignore] fn test_multiple_json_objects() {
let response = r#"
{"name": "Alice", "age": 30}
{"name": "Bob", "age": 25}
"#;
let result: Result<Vec<User>, _> = parse(response);
assert!(result.is_ok(), "Should handle multiple JSON objects");
}
#[test]
fn test_truncated_json() {
let response = r#"{"name": "Alice", "age": 30"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should close unclosed braces");
}
#[test]
fn test_block_comments() {
let response = r#"{"name": "Alice" /* this is her name */, "age": 30}"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should remove block comments");
}
#[test]
fn test_smart_quotes() {
let response = r#"{"name": "Alice", "age": 30}"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should normalize Unicode quotes");
}
#[test]
fn test_missing_commas() {
let response = r#"{"name": "Alice" "age": 30}"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should add missing commas");
}
#[test]
#[ignore] fn test_case_insensitive_fields() {
let response = r#"{"Name": "Alice", "AGE": 30}"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should match fields case-insensitively");
}
#[test]
fn test_json_in_long_prose() {
let response = r#"
Well, let me think about this. The user you're asking about is quite interesting.
They have been with us for a while. Actually, I should give you their data.
The information is {"name": "Alice", "age": 30} as you can see.
Let me know if you need anything else about this user or other users.
"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should extract JSON from rambling text");
}
#[test]
#[ignore] fn test_multiple_issues_combined() {
let response = r#"{name: 'Alice', age: 30,"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should handle multiple issues at once");
}
#[test]
#[cfg(feature = "yaml")]
fn test_yaml_style() {
let response = r#"
name: Alice
age: 30
"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should parse YAML-style simple objects");
let user = result.unwrap();
assert_eq!(user.name, "Alice");
assert_eq!(user.age, 30);
}
#[test]
#[cfg(not(feature = "yaml"))]
#[ignore] fn test_yaml_style() {
let response = r#"
name: Alice
age: 30
"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should parse YAML-style simple objects");
}
#[test]
#[ignore] fn test_garbage_characters() {
let response = r#"```json
{
"name": "Alice",,,,
"age": 30
}
```"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should handle extra commas/garbage");
}
#[test]
#[ignore] fn test_nested_errors() {
#[derive(Deserialize, Debug)]
#[allow(dead_code)]
struct Company {
name: String,
users: Vec<User>,
}
let response = r#"{
"name": "ACME",
"users": [
{name: "Alice", age: 30},
{name: 'Bob', age: '25'}
]
}"#;
let result: Result<Company, _> = parse(response);
assert!(result.is_ok(), "Should fix errors at any nesting level");
}
#[test]
fn test_excessive_whitespace() {
let response = r#"
{
"name" : "Alice" ,
"age" : 30
}
"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should handle excessive whitespace");
}
#[test]
fn test_string_numbers() {
let response = r#"{"name": "Alice", "age": "30"}"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok(), "Should coerce string numbers");
assert_eq!(result.unwrap().age, 30);
}
#[test]
fn test_empty_response() {
let response = "";
let result: Result<User, _> = parse(response);
assert!(result.is_err(), "Should fail gracefully on empty input");
}
#[test]
#[ignore] fn test_llm_error_message() {
let response = "I'm sorry, I cannot provide that information.";
let result: Result<User, _> = parse(response);
assert!(result.is_err(), "Should fail on non-JSON responses");
}
#[test]
#[ignore] fn test_array_for_object() {
let response = r#"["Alice", 30]"#;
let result: Result<User, _> = parse(response);
assert!(result.is_err(), "Should fail but with clear error");
}
#[test]
fn test_markdown_json_block() {
let response = r#"
```json
{"name": "Alice", "age": 30}
```
"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok());
}
#[test]
fn test_trailing_commas() {
let response = r#"{"name": "Alice", "age": 30,}"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok());
}
#[test]
fn test_single_quotes() {
let response = r#"{'name': 'Alice', 'age': 30}"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok());
}
#[test]
fn test_unquoted_keys() {
let response = r#"{name: "Alice", age: 30}"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok());
}
#[test]
fn test_line_comments() {
let response = r#"{"name": "Alice", "age": 30} // the user"#;
let result: Result<User, _> = parse(response);
assert!(result.is_ok());
}