| 208 | |
| 209 | #[test] |
| 210 | fn render_includes_scope_and_constraints() { |
| 211 | let node = CanonicalNode { |
| 212 | context: CONTEXT_URL.to_string(), |
| 213 | type_: NodeType::Intent.as_str().to_string(), |
| 214 | id: "urn:atomic:intent:render-1".to_string(), |
| 215 | human_key: "R-1".to_string(), |
| 216 | title: "Render".to_string(), |
| 217 | status: "todo".to_string(), |
| 218 | priority: None, |
| 219 | view: None, |
| 220 | motivated_by: None, |
| 221 | informed_by: Vec::new(), |
| 222 | has_acceptance_criterion: Vec::new(), |
| 223 | has_task: Vec::new(), |
| 224 | has_scope_in: vec![scope("urn:atomic:scope:r-1-scope-in-1", "the modal markup")], |
| 225 | has_scope_out: vec![scope( |
| 226 | "urn:atomic:scope:r-1-scope-out-1", |
| 227 | "persisting across reloads", |
| 228 | )], |
| 229 | has_constraint: vec![ |
| 230 | Constraint { |
| 231 | type_: NodeType::Constraint.as_str().to_string(), |
| 232 | id: "urn:atomic:constraint:r-1-constraint-1".to_string(), |
| 233 | text: "keep it local".to_string(), |
| 234 | }, |
| 235 | Constraint { |
| 236 | type_: NodeType::Constraint.as_str().to_string(), |
| 237 | id: "urn:atomic:constraint:r-1-constraint-2".to_string(), |
| 238 | text: "do not touch the keyboard handler".to_string(), |
| 239 | }, |
| 240 | ], |
| 241 | depends_on: vec![Ref { |
| 242 | type_: None, |
| 243 | id: None, |
| 244 | to: "urn:atomic:intent:xyz".to_string(), |
| 245 | edge: "blockedBy".to_string(), |
| 246 | }], |
| 247 | why: Some("a reason".to_string()), |
| 248 | content_hash: None, |
| 249 | attributed_to: None, |
| 250 | created_at: "2026-06-25T00:00:00Z".to_string(), |
| 251 | proof: None, |
| 252 | }; |
| 253 | |
| 254 | let text = render(&node, Target::Cli); |
| 255 | assert!(text.contains("Out of Scope"), "render:\n{text}"); |
| 256 | assert!(text.contains("persisting across reloads")); |
| 257 | assert!(text.contains("keep it local")); |
| 258 | assert!(text.contains("do not touch the keyboard handler")); |
| 259 | // Dependency rendered as 'edge -> to'. |
| 260 | assert!(text.contains("blockedBy")); |
| 261 | assert!(text.contains("blockedBy -> urn:atomic:intent:xyz")); |
| 262 | } |
| 263 | |
| 264 | #[test] |
| 265 | fn render_memory_regenerates_status_from_spine() { |