huskies: merge 1035
This commit is contained in:
@@ -20,25 +20,33 @@ pub fn format_gateway_event(project_name: &str, event: &StoredEvent) -> (String,
|
||||
match event {
|
||||
StoredEvent::StageTransition {
|
||||
story_id,
|
||||
story_name,
|
||||
from_stage,
|
||||
to_stage,
|
||||
..
|
||||
} => {
|
||||
let from_typed = Stage::from_dir(from_stage).unwrap_or(Stage::Upcoming);
|
||||
let to_typed = Stage::from_dir(to_stage).unwrap_or(Stage::Upcoming);
|
||||
let (plain, html) = format_stage_notification(story_id, "", &from_typed, &to_typed);
|
||||
let (plain, html) =
|
||||
format_stage_notification(story_id, story_name, &from_typed, &to_typed);
|
||||
(format!("{prefix}{plain}"), format!("{prefix}{html}"))
|
||||
}
|
||||
StoredEvent::MergeFailure {
|
||||
story_id, reason, ..
|
||||
story_id,
|
||||
story_name,
|
||||
reason,
|
||||
..
|
||||
} => {
|
||||
let (plain, html) = format_error_notification(story_id, "", reason);
|
||||
let (plain, html) = format_error_notification(story_id, story_name, reason);
|
||||
(format!("{prefix}{plain}"), format!("{prefix}{html}"))
|
||||
}
|
||||
StoredEvent::StoryBlocked {
|
||||
story_id, reason, ..
|
||||
story_id,
|
||||
story_name,
|
||||
reason,
|
||||
..
|
||||
} => {
|
||||
let (plain, html) = format_blocked_notification(story_id, "", reason);
|
||||
let (plain, html) = format_blocked_notification(story_id, story_name, reason);
|
||||
(format!("{prefix}{plain}"), format!("{prefix}{html}"))
|
||||
}
|
||||
}
|
||||
@@ -54,6 +62,7 @@ mod tests {
|
||||
fn stage_transition_prefixes_project_name() {
|
||||
let event = StoredEvent::StageTransition {
|
||||
story_id: "42_story_my_feature".to_string(),
|
||||
story_name: String::new(),
|
||||
from_stage: "coding".to_string(),
|
||||
to_stage: "qa".to_string(),
|
||||
timestamp_ms: 1000,
|
||||
@@ -69,6 +78,7 @@ mod tests {
|
||||
fn merge_failure_prefixes_project_name() {
|
||||
let event = StoredEvent::MergeFailure {
|
||||
story_id: "42_story_my_feature".to_string(),
|
||||
story_name: String::new(),
|
||||
reason: "merge conflict".to_string(),
|
||||
timestamp_ms: 1000,
|
||||
};
|
||||
@@ -81,6 +91,7 @@ mod tests {
|
||||
fn story_blocked_prefixes_project_name() {
|
||||
let event = StoredEvent::StoryBlocked {
|
||||
story_id: "43_story_bar".to_string(),
|
||||
story_name: String::new(),
|
||||
reason: "retry limit exceeded".to_string(),
|
||||
timestamp_ms: 2000,
|
||||
};
|
||||
@@ -88,4 +99,93 @@ mod tests {
|
||||
assert!(plain.starts_with("[huskies] "));
|
||||
assert!(plain.contains("BLOCKED"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stage_transition_with_story_name_includes_title() {
|
||||
let event = StoredEvent::StageTransition {
|
||||
story_id: "10_story_feat".to_string(),
|
||||
story_name: "My New Feature".to_string(),
|
||||
from_stage: "backlog".to_string(),
|
||||
to_stage: "coding".to_string(),
|
||||
timestamp_ms: 100,
|
||||
};
|
||||
let (plain, html) = format_gateway_event("huskies", &event);
|
||||
assert!(plain.starts_with("[huskies] "));
|
||||
assert!(
|
||||
plain.contains("My New Feature"),
|
||||
"plain must include story title; got: {plain}"
|
||||
);
|
||||
assert!(
|
||||
html.contains("My New Feature"),
|
||||
"html must include story title; got: {html}"
|
||||
);
|
||||
assert!(plain.contains("#10"));
|
||||
assert!(plain.contains("Backlog"));
|
||||
assert!(plain.contains("Current"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_failure_with_story_name_includes_title() {
|
||||
let event = StoredEvent::MergeFailure {
|
||||
story_id: "7_story_bar".to_string(),
|
||||
story_name: "Bar Feature".to_string(),
|
||||
reason: "conflict in lib.rs".to_string(),
|
||||
timestamp_ms: 200,
|
||||
};
|
||||
let (plain, html) = format_gateway_event("robot-studio", &event);
|
||||
assert!(plain.starts_with("[robot-studio] "));
|
||||
assert!(
|
||||
plain.contains("Bar Feature"),
|
||||
"plain must include story title; got: {plain}"
|
||||
);
|
||||
assert!(
|
||||
html.contains("Bar Feature"),
|
||||
"html must include story title; got: {html}"
|
||||
);
|
||||
assert!(plain.contains("#7"));
|
||||
assert!(plain.contains("conflict in lib.rs"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn story_blocked_with_story_name_includes_title() {
|
||||
let event = StoredEvent::StoryBlocked {
|
||||
story_id: "3_story_baz".to_string(),
|
||||
story_name: "Baz Story".to_string(),
|
||||
reason: "retry limit exceeded".to_string(),
|
||||
timestamp_ms: 300,
|
||||
};
|
||||
let (plain, html) = format_gateway_event("huskies", &event);
|
||||
assert!(plain.starts_with("[huskies] "));
|
||||
assert!(
|
||||
plain.contains("Baz Story"),
|
||||
"plain must include story title; got: {plain}"
|
||||
);
|
||||
assert!(
|
||||
html.contains("Baz Story"),
|
||||
"html must include story title; got: {html}"
|
||||
);
|
||||
assert!(plain.contains("#3"));
|
||||
assert!(plain.contains("BLOCKED"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unnamed_story_falls_back_gracefully() {
|
||||
let event = StoredEvent::StageTransition {
|
||||
story_id: "5_story_unnamed".to_string(),
|
||||
story_name: String::new(),
|
||||
from_stage: "backlog".to_string(),
|
||||
to_stage: "qa".to_string(),
|
||||
timestamp_ms: 50,
|
||||
};
|
||||
let (plain, _html) = format_gateway_event("proj", &event);
|
||||
assert!(plain.starts_with("[proj] "));
|
||||
assert!(plain.contains("#5"));
|
||||
assert!(plain.contains("Backlog"));
|
||||
assert!(plain.contains("QA"));
|
||||
// Must NOT contain stray empty-name artefacts between # and —
|
||||
assert!(
|
||||
!plain.contains(" "),
|
||||
"should not have double spaces from empty name; got: {plain}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user