use super::setup::{GoValueContext, native_go_dto_literal};
use crate::core::ir::{FieldDef, TypeDef, TypeRef};
fn json_field_owner(optional: bool) -> [TypeDef; 1] {
[TypeDef {
name: "ResponseFormat".into(),
fields: vec![FieldDef {
name: "schema".into(),
ty: TypeRef::Json,
optional,
..FieldDef::default()
}],
..TypeDef::default()
}]
}
fn render_response_format(value: serde_json::Value, types: &[TypeDef]) -> Option<String> {
native_go_dto_literal(
&value,
"ResponseFormat",
GoValueContext {
import_alias: "sample",
type_defs: types,
enums: &[],
files: &[],
},
)
.expect("no refusal")
}
#[test]
fn renders_json_typed_field_as_a_raw_message_conversion() {
let types = json_field_owner(false);
let rendered = render_response_format(
serde_json::json!({"schema": {"type": "object", "required": ["name"]}}),
&types,
)
.expect("native DTO");
assert!(
rendered.contains("Schema: json.RawMessage(`{\"required\":[\"name\"],\"type\":\"object\"}`)"),
"the schema itself must appear in the literal, not be dropped: {rendered}"
);
assert!(
!rendered.contains("sample.ResponseFormat{}"),
"the only field must not be dropped, leaving an empty literal: {rendered}"
);
}
#[test]
fn renders_optional_json_typed_field_through_the_pointer_helper() {
let types = json_field_owner(true);
let rendered =
render_response_format(serde_json::json!({"schema": {"type": "object"}}), &types).expect("native DTO");
assert!(
rendered.contains("Schema: ptr(json.RawMessage(`{\"type\":\"object\"}`))"),
"{rendered}"
);
}
#[test]
fn omits_a_null_json_typed_field() {
let types = json_field_owner(false);
let rendered = render_response_format(serde_json::json!({"schema": null}), &types).expect("native DTO");
assert_eq!(rendered, "sample.ResponseFormat{}", "{rendered}");
}
#[test]
fn renders_nested_file_pointer_as_byte_read() {
let types = [TypeDef {
name: "Upload".into(),
fields: vec![FieldDef {
name: "content".into(),
ty: TypeRef::Bytes,
..FieldDef::default()
}],
..TypeDef::default()
}];
let files = [crate::e2e::fixture::FixtureDocsFileInput {
field: "/content".into(),
path: "guide.pdf".into(),
}];
let rendered = native_go_dto_literal(
&serde_json::json!({"content": "guide.pdf"}),
"Upload",
GoValueContext {
import_alias: "sample",
type_defs: &types,
enums: &[],
files: &files,
},
)
.expect("no refusal")
.expect("native DTO");
assert!(rendered.contains("Content: mustReadFile(`guide.pdf`)"), "{rendered}");
}
#[test]
fn renders_pointer_integer_field_with_explicit_width_cast() {
let types = [TypeDef {
name: "ChunkingConfig".into(),
fields: vec![FieldDef {
name: "max_characters".into(),
ty: TypeRef::Primitive(crate::core::ir::PrimitiveType::U64),
optional: true,
..FieldDef::default()
}],
..TypeDef::default()
}];
let rendered = native_go_dto_literal(
&serde_json::json!({"max_characters": 300}),
"ChunkingConfig",
GoValueContext {
import_alias: "samplecrate",
type_defs: &types,
enums: &[],
files: &[],
},
)
.expect("no refusal")
.expect("native DTO");
assert!(rendered.contains("MaxCharacters: ptr(uint64(300))"), "{rendered}");
assert!(
!rendered.contains("ptr(300)"),
"must not emit a bare untyped literal for a non-bool pointer field: {rendered}"
);
}
#[test]
fn renders_pointer_bool_field_without_a_cast() {
let types = [TypeDef {
name: "SampleConfig".into(),
fields: vec![FieldDef {
name: "retry".into(),
ty: TypeRef::Primitive(crate::core::ir::PrimitiveType::Bool),
optional: true,
..FieldDef::default()
}],
..TypeDef::default()
}];
let rendered = native_go_dto_literal(
&serde_json::json!({"retry": true}),
"SampleConfig",
GoValueContext {
import_alias: "samplecrate",
type_defs: &types,
enums: &[],
files: &[],
},
)
.expect("no refusal")
.expect("native DTO");
assert!(rendered.contains("Retry: ptr(true)"), "{rendered}");
}
#[test]
fn go_snippet_uses_binding_field_identifier_not_wire_name() {
let types = [TypeDef {
name: "ChunkingConfig".into(),
fields: vec![FieldDef {
name: "max_characters".into(),
ty: TypeRef::Primitive(crate::core::ir::PrimitiveType::Usize),
serde_rename: Some("max_chars".into()),
..FieldDef::default()
}],
..TypeDef::default()
}];
let rendered = native_go_dto_literal(
&serde_json::json!({"max_chars": 300}),
"ChunkingConfig",
GoValueContext {
import_alias: "samplecrate",
type_defs: &types,
enums: &[],
files: &[],
},
)
.expect("no refusal")
.expect("native DTO");
assert!(
rendered.contains("MaxCharacters: 300"),
"expected the binding's Go identifier `MaxCharacters` (matching \
`to_go_name(\"max_characters\")`) keyed by the wire name `max_chars`, got: {rendered}"
);
assert!(
!rendered.contains("MaxChars:"),
"must not PascalCase the serde wire name into an unknown field identifier: {rendered}"
);
}
#[test]
fn qualified_dto_type_name_matches_the_go_backends_acronym_casing() {
let types = [TypeDef {
name: "SampleJsonSchema".into(),
fields: vec![FieldDef {
name: "strict".into(),
ty: TypeRef::Primitive(crate::core::ir::PrimitiveType::Bool),
..FieldDef::default()
}],
..TypeDef::default()
}];
let rendered = native_go_dto_literal(
&serde_json::json!({"strict": true}),
"SampleJsonSchema",
GoValueContext {
import_alias: "pkg",
type_defs: &types,
enums: &[],
files: &[],
},
)
.expect("no refusal")
.expect("native DTO");
let backend_name = crate::codegen::naming::go_type_name("SampleJsonSchema");
let expected = format!("pkg.{backend_name}");
assert!(
rendered.starts_with(&expected),
"snippet literal's qualified type name must be byte-identical to the Go backend's \
own naming helper (`{expected}`), got: {rendered}"
);
assert!(
!rendered.contains("pkg.SampleJsonSchema"),
"must not re-derive casing locally and emit the raw un-acronymed IR name: {rendered}"
);
}