mirror of
https://github.com/zoriya/jjui.git
synced 2026-08-16 02:44:50 +00:00
145 lines
3.5 KiB
Go
145 lines
3.5 KiB
Go
package test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"slices"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/idursun/jjui/internal/config"
|
|
appContext "github.com/idursun/jjui/internal/ui/context"
|
|
|
|
tea "charm.land/bubbletea/v2"
|
|
"github.com/idursun/jjui/internal/ui/common"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
type ExpectedCommand struct {
|
|
args []string
|
|
output []byte
|
|
called bool
|
|
err error
|
|
}
|
|
|
|
func (e *ExpectedCommand) SetOutput(output []byte) *ExpectedCommand {
|
|
e.output = output
|
|
return e
|
|
}
|
|
|
|
func (e *ExpectedCommand) SetError(err error) *ExpectedCommand {
|
|
e.err = err
|
|
return e
|
|
}
|
|
|
|
type CommandRunner struct {
|
|
*testing.T
|
|
expectations map[string][]*ExpectedCommand
|
|
mutex sync.Mutex
|
|
}
|
|
|
|
func (t *CommandRunner) RunCommandImmediate(args []string) ([]byte, error) {
|
|
t.mutex.Lock()
|
|
defer t.mutex.Unlock()
|
|
|
|
subCommand := args[0]
|
|
expectations, ok := t.expectations[subCommand]
|
|
if !ok || len(expectations) == 0 {
|
|
assert.Fail(t, "unexpected command", subCommand)
|
|
}
|
|
|
|
for _, e := range expectations {
|
|
if slices.Equal(e.args, args) {
|
|
e.called = true
|
|
return e.output, e.err
|
|
}
|
|
}
|
|
assert.Fail(t, "unexpected command", subCommand)
|
|
return nil, nil
|
|
}
|
|
|
|
func (t *CommandRunner) RunCommandImmediateWithEnv(args []string, _ []string) ([]byte, error) {
|
|
return t.RunCommandImmediate(args)
|
|
}
|
|
|
|
func (t *CommandRunner) RunCommandStreaming(_ context.Context, args []string) (*appContext.StreamingCommand, error) {
|
|
reader, err := t.RunCommandImmediate(args)
|
|
return &appContext.StreamingCommand{
|
|
ReadCloser: io.NopCloser(bytes.NewReader(reader)),
|
|
ErrPipe: nil,
|
|
}, err
|
|
}
|
|
|
|
func (t *CommandRunner) RunCommandWithInput(args []string, input string, continuations ...tea.Cmd) tea.Cmd {
|
|
cmds := make([]tea.Cmd, 0)
|
|
cmds = append(cmds, func() tea.Msg {
|
|
output, err := t.RunCommandImmediate(args)
|
|
return common.CommandCompletedMsg{Output: string(output), Err: err}
|
|
})
|
|
cmds = append(cmds, continuations...)
|
|
return tea.Batch(cmds...)
|
|
}
|
|
|
|
func (t *CommandRunner) RunCommand(args []string, continuations ...tea.Cmd) tea.Cmd {
|
|
cmds := make([]tea.Cmd, 0)
|
|
cmds = append(cmds, func() tea.Msg {
|
|
output, err := t.RunCommandImmediate(args)
|
|
return common.CommandCompletedMsg{Output: string(output), Err: err}
|
|
})
|
|
cmds = append(cmds, continuations...)
|
|
return tea.Batch(cmds...)
|
|
}
|
|
|
|
func (t *CommandRunner) RunInteractiveCommand(args []string, continuation tea.Cmd) tea.Cmd {
|
|
return t.RunCommand(args, continuation)
|
|
}
|
|
|
|
func (t *CommandRunner) Expect(args []string) *ExpectedCommand {
|
|
subCommand := args[0]
|
|
if _, ok := t.expectations[subCommand]; !ok {
|
|
t.expectations[subCommand] = make([]*ExpectedCommand, 0)
|
|
}
|
|
e := &ExpectedCommand{
|
|
args: args,
|
|
}
|
|
t.expectations[subCommand] = append(t.expectations[subCommand], e)
|
|
return e
|
|
}
|
|
|
|
func (t *CommandRunner) Verify() {
|
|
for subCommand, subCommandExpectations := range t.expectations {
|
|
for _, e := range subCommandExpectations {
|
|
if !e.called {
|
|
assert.Fail(t, "expected command not called", subCommand)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *CommandRunner) IsVerified() bool {
|
|
for _, subCommandExpectations := range t.expectations {
|
|
for _, e := range subCommandExpectations {
|
|
if !e.called {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func NewTestCommandRunner(t *testing.T) *CommandRunner {
|
|
return &CommandRunner{
|
|
T: t,
|
|
expectations: make(map[string][]*ExpectedCommand),
|
|
}
|
|
}
|
|
|
|
func NewTestContext(commandRunner appContext.CommandRunner) *appContext.MainContext {
|
|
return &appContext.MainContext{
|
|
CommandRunner: commandRunner,
|
|
JJConfig: &config.JJConfig{},
|
|
SelectedItem: nil,
|
|
}
|
|
}
|