From 4ab04a0a1c2316f820297fe1e258c1d8665f361f Mon Sep 17 00:00:00 2001 From: teernisse Date: Thu, 12 Mar 2026 10:07:16 -0400 Subject: [PATCH] test(me): add integration tests for gitlab_base_url in robot JSON envelope Guards against regression in the wiring chain run_me -> print_me_json -> MeJsonEnvelope where the gitlab_base_url meta field could silently disappear. - me_envelope_includes_gitlab_base_url_in_meta: verifies full envelope serialization preserves the base URL in meta - activity_event_carries_url_construction_fields: verifies activity events contain entity_type + entity_iid + project fields, then demonstrates URL construction by combining with meta.gitlab_base_url --- src/cli/commands/me/render_robot.rs | 103 ++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/src/cli/commands/me/render_robot.rs b/src/cli/commands/me/render_robot.rs index 48cb217..e99292a 100644 --- a/src/cli/commands/me/render_robot.rs +++ b/src/cli/commands/me/render_robot.rs @@ -479,4 +479,107 @@ mod tests { assert_eq!(value["data"]["cursor_reset"], serde_json::json!(true)); assert_eq!(value["meta"]["elapsed_ms"], serde_json::json!(17)); } + + /// Integration test: full envelope serialization includes gitlab_base_url in meta. + /// Guards against drift where the wiring from run_me -> print_me_json -> JSON + /// could silently lose the base URL field. + #[test] + fn me_envelope_includes_gitlab_base_url_in_meta() { + let dashboard = MeDashboard { + username: "testuser".to_string(), + since_ms: Some(1_700_000_000_000), + summary: MeSummary { + project_count: 1, + open_issue_count: 0, + authored_mr_count: 0, + reviewing_mr_count: 0, + mentioned_in_count: 0, + needs_attention_count: 0, + }, + open_issues: vec![], + open_mrs_authored: vec![], + reviewing_mrs: vec![], + mentioned_in: vec![], + activity: vec![], + since_last_check: None, + }; + + let envelope = MeJsonEnvelope { + ok: true, + data: MeDataJson::from_dashboard(&dashboard), + meta: RobotMeta::with_base_url(42, "https://gitlab.example.com"), + }; + + let value = serde_json::to_value(&envelope).unwrap(); + assert_eq!(value["ok"], serde_json::json!(true)); + assert_eq!(value["meta"]["elapsed_ms"], serde_json::json!(42)); + assert_eq!( + value["meta"]["gitlab_base_url"], + serde_json::json!("https://gitlab.example.com") + ); + } + + /// Verify activity events carry the fields needed for URL construction + /// (entity_type, entity_iid, project) so consumers can combine with + /// meta.gitlab_base_url to build links. + #[test] + fn activity_event_carries_url_construction_fields() { + let dashboard = MeDashboard { + username: "testuser".to_string(), + since_ms: Some(1_700_000_000_000), + summary: MeSummary { + project_count: 1, + open_issue_count: 0, + authored_mr_count: 0, + reviewing_mr_count: 0, + mentioned_in_count: 0, + needs_attention_count: 0, + }, + open_issues: vec![], + open_mrs_authored: vec![], + reviewing_mrs: vec![], + mentioned_in: vec![], + activity: vec![MeActivityEvent { + timestamp: 1_700_000_000_000, + event_type: ActivityEventType::Note, + entity_type: "mr".to_string(), + entity_iid: 99, + project_path: "group/repo".to_string(), + actor: Some("alice".to_string()), + is_own: false, + summary: "Commented on MR".to_string(), + body_preview: None, + }], + since_last_check: None, + }; + + let envelope = MeJsonEnvelope { + ok: true, + data: MeDataJson::from_dashboard(&dashboard), + meta: RobotMeta::with_base_url(0, "https://gitlab.example.com"), + }; + + let value = serde_json::to_value(&envelope).unwrap(); + let event = &value["data"]["activity"][0]; + + // These three fields + meta.gitlab_base_url = complete URL + assert_eq!(event["entity_type"], "mr"); + assert_eq!(event["entity_iid"], 99); + assert_eq!(event["project"], "group/repo"); + + // Consumer constructs: https://gitlab.example.com/group/repo/-/merge_requests/99 + let base = value["meta"]["gitlab_base_url"].as_str().unwrap(); + let project = event["project"].as_str().unwrap(); + let entity_path = match event["entity_type"].as_str().unwrap() { + "issue" => "issues", + "mr" => "merge_requests", + other => panic!("unexpected entity_type: {other}"), + }; + let iid = event["entity_iid"].as_i64().unwrap(); + let url = format!("{base}/{project}/-/{entity_path}/{iid}"); + assert_eq!( + url, + "https://gitlab.example.com/group/repo/-/merge_requests/99" + ); + } }