fix: project ticket blockers from current DTO shape
This commit is contained in:
@@ -124,7 +124,6 @@ struct ModelBlocker {
|
|||||||
ticket: String,
|
ticket: String,
|
||||||
kind: String,
|
kind: String,
|
||||||
state: Option<String>,
|
state: Option<String>,
|
||||||
resolved: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@@ -436,7 +435,6 @@ fn project_blocker(value: &Value) -> Result<ModelBlocker, String> {
|
|||||||
ticket: resource_ref(blocker, "blocking_resource_key", "T-")?,
|
ticket: resource_ref(blocker, "blocking_resource_key", "T-")?,
|
||||||
kind: string_field(blocker, "relation_kind")?,
|
kind: string_field(blocker, "relation_kind")?,
|
||||||
state: optional_string(blocker, "blocking_state")?,
|
state: optional_string(blocker, "blocking_state")?,
|
||||||
resolved: bool_field(blocker, "resolved")?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,6 +758,70 @@ mod tests {
|
|||||||
assert!(!objective_json.contains("00001TICKETINTERNAL"));
|
assert!(!objective_json.contains("00001TICKETINTERNAL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ticket_detail_projection_accepts_current_blocker_shape() {
|
||||||
|
let projected = project_ticket_detail(json!({
|
||||||
|
"id": "internal-ticket",
|
||||||
|
"resource_key": "T-588",
|
||||||
|
"title": "Queued Submit",
|
||||||
|
"body": "Body",
|
||||||
|
"state": "planning",
|
||||||
|
"readiness": null,
|
||||||
|
"priority": "P2",
|
||||||
|
"created_at": "2026-09-03T00:00:00Z",
|
||||||
|
"updated_at": "2026-09-03T00:00:00Z",
|
||||||
|
"events": [],
|
||||||
|
"relations": {
|
||||||
|
"outgoing": [],
|
||||||
|
"incoming": [],
|
||||||
|
"blockers": [{
|
||||||
|
"blocking_ticket": "internal-blocker",
|
||||||
|
"blocking_resource_key": "T-584",
|
||||||
|
"reason_kind": "depends_on",
|
||||||
|
"relation_kind": "depends_on",
|
||||||
|
"note": "required foundation",
|
||||||
|
"blocking_state": "planning"
|
||||||
|
}],
|
||||||
|
"notices": []
|
||||||
|
},
|
||||||
|
"linked_objectives": [],
|
||||||
|
"implementation_reports": [],
|
||||||
|
"assignments": [],
|
||||||
|
"current_coder": null,
|
||||||
|
"merge_request": null,
|
||||||
|
"evidence": {
|
||||||
|
"has_merge_request": false,
|
||||||
|
"has_current_subject_ref": false,
|
||||||
|
"has_review_request": false,
|
||||||
|
"has_commit": false,
|
||||||
|
"review_status": null,
|
||||||
|
"approved_current_subject": false,
|
||||||
|
"unresolved_request_changes": false,
|
||||||
|
"complete_for_integration": false,
|
||||||
|
"missing": ["merge_request"]
|
||||||
|
},
|
||||||
|
"action_eligibility": {
|
||||||
|
"can_assign_orchestrator": true,
|
||||||
|
"can_unassign_orchestrator": false,
|
||||||
|
"can_queue": false,
|
||||||
|
"can_start_manual_coder": false
|
||||||
|
},
|
||||||
|
"event_page": {"next_cursor": null, "has_more": false}
|
||||||
|
}))
|
||||||
|
.expect("current Ticket blocker shape must project");
|
||||||
|
|
||||||
|
let projected = serde_json::to_value(projected).expect("serialize Ticket detail");
|
||||||
|
assert_eq!(
|
||||||
|
projected["relations"]["blockers"],
|
||||||
|
json!([{
|
||||||
|
"ticket": "T-584",
|
||||||
|
"kind": "depends_on",
|
||||||
|
"state": "planning"
|
||||||
|
}])
|
||||||
|
);
|
||||||
|
assert!(!projected.to_string().contains("internal-blocker"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn relation_projection_accepts_current_workspace_api_shapes() {
|
fn relation_projection_accepts_current_workspace_api_shapes() {
|
||||||
let outgoing = project_relation(
|
let outgoing = project_relation(
|
||||||
|
|||||||
Reference in New Issue
Block a user