- Core poller: 5min cycle, journal-backed state, signal dispatch - GitHub client: PR fetching, child issue enumeration - 11 action handlers: link/publish/merge/tick/resolve/etc. - core-ide: headless mode + MCP handler + systemd service - 39 tests, all passing
90 lines
2.4 KiB
Go
90 lines
2.4 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/host-uk/core/pkg/jobrunner"
|
|
)
|
|
|
|
func TestTickParent_Match_Good(t *testing.T) {
|
|
h := NewTickParentHandler()
|
|
sig := &jobrunner.PipelineSignal{
|
|
PRState: "MERGED",
|
|
}
|
|
assert.True(t, h.Match(sig))
|
|
}
|
|
|
|
func TestTickParent_Match_Bad_Open(t *testing.T) {
|
|
h := NewTickParentHandler()
|
|
sig := &jobrunner.PipelineSignal{
|
|
PRState: "OPEN",
|
|
}
|
|
assert.False(t, h.Match(sig))
|
|
}
|
|
|
|
func TestTickParent_Execute_Good(t *testing.T) {
|
|
// Save and restore the original execCommand.
|
|
original := execCommand
|
|
defer func() { execCommand = original }()
|
|
|
|
epicBody := "## Tasks\n- [x] #1\n- [ ] #7\n- [ ] #8\n"
|
|
var callCount int
|
|
var editArgs []string
|
|
var closeArgs []string
|
|
|
|
execCommand = func(ctx context.Context, name string, args ...string) *exec.Cmd {
|
|
callCount++
|
|
if callCount == 1 {
|
|
// First call: gh issue view — return the epic body.
|
|
return exec.CommandContext(ctx, "echo", "-n", epicBody)
|
|
}
|
|
if callCount == 2 {
|
|
// Second call: gh issue edit — capture args and succeed.
|
|
editArgs = append([]string{name}, args...)
|
|
return exec.CommandContext(ctx, "echo", "ok")
|
|
}
|
|
// Third call: gh issue close — capture args and succeed.
|
|
closeArgs = append([]string{name}, args...)
|
|
return exec.CommandContext(ctx, "echo", "ok")
|
|
}
|
|
|
|
h := NewTickParentHandler()
|
|
sig := &jobrunner.PipelineSignal{
|
|
RepoOwner: "host-uk",
|
|
RepoName: "core-php",
|
|
EpicNumber: 42,
|
|
ChildNumber: 7,
|
|
PRNumber: 99,
|
|
PRState: "MERGED",
|
|
}
|
|
|
|
result, err := h.Execute(context.Background(), sig)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, result.Success)
|
|
assert.Equal(t, "tick_parent", result.Action)
|
|
assert.Equal(t, 3, callCount, "expected three exec calls: view + edit + close")
|
|
|
|
// Verify the edit args contain the checked checkbox.
|
|
editJoined := strings.Join(editArgs, " ")
|
|
assert.Contains(t, editJoined, "issue")
|
|
assert.Contains(t, editJoined, "edit")
|
|
assert.Contains(t, editJoined, "42")
|
|
assert.Contains(t, editJoined, fmt.Sprintf("-R %s", sig.RepoFullName()))
|
|
assert.Contains(t, editJoined, "- [x] #7")
|
|
|
|
// Verify the close args target the child issue.
|
|
closeJoined := strings.Join(closeArgs, " ")
|
|
assert.Contains(t, closeJoined, "issue")
|
|
assert.Contains(t, closeJoined, "close")
|
|
assert.Contains(t, closeJoined, "7")
|
|
assert.Contains(t, closeJoined, "-R")
|
|
assert.Contains(t, closeJoined, "host-uk/core-php")
|
|
}
|