feat(t208): close candidate decision feedback loop
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package usecase
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidateCandidateHumanReviewAcceptsStructuredSelection(t *testing.T) {
|
||||
selected := 2
|
||||
command := validCandidateHumanReviewCommand()
|
||||
command.SelectedCandidateOrdinal = &selected
|
||||
command.Items = []CandidateHumanReviewItemInput{
|
||||
{
|
||||
CandidateOrdinal: 1,
|
||||
Label: "REJECT",
|
||||
PrimaryReasonCode: "NOT_BEST_MATCH",
|
||||
ReasonCodes: []string{"NOT_BEST_MATCH"},
|
||||
},
|
||||
{
|
||||
CandidateOrdinal: 2,
|
||||
Label: "ACCEPT",
|
||||
PrimaryReasonCode: "SKU_MATCH",
|
||||
ReasonCodes: []string{"SKU_MATCH", "IMAGE_MATCH"},
|
||||
},
|
||||
}
|
||||
|
||||
if err := validateCandidateHumanReview(command); err != nil {
|
||||
t.Fatalf("validate structured selection: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCandidateHumanReviewRejectsMissingSelectedItem(t *testing.T) {
|
||||
selected := 2
|
||||
command := validCandidateHumanReviewCommand()
|
||||
command.SelectedCandidateOrdinal = &selected
|
||||
|
||||
if err := validateCandidateHumanReview(command); err == nil {
|
||||
t.Fatal("expected missing selected item to be rejected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCandidateHumanReviewRequiresOtherNote(t *testing.T) {
|
||||
command := validCandidateHumanReviewCommand()
|
||||
command.PrimaryReasonCode = "OTHER"
|
||||
command.Note = "短"
|
||||
|
||||
if err := validateCandidateHumanReview(command); err == nil {
|
||||
t.Fatal("expected short OTHER note to be rejected")
|
||||
}
|
||||
command.Note = "人工判断更合适"
|
||||
if err := validateCandidateHumanReview(command); err != nil {
|
||||
t.Fatalf("validate OTHER note: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCandidateHumanReviewAllowsEmptyNoMatch(t *testing.T) {
|
||||
command := validCandidateHumanReviewCommand()
|
||||
command.Outcome = "NO_MATCH"
|
||||
command.SelectedCandidateOrdinal = nil
|
||||
command.PrimaryReasonCode = "NO_ACCEPTABLE_CANDIDATE"
|
||||
command.Items = nil
|
||||
|
||||
if err := validateCandidateHumanReview(command); err != nil {
|
||||
t.Fatalf("validate empty no-match review: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func validCandidateHumanReviewCommand() StoreCandidateHumanReviewCommand {
|
||||
selected := 1
|
||||
return StoreCandidateHumanReviewCommand{
|
||||
TaskContentSHA256: strings.Repeat("a", 64),
|
||||
ReasonSchemaVersion: 1,
|
||||
Outcome: "CANDIDATE_ACCEPTED",
|
||||
SelectedCandidateOrdinal: &selected,
|
||||
PrimaryReasonCode: "SELECTED_BEST_MATCH",
|
||||
Items: []CandidateHumanReviewItemInput{
|
||||
{
|
||||
CandidateOrdinal: 1,
|
||||
Label: "ACCEPT",
|
||||
PrimaryReasonCode: "SKU_MATCH",
|
||||
ReasonCodes: []string{"SKU_MATCH"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user