type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>;
use crate::_test_support::{assert_contains, assert_not_contains, eval_lua, setup_lua};
use crate::script::aip_modules;
use serde_json::json;
use value_ext::JsonValueExt as _;
#[tokio::test]
async fn test_script_lua_json_parse_simple() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local content = '{"name": "John", "age": 30}'
return aip.json.parse(content)
"#;
let res = eval_lua(&lua, script)?;
assert_eq!(res.x_get_str("name")?, "John");
assert_eq!(res.x_get_i64("age")?, 30);
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_parse_with_comment() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local content = [[
// Some comment
{"name": "John", "age": 30}
]]
return aip.json.parse(content)
"#;
let res = eval_lua(&lua, script)?;
assert_eq!(res.x_get_str("name")?, "John");
assert_eq!(res.x_get_i64("age")?, 30);
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_parse_nil() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
return aip.json.parse(nil)
"#;
let res = eval_lua(&lua, script)?;
assert!(res.is_null());
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_parse_invalid() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local ok, err = pcall(function()
local content = "{invalid_json}"
return aip.json.parse(content)
end)
if ok then
return "should not reach here"
else
return err
end
"#;
let res = eval_lua(&lua, script);
let Err(err) = res else {
panic!("Expected error, got {res:?}");
};
let err_str = err.to_string();
assert_contains(&err_str, "json.parse failed");
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_parse_ndjson_simple() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local content = '{"name": "John", "age": 30}\n{"name": "Jane", "age": 25}'
return aip.json.parse_ndjson(content)
"#;
let res = eval_lua(&lua, script)?;
let expected = json!([
{"name": "John", "age": 30},
{"name": "Jane", "age": 25}
]);
assert_eq!(res, expected);
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_parse_ndjson_empty_lines() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local content = '{"id": 1}\n\n{"id": 2}\n \n{"id": 3}'
return aip.json.parse_ndjson(content)
"#;
let res = eval_lua(&lua, script)?;
let expected = json!([
{"id": 1},
{"id": 2},
{"id": 3}
]);
assert_eq!(res, expected);
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_parse_ndjson_nil() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
return aip.json.parse_ndjson(nil)
"#;
let res = eval_lua(&lua, script)?;
assert!(res.is_null());
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_parse_ndjson_invalid_json() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local ok, err = pcall(function()
local content = '{"id": 1}\n{invalid_json}\n{"id": 3}'
return aip.json.parse_ndjson(content)
end)
if ok then
return "should not reach here"
else
return err
end
"#;
let res = eval_lua(&lua, script);
let Err(err) = res else {
panic!("Expected error, got {res:?}");
};
let err_str = err.to_string();
assert_contains(&err_str, "aip.json.parse_ndjson failed");
assert_contains(&err_str, "line 2");
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_stringify_pretty_basic() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local obj = {
name = "John",
age = 30
}
return aip.json.stringify_pretty(obj)
"#;
let res = eval_lua(&lua, script)?;
let result = res.as_str().ok_or("Expected string result")?;
let parsed: serde_json::Value = serde_json::from_str(result)?;
assert_eq!(parsed["name"], "John");
assert_eq!(parsed["age"], 30);
assert!(result.contains('\n'), "Expected pretty formatting with newlines");
assert!(result.contains(" "), "Expected pretty formatting with indentation");
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_stringify_pretty_complex() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local obj = {
name = "John",
age = 30,
address = {
street = "123 Main St",
city = "New York"
},
hobbies = {"reading", "gaming"}
}
return aip.json.stringify_pretty(obj)
"#;
let res = eval_lua(&lua, script)?;
let result = res.as_str().ok_or("Expected string result")?;
let parsed: serde_json::Value = serde_json::from_str(result)?;
assert_eq!(parsed["name"], "John");
assert_eq!(parsed["age"], 30);
assert_eq!(parsed["address"]["street"], "123 Main St");
assert_eq!(parsed["hobbies"][0], "reading");
assert!(result.contains('\n'), "Expected pretty formatting with newlines");
assert!(result.contains(" "), "Expected pretty formatting with indentation");
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_stringify_simple() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local obj = {
name = "John",
age = 30,
address = {
street = "123 Main St",
city = "New York"
},
hobbies = {"reading", "gaming"}
}
return aip.json.stringify(obj)
"#;
let res = eval_lua(&lua, script)?;
let result = res.as_str().ok_or("Expected string result")?;
assert_contains(result, r#""name":"John""#);
assert_not_contains(result, "\n");
assert_not_contains(result, " ");
Ok(())
}
#[tokio::test]
async fn test_script_lua_json_stringify_to_line_alias() -> Result<()> {
let lua = setup_lua(aip_modules::aip_json::init_module, "json").await?;
let script = r#"
local obj = {
name = "John",
age = 30,
address = {
street = "123 Main St",
city = "New York"
},
hobbies = {"reading", "gaming"}
}
return aip.json.stringify_to_line(obj)
"#;
let res = eval_lua(&lua, script)?;
let result = res.as_str().ok_or("Expected string result")?;
assert_contains(result, r#""name":"John""#);
assert_not_contains(result, "\n");
assert_not_contains(result, " ");
Ok(())
}