Wire intent→coordinator DocResolver confirm cards→action_executor kinds for comment, reopen, pending-supplements query, and real submit-review execution.
161 lines
4.9 KiB
Go
161 lines
4.9 KiB
Go
package chat
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"chat-agent-system/internal/bizdev"
|
|
"chat-agent-system/internal/config"
|
|
"chat-agent-system/internal/coordinator"
|
|
"chat-agent-system/internal/docgov"
|
|
)
|
|
|
|
func TestExecuteAction_DocGovReviewApprove(t *testing.T) {
|
|
cfg := &config.Config{DataDir: t.TempDir()}
|
|
svc := bizdev.MustNewService(t, cfg)
|
|
docGov := bizdev.Snapshot(svc).Gov
|
|
ctx := context.Background()
|
|
|
|
docID := "doc_proj1_research"
|
|
_, err := docGov.CreateOrGetDocument(
|
|
ctx, docID, 1, "research", "调研报告", "V0.5", "",
|
|
1, "张工", 2, "李主管", 3, "王总监",
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("CreateOrGetDocument: %v", err)
|
|
}
|
|
_ = docGov.MarkDocumentContentUpdated(ctx, docID, "hash1", false)
|
|
_, _ = docGov.SubmitForReview(ctx, docID, 1, docgov.RoleAuthor, "张工")
|
|
|
|
sess := &Session{
|
|
UserID: 2,
|
|
Actions: &ActionServices{DocGov: docGov},
|
|
}
|
|
action := &coordinator.PendingAction{
|
|
Kind: "docgov.review_approve",
|
|
DocID: docID,
|
|
Comment: "同意",
|
|
}
|
|
userCtx := &coordinator.UserProjectContext{
|
|
User: coordinator.UserInfo{ID: "2", Name: "李主管"},
|
|
}
|
|
|
|
result, err := sess.executeAction(ctx, action, userCtx)
|
|
if err != nil {
|
|
t.Fatalf("executeAction failed: %v", err)
|
|
}
|
|
if result.DocState != string(docgov.StateApproving) {
|
|
t.Fatalf("expected approving state, got %s", result.DocState)
|
|
}
|
|
reply := renderActionReply(action, result, nil)
|
|
if reply == "" {
|
|
t.Fatal("expected non-empty reply")
|
|
}
|
|
}
|
|
|
|
func TestExecuteAction_SubmitReviewAndComment(t *testing.T) {
|
|
cfg := &config.Config{DataDir: t.TempDir()}
|
|
svc := bizdev.MustNewService(t, cfg)
|
|
docGov := bizdev.Snapshot(svc).Gov
|
|
ctx := context.Background()
|
|
|
|
docID := "doc_proj1_intake"
|
|
_, err := docGov.CreateOrGetDocument(
|
|
ctx, docID, 1, "intake", "需求收集表", "V0.1", "",
|
|
1, "张工", 2, "李主管", 3, "王总监",
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("create: %v", err)
|
|
}
|
|
_ = docGov.MarkDocumentContentUpdated(ctx, docID, "hash1", false)
|
|
|
|
sess := &Session{UserID: 1, ProjectID: 1, Actions: &ActionServices{DocGov: docGov}}
|
|
userCtx := &coordinator.UserProjectContext{User: coordinator.UserInfo{ID: "1", Name: "张工"}}
|
|
|
|
res, err := sess.executeAction(ctx, &coordinator.PendingAction{Kind: "docgov.submit_review", DocID: docID}, userCtx)
|
|
if err != nil {
|
|
t.Fatalf("submit: %v", err)
|
|
}
|
|
if res.DocState != string(docgov.StateReviewing) {
|
|
t.Fatalf("state=%s", res.DocState)
|
|
}
|
|
|
|
_, err = sess.executeAction(ctx, &coordinator.PendingAction{
|
|
Kind: "docgov.comment_add", DocID: docID, Role: "reviewer", Section: "s1",
|
|
Comment: "请补充风险", Reason: "suggestion",
|
|
}, &coordinator.UserProjectContext{User: coordinator.UserInfo{ID: "2", Name: "李主管"}})
|
|
if err != nil {
|
|
// author can also comment in reviewing; use reviewer id
|
|
t.Fatalf("comment add: %v", err)
|
|
}
|
|
|
|
sess.UserID = 2
|
|
_, err = sess.executeAction(ctx, &coordinator.PendingAction{
|
|
Kind: "docgov.comment_resolve", DocID: docID, Role: "reviewer", Section: "s1",
|
|
}, &coordinator.UserProjectContext{User: coordinator.UserInfo{ID: "2", Name: "李主管"}})
|
|
if err != nil {
|
|
t.Fatalf("comment resolve: %v", err)
|
|
}
|
|
}
|
|
|
|
type stubReopen struct {
|
|
reqErr error
|
|
aprErr error
|
|
}
|
|
|
|
func (s *stubReopen) ListPendingReopens(context.Context, int64) ([]ReopenRequestView, error) {
|
|
return nil, nil
|
|
}
|
|
func (s *stubReopen) RequestReopenByDoc(context.Context, int64, string, string, int64) (ReopenRequestView, error) {
|
|
if s.reqErr != nil {
|
|
return ReopenRequestView{}, s.reqErr
|
|
}
|
|
return ReopenRequestView{ID: 9, Status: "pending"}, nil
|
|
}
|
|
func (s *stubReopen) ApproveReopenByID(context.Context, int64, int64, int64) (ReopenRequestView, error) {
|
|
if s.aprErr != nil {
|
|
return ReopenRequestView{}, s.aprErr
|
|
}
|
|
return ReopenRequestView{ID: 9, Status: "approved"}, nil
|
|
}
|
|
|
|
func TestExecuteAction_ReopenPaths(t *testing.T) {
|
|
sess := &Session{
|
|
UserID: 1, ProjectID: 1,
|
|
Actions: &ActionServices{Reopens: &stubReopen{}},
|
|
}
|
|
userCtx := &coordinator.UserProjectContext{User: coordinator.UserInfo{ID: "1", Name: "A"}}
|
|
res, err := sess.executeAction(context.Background(), &coordinator.PendingAction{
|
|
Kind: "docgov.reopen_request", TaskKey: "intake", Reason: "需补充",
|
|
}, userCtx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if res.Message == "" {
|
|
t.Fatal("expected message")
|
|
}
|
|
res, err = sess.executeAction(context.Background(), &coordinator.PendingAction{
|
|
Kind: "docgov.reopen_approve", RequestID: 9,
|
|
}, userCtx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if res.Message == "" {
|
|
t.Fatal("expected approve message")
|
|
}
|
|
|
|
sess.Actions.Reopens = &stubReopen{reqErr: fmt.Errorf("无权申请重开")}
|
|
_, err = sess.executeAction(context.Background(), &coordinator.PendingAction{
|
|
Kind: "docgov.reopen_request", TaskKey: "intake", Reason: "x",
|
|
}, userCtx)
|
|
if err == nil {
|
|
t.Fatal("expected permission failure")
|
|
}
|
|
reply := renderActionReply(&coordinator.PendingAction{Kind: "docgov.reopen_request", DocID: "d"}, nil, err)
|
|
if reply == "" || !strings.Contains(reply, "无权") {
|
|
t.Fatalf("reply=%s", reply)
|
|
}
|
|
}
|