feat(sprints): modèle de sprints — domaine, use-cases, persistance et surfaces (backend)
Ticket #10 — introduction du modèle de sprints côté backend. - Domaine : nouvel agrégat Sprint (sprint.rs), IDs, événements et invariants ; rattachement des issues à un sprint (issue.rs) et ports associés. - Application : use-cases sprints (application/src/sprints) + erreurs dédiées. - Infrastructure : store de sprints (infrastructure/src/sprints.rs), adaptation du store d'issues et exposition MCP via orchestrator/mcp/tickets.rs. - app-tauri : commandes, state et events pour piloter les sprints depuis l'UI. Tests domaine/application/infra/app-tauri verts (sprint_usecases, sprint_store, issue_store, mcp_server). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -4,7 +4,7 @@ use std::str::FromStr;
|
||||
use domain::{
|
||||
AgentIssueRef, AgentIssueRole, Issue, IssueActor, IssueId, IssueListFilter,
|
||||
IssueNumberAllocator, IssuePriority, IssueRef, IssueStatus, IssueStore, IssueStoreError,
|
||||
MarkdownDoc, ProjectPath,
|
||||
MarkdownDoc, ProjectPath, SprintId,
|
||||
};
|
||||
use infrastructure::{FsIssueNumberAllocator, FsIssueStore};
|
||||
use uuid::Uuid;
|
||||
@ -144,6 +144,44 @@ async fn issue_store_lists_by_index_filters() {
|
||||
assert_eq!(rows[0].title, "Beta");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn issue_store_persists_and_filters_sprint_membership() {
|
||||
let tmp = TempDir::new();
|
||||
let root = tmp.root();
|
||||
let store = FsIssueStore::new();
|
||||
let sprint_id = SprintId::from_uuid(Uuid::from_u128(42));
|
||||
let assigned = issue(&root, 1, "Assigned")
|
||||
.mutate(IssueActor::System, 2_000, |i| {
|
||||
i.sprint = Some(sprint_id);
|
||||
})
|
||||
.unwrap();
|
||||
store.create(&root, &assigned).await.unwrap();
|
||||
store
|
||||
.create(&root, &issue(&root, 2, "Backlog"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let loaded = store
|
||||
.get_by_ref(&root, IssueRef::from_str("#1").unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(loaded.sprint, Some(sprint_id));
|
||||
|
||||
let rows = store
|
||||
.list(
|
||||
&root,
|
||||
IssueListFilter {
|
||||
sprint: Some(sprint_id),
|
||||
..IssueListFilter::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(rows.len(), 1);
|
||||
assert_eq!(rows[0].title, "Assigned");
|
||||
assert_eq!(rows[0].sprint, Some(sprint_id));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn allocator_never_reuses_numbers() {
|
||||
let tmp = TempDir::new();
|
||||
|
||||
Reference in New Issue
Block a user