#[cfg(test)]
mod tests {
use openapi_to_rust::test_helpers::*;
use serde_json::json;
#[test]
fn test_x_stainless_const_bug_nested() {
let spec = minimal_spec(json!({
"ReasoningPart": {
"type": "object",
"properties": {
"type": {
"description": "The type of the part. Always `summary_text`.",
"enum": ["summary_text"],
"type": "string",
"x-stainless-const": true
},
"text": {
"type": "string"
}
},
"required": ["type", "text"]
},
"ResponseEvent": {
"type": "object",
"properties": {
"type": {
"description": "The type of the event. Always `response.event.done`.",
"enum": ["response.event.done"],
"type": "string",
"x-stainless-const": true
},
"part": {
"$ref": "#/components/schemas/ReasoningPart"
}
},
"required": ["type", "part"]
}
}));
let result = test_generation("x_stainless_nested", spec).expect("Generation failed");
println!("Generated output:\n{}", result);
assert!(
result.contains("pub enum ReasoningPartType"),
"ReasoningPartType enum should be generated"
);
assert!(
result.contains("#[serde(rename = \"summary_text\")]"),
"ReasoningPartType should have summary_text variant with correct serde rename"
);
assert!(
result.contains("pub enum ResponseEventType"),
"ResponseEventType enum should be generated"
);
assert!(
result.contains("#[serde(rename = \"response.event.done\")]"),
"ResponseEventType should have response.event.done variant with correct serde rename - NOT summary_text"
);
if result.contains("ResponseEventType") {
assert!(
!result.contains("ResponseEventType")
|| !result.contains("summary_text")
|| result.contains("response.event.done"),
"ResponseEventType should NOT have summary_text enum value - this would indicate the bug"
);
}
}
#[test]
fn test_x_stainless_const_bug_discriminated_union() {
let spec = minimal_spec(json!({
"ReasoningPart": {
"type": "object",
"properties": {
"type": {
"description": "The type of the part. Always `summary_text`.",
"enum": ["summary_text"],
"type": "string",
"x-stainless-const": true
},
"text": {
"type": "string"
}
},
"required": ["type", "text"]
},
"ResponseReasoningSummaryPartAddedEvent": {
"type": "object",
"properties": {
"type": {
"description": "The type of the event. Always `response.reasoning_summary_part.added`.",
"enum": ["response.reasoning_summary_part.added"],
"type": "string",
"x-stainless-const": true
},
"part": {
"$ref": "#/components/schemas/ReasoningPart"
}
},
"required": ["type", "part"]
},
"ResponseReasoningSummaryPartDoneEvent": {
"type": "object",
"properties": {
"type": {
"description": "The type of the event. Always `response.reasoning_summary_part.done`.",
"enum": ["response.reasoning_summary_part.done"],
"type": "string",
"x-stainless-const": true
},
"part": {
"$ref": "#/components/schemas/ReasoningPart"
}
},
"required": ["type", "part"]
},
"EventUnion": {
"oneOf": [
{ "$ref": "#/components/schemas/ResponseReasoningSummaryPartAddedEvent" },
{ "$ref": "#/components/schemas/ResponseReasoningSummaryPartDoneEvent" }
],
"discriminator": {
"propertyName": "type"
}
}
}));
let result = test_generation("x_stainless_discriminated", spec).expect("Generation failed");
println!("Generated output:\n{}", result);
assert!(
result.contains("pub enum ReasoningPartType"),
"ReasoningPartType enum should be generated"
);
assert!(
result.contains("#[serde(rename = \"summary_text\")]"),
"ReasoningPartType should have summary_text variant with correct serde rename"
);
assert!(
result.contains("pub enum ResponseReasoningSummaryPartAddedEventType"),
"ResponseReasoningSummaryPartAddedEventType enum should be generated"
);
assert!(
result.contains("#[serde(rename = \"response.reasoning_summary_part.added\")]"),
"ResponseReasoningSummaryPartAddedEventType should have response.reasoning_summary_part.added variant"
);
assert!(
result.contains("pub enum ResponseReasoningSummaryPartDoneEventType"),
"ResponseReasoningSummaryPartDoneEventType enum should be generated"
);
assert!(
result.contains("#[serde(rename = \"response.reasoning_summary_part.done\")]"),
"ResponseReasoningSummaryPartDoneEventType should have response.reasoning_summary_part.done variant"
);
assert!(
result.contains("pub enum EventUnion"),
"EventUnion should be generated as discriminated union"
);
assert!(
result.contains("#[serde(tag = \"type\")]"),
"EventUnion should use type as discriminator tag"
);
}
#[test]
#[ignore = "Test designed to fail until generator enum collision bug is fixed - see investigation results"]
fn test_actual_reasoning_item_missing_type_field() {
let spec = minimal_spec(json!({
"ReasoningItem": {
"description": "A description of the chain of thought used by a reasoning model while generating a response.",
"type": "object",
"properties": {
"encrypted_content": {
"description": "The encrypted content of the reasoning item - populated when a response is generated with `reasoning.encrypted_content` in the `include` parameter.",
"nullable": true,
"type": "string"
},
"id": {
"description": "The unique identifier of the reasoning content.",
"type": "string"
},
"status": {
"description": "The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API.",
"enum": [
"in_progress",
"completed",
"incomplete"
],
"type": "string"
},
"summary": {
"description": "Reasoning text contents.",
"items": {
"properties": {
"text": {
"description": "A short summary of the reasoning used by the model when generating the response.",
"type": "string"
},
"type": {
"description": "The type of the object. Always `summary_text`.",
"enum": [
"summary_text"
],
"type": "string",
"x-stainless-const": true
}
},
"required": [
"type",
"text"
],
"type": "object"
},
"type": "array"
},
"type": {
"description": "The type of the object. Always `reasoning`.",
"enum": [
"reasoning"
],
"type": "string",
"x-stainless-const": true
}
},
"required": [
"id",
"summary",
"type"
],
"title": "Reasoning",
"type": "object"
}
}));
let result = test_generation("actual_reasoning_item_missing_type_field", spec)
.expect("Generation failed");
println!("Generated output:\n{}", result);
assert!(
result.contains("pub struct ReasoningItem"),
"ReasoningItem struct should be generated"
);
assert!(
result.contains("pub r#type: ReasoningItemMainType"),
"ReasoningItem should have main type field"
);
assert!(
result.contains("pub enum ReasoningItemMainType")
|| result.contains("pub enum ReasoningItemType"),
"ReasoningItem main type enum should be generated"
);
assert!(
result.contains("#[serde(rename = \"reasoning\")]"),
"ReasoningItem main type should have 'reasoning' variant"
);
assert!(
result.contains("ReasoningItemSummaryItemType")
|| result.contains("ReasoningItemSummaryItem"),
"ReasoningItem summary item type should be generated"
);
assert!(
result.contains("#[serde(rename = \"summary_text\")]"),
"ReasoningItem summary item should have 'summary_text' variant"
);
}
#[test]
fn test_x_stainless_const_bug_reproduction() {
let spec = minimal_spec(json!({
"ReasoningItem": {
"type": "object",
"properties": {
"type": {
"description": "The type of the object. Always `summary_text`.",
"enum": ["summary_text"],
"type": "string",
"x-stainless-const": true
},
"text": {
"type": "string"
}
},
"required": ["type", "text"]
},
"ResponseReasoningSummaryPartDoneEvent": {
"description": "Emitted when a reasoning summary part is completed.",
"type": "object",
"properties": {
"type": {
"description": "The type of the event. Always `response.reasoning_summary_part.done`.",
"enum": ["response.reasoning_summary_part.done"],
"type": "string",
"x-stainless-const": true
},
"item_id": {
"type": "string"
},
"part": {
"$ref": "#/components/schemas/ReasoningItem"
}
},
"required": ["type", "item_id", "part"]
},
"ResponseReasoningSummaryPartAddedEvent": {
"description": "Emitted when a new reasoning summary part is added.",
"type": "object",
"properties": {
"type": {
"description": "The type of the event. Always `response.reasoning_summary_part.added`.",
"enum": ["response.reasoning_summary_part.added"],
"type": "string",
"x-stainless-const": true
},
"item_id": {
"type": "string"
},
"part": {
"$ref": "#/components/schemas/ReasoningItem"
}
},
"required": ["type", "item_id", "part"]
},
"EventUnion": {
"oneOf": [
{ "$ref": "#/components/schemas/ResponseReasoningSummaryPartDoneEvent" },
{ "$ref": "#/components/schemas/ResponseReasoningSummaryPartAddedEvent" }
],
"discriminator": {
"propertyName": "type"
}
}
}));
let result = test_generation("x_stainless_const_bug", spec).expect("Generation failed");
println!("Generated output:\n{}", result);
assert!(
result.contains("pub enum ReasoningItemType"),
"ReasoningItemType enum should be generated"
);
assert!(
result.contains("#[serde(rename = \"summary_text\")]"),
"ReasoningItemType should have summary_text variant with correct serde rename"
);
assert!(
result.contains("pub enum ResponseReasoningSummaryPartDoneEventType"),
"ResponseReasoningSummaryPartDoneEventType enum should be generated"
);
assert!(
result.contains("pub enum ResponseReasoningSummaryPartAddedEventType"),
"ResponseReasoningSummaryPartAddedEventType enum should be generated"
);
assert!(
!result.contains("ResponseReasoningSummaryPartDoneEventType")
|| !result.contains("#[serde(rename = \"summary_text\")]")
|| result.contains("#[serde(rename = \"response.reasoning_summary_part.done\")]"),
"ResponseReasoningSummaryPartDoneEventType should NOT have summary_text - should have response.reasoning_summary_part.done"
);
assert!(
!result.contains("ResponseReasoningSummaryPartAddedEventType")
|| !result.contains("#[serde(rename = \"summary_text\")]")
|| result.contains("#[serde(rename = \"response.reasoning_summary_part.added\")]"),
"ResponseReasoningSummaryPartAddedEventType should NOT have summary_text - should have response.reasoning_summary_part.added"
);
assert!(
result.contains("pub enum EventUnion"),
"EventUnion should be generated as discriminated union"
);
assert!(
result.contains("#[serde(tag = \"type\")]"),
"EventUnion should use type as discriminator tag"
);
}
}