huskies: merge 516_story_update_story_description_should_create_the_description_section_if_it_doesn_t_exist_instead_of_erroring

This commit is contained in:
dave
2026-04-10 10:25:07 +00:00
parent f015fe5a1d
commit 61ae30873f
2 changed files with 104 additions and 8 deletions
+57 -8
View File
@@ -3,7 +3,7 @@ use serde_json::Value;
use std::collections::HashMap;
use std::path::Path;
use super::{next_item_number, read_story_content, replace_section_content, slugify_name, story_stage, write_story_content_with_fs};
use super::{create_section_content, next_item_number, read_story_content, replace_section_content, slugify_name, story_stage, write_story_content_with_fs};
/// Shared create-story logic used by both the OpenApi and MCP handlers.
///
@@ -249,10 +249,16 @@ pub fn update_story_in_file(
}
if let Some(us) = user_story {
contents = replace_section_content(&contents, "User Story", us)?;
contents = match replace_section_content(&contents, "User Story", us) {
Ok(updated) => updated,
Err(_) => create_section_content(&contents, "User Story", us, Some("Acceptance Criteria")),
};
}
if let Some(desc) = description {
contents = replace_section_content(&contents, "Description", desc)?;
contents = match replace_section_content(&contents, "Description", desc) {
Ok(updated) => updated,
Err(_) => create_section_content(&contents, "Description", desc, Some("Acceptance Criteria")),
};
}
// Write back to content store.
@@ -505,13 +511,56 @@ mod tests {
}
#[test]
fn update_story_missing_section_returns_error() {
fn update_story_creates_user_story_section_if_missing() {
let tmp = tempfile::tempdir().unwrap();
setup_story_in_fs(tmp.path(), "23_test", "---\nname: T\n---\n\nNo sections here.\n");
// Story with no ## User Story section but has ## Acceptance Criteria.
let content = "---\nname: T\n---\n\n## Acceptance Criteria\n\n- [ ] AC\n";
setup_story_in_fs(tmp.path(), "23_test", content);
let result = update_story_in_file(tmp.path(), "23_test", Some("new text"), None, None);
assert!(result.is_err());
assert!(result.unwrap_err().contains("User Story"));
let result = update_story_in_file(tmp.path(), "23_test", Some("New user story"), None, None);
assert!(result.is_ok(), "should succeed when section is missing: {result:?}");
let updated = read_story_content(tmp.path(), "23_test").unwrap();
assert!(updated.contains("## User Story"), "section should be created");
assert!(updated.contains("New user story"), "text should be present");
// Section should appear before Acceptance Criteria.
let pos_us = updated.find("## User Story").unwrap();
let pos_ac = updated.find("## Acceptance Criteria").unwrap();
assert!(pos_us < pos_ac, "User Story should be before Acceptance Criteria");
}
#[test]
fn update_story_creates_description_section_if_missing() {
let tmp = tempfile::tempdir().unwrap();
// Story with no ## Description section but has ## Acceptance Criteria.
let content = "---\nname: T\n---\n\n## User Story\n\nAs a user...\n\n## Acceptance Criteria\n\n- [ ] AC\n";
setup_story_in_fs(tmp.path(), "32_test", content);
let result = update_story_in_file(tmp.path(), "32_test", None, Some("New description text"), None);
assert!(result.is_ok(), "should succeed when section is missing: {result:?}");
let updated = read_story_content(tmp.path(), "32_test").unwrap();
assert!(updated.contains("## Description"), "section should be created");
assert!(updated.contains("New description text"), "text should be present");
// Section should appear before Acceptance Criteria.
let pos_desc = updated.find("## Description").unwrap();
let pos_ac = updated.find("## Acceptance Criteria").unwrap();
assert!(pos_desc < pos_ac, "Description should be before Acceptance Criteria");
}
#[test]
fn update_story_creates_description_section_no_ac_section() {
let tmp = tempfile::tempdir().unwrap();
// Story with no ## Description and no ## Acceptance Criteria.
let content = "---\nname: T\n---\n\nSome content here.\n";
setup_story_in_fs(tmp.path(), "33_test", content);
let result = update_story_in_file(tmp.path(), "33_test", None, Some("Appended description"), None);
assert!(result.is_ok(), "should succeed even with no Acceptance Criteria: {result:?}");
let updated = read_story_content(tmp.path(), "33_test").unwrap();
assert!(updated.contains("## Description"), "section should be created");
assert!(updated.contains("Appended description"), "text should be present");
}
#[test]