- Implement V2 execution model in the standard executor, simplifying task execution to a single call without validation loops. - Introduce support for resuming suspended executions, allowing for human input during task processing. - Enhance event handling by pushing task completion and failure events to the event bus for better tracking and integration. - Update tests to reflect changes in execution flow and ensure robust handling of task statuses and results.
153 lines
3.9 KiB
Go
153 lines
3.9 KiB
Go
package events
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// EP1: ExecPayload with all execution statuses
|
|
func TestExecPayloadAllStatuses(t *testing.T) {
|
|
statuses := []string{
|
|
"running", "completed", "failed", "cancelled", "waiting", "confirming",
|
|
}
|
|
|
|
for _, s := range statuses {
|
|
payload := ExecPayload{
|
|
ExecutionID: "exec-ep1",
|
|
MemberID: "member-ep1",
|
|
TeamID: "team-ep1",
|
|
Status: s,
|
|
}
|
|
|
|
data, err := json.Marshal(payload)
|
|
require.NoError(t, err)
|
|
|
|
var parsed ExecPayload
|
|
err = json.Unmarshal(data, &parsed)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, s, parsed.Status, "Status %s should round-trip", s)
|
|
}
|
|
}
|
|
|
|
// EP2: NeedInputPayload with empty question
|
|
func TestNeedInputPayloadEmptyQuestion(t *testing.T) {
|
|
payload := NeedInputPayload{
|
|
ExecutionID: "exec-ep2",
|
|
MemberID: "member-ep2",
|
|
TeamID: "team-ep2",
|
|
TaskID: "task-ep2",
|
|
Question: "",
|
|
}
|
|
|
|
data, err := json.Marshal(payload)
|
|
require.NoError(t, err)
|
|
|
|
var parsed map[string]interface{}
|
|
err = json.Unmarshal(data, &parsed)
|
|
require.NoError(t, err)
|
|
|
|
// Empty string should be present but empty
|
|
q, ok := parsed["question"]
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "", q)
|
|
}
|
|
|
|
// EP3: TaskPayload serializes error correctly
|
|
func TestTaskPayloadErrorSerialization(t *testing.T) {
|
|
payload := TaskPayload{
|
|
ExecutionID: "exec-ep3",
|
|
MemberID: "member-ep3",
|
|
TeamID: "team-ep3",
|
|
TaskID: "task-ep3",
|
|
Error: "context deadline exceeded",
|
|
}
|
|
|
|
data, err := json.Marshal(payload)
|
|
require.NoError(t, err)
|
|
|
|
var parsed map[string]interface{}
|
|
err = json.Unmarshal(data, &parsed)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "context deadline exceeded", parsed["error"])
|
|
}
|
|
|
|
// EP4: DeliveryPayload with nested content
|
|
func TestDeliveryPayloadNestedContent(t *testing.T) {
|
|
content := map[string]interface{}{
|
|
"report": map[string]interface{}{
|
|
"title": "Daily Summary",
|
|
"sections": []interface{}{"intro", "body", "conclusion"},
|
|
},
|
|
}
|
|
|
|
payload := DeliveryPayload{
|
|
ExecutionID: "exec-ep4",
|
|
MemberID: "member-ep4",
|
|
TeamID: "team-ep4",
|
|
Content: content,
|
|
}
|
|
|
|
data, err := json.Marshal(payload)
|
|
require.NoError(t, err)
|
|
|
|
var parsed DeliveryPayload
|
|
err = json.Unmarshal(data, &parsed)
|
|
require.NoError(t, err)
|
|
|
|
contentMap, ok := parsed.Content.(map[string]interface{})
|
|
require.True(t, ok)
|
|
report, ok := contentMap["report"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
assert.Equal(t, "Daily Summary", report["title"])
|
|
}
|
|
|
|
// EP5: Event constants follow naming convention
|
|
func TestEventConstantNamingConvention(t *testing.T) {
|
|
allEvents := []string{
|
|
TaskNeedInput, TaskFailed, TaskCompleted,
|
|
ExecWaiting, ExecResumed, ExecCompleted, ExecFailed, ExecCancelled,
|
|
Delivery,
|
|
}
|
|
|
|
for _, e := range allEvents {
|
|
assert.Contains(t, e, "robot.", "Event %q should start with 'robot.'", e)
|
|
}
|
|
}
|
|
|
|
// EP6: ExecPayload omits empty ChatID
|
|
func TestExecPayloadOmitsEmptyOptionalFields(t *testing.T) {
|
|
payload := ExecPayload{
|
|
ExecutionID: "exec-ep6",
|
|
MemberID: "member-ep6",
|
|
TeamID: "team-ep6",
|
|
Status: "completed",
|
|
}
|
|
|
|
data, err := json.Marshal(payload)
|
|
require.NoError(t, err)
|
|
|
|
var parsed map[string]interface{}
|
|
err = json.Unmarshal(data, &parsed)
|
|
require.NoError(t, err)
|
|
|
|
_, hasChatID := parsed["chat_id"]
|
|
if hasChatID {
|
|
assert.Equal(t, "", parsed["chat_id"])
|
|
}
|
|
}
|
|
|
|
// EP7: All payloads share common fields (ExecutionID, MemberID, TeamID)
|
|
func TestPayloadCommonFields(t *testing.T) {
|
|
needInput := NeedInputPayload{ExecutionID: "e1", MemberID: "m1", TeamID: "t1"}
|
|
task := TaskPayload{ExecutionID: "e2", MemberID: "m2", TeamID: "t2"}
|
|
exec := ExecPayload{ExecutionID: "e3", MemberID: "m3", TeamID: "t3"}
|
|
delivery := DeliveryPayload{ExecutionID: "e4", MemberID: "m4", TeamID: "t4"}
|
|
|
|
assert.Equal(t, "e1", needInput.ExecutionID)
|
|
assert.Equal(t, "m2", task.MemberID)
|
|
assert.Equal(t, "t3", exec.TeamID)
|
|
assert.Equal(t, "e4", delivery.ExecutionID)
|
|
}
|