Skip to content

Commit

Permalink
test: support complex keys like arrow keys
Browse files Browse the repository at this point in the history
  • Loading branch information
majori committed Feb 8, 2024
1 parent a5fae2c commit ae6c253
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 7 deletions.
57 changes: 53 additions & 4 deletions internal/cli/cmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func TestFeatures(t *testing.T) {
s.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
ctx = context.WithValue(ctx, cmdAdditionalFlagsCtxKey{}, make(map[string]string))
ctx = context.WithValue(ctx, dockerResourcesCtxKey{}, []*dockertest.Resource{})
ctx = context.WithValue(ctx, cmdStdInCtxKey{}, new(bytes.Buffer))
ctx = context.WithValue(ctx, cmdStdInCtxKey{}, NewBlockBuffer())

return ctx, nil
})
Expand Down Expand Up @@ -138,7 +138,7 @@ func TestFeatures(t *testing.T) {

func wrapCmdOutputs(ctx context.Context) (context.Context, *cobra.Command) {
rootCmd := cli.NewRootCmd()
cmdStdIn, isInteractive := ctx.Value(cmdStdInCtxKey{}).(*bytes.Buffer)
cmdStdIn, isInteractive := ctx.Value(cmdStdInCtxKey{}).(*BlockBuffer)
if isInteractive {
rootCmd.SetIn(cmdStdIn)
}
Expand Down Expand Up @@ -243,10 +243,11 @@ func aRecipesDirectory(ctx context.Context) (context.Context, error) {
}

func bufferKeysToInput(ctx context.Context, keys string) (context.Context, error) {
stdIn := ctx.Value(cmdStdInCtxKey{}).(*bytes.Buffer)
stdIn := ctx.Value(cmdStdInCtxKey{}).(*BlockBuffer)

keys = strings.Replace(keys, "\\r", "\r", -1)
stdIn.WriteString(keys)
keys = strings.Replace(keys, "\\x1b", "\x1b", -1)
stdIn.Add([]byte(keys))

return context.WithValue(ctx, cmdStdInCtxKey{}, stdIn), nil
}
Expand Down Expand Up @@ -634,3 +635,51 @@ func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{},
return nestedMapLookup(m, ks[1:]...)
}
}

// BlockBuffer represents a buffer that stores blocks of data.
// This is used to simulate user input for the CLI. Using the standard buffer
// would not allow the simulation of complex key presses due to how bubbletea is implemented.
type BlockBuffer struct {
data [][]byte // The blocks of data stored in the buffer.
blockIndex int // The index of the current block.
readIndex int // The index of the next byte to be read.
}

var _ io.Reader = &BlockBuffer{}

func NewBlockBuffer() *BlockBuffer {
return &BlockBuffer{
data: make([][]byte, 0),
blockIndex: 0,
readIndex: 0,
}
}

func (r *BlockBuffer) Add(p []byte) {
r.data = append(r.data, p)
}

func (r *BlockBuffer) Len() int {
s := 0
for i := range r.data {
s += len(r.data[i])
}

return s
}

func (r *BlockBuffer) Read(p []byte) (n int, err error) {
if r.blockIndex >= len(r.data) || r.readIndex >= len(r.data[r.blockIndex]) {
err = io.EOF
return
}

n = copy(p, r.data[r.blockIndex][r.readIndex:])
if n == len(r.data[r.blockIndex]) {
r.blockIndex++
r.readIndex = 0
} else {
r.readIndex += n
}
return
}
3 changes: 1 addition & 2 deletions internal/cli/execute_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cli_test

import (
"bytes"
"context"
"fmt"
"os"
Expand All @@ -20,7 +19,7 @@ func AddExecuteSteps(s *godog.ScenarioContext) {
func iRunExecute(ctx context.Context, recipe string) (context.Context, error) {
projectDir := ctx.Value(projectDirectoryPathCtxKey{}).(string)
additionalFlags := ctx.Value(cmdAdditionalFlagsCtxKey{}).(map[string]string)
stdIn := ctx.Value(cmdStdInCtxKey{}).(*bytes.Buffer)
stdIn := ctx.Value(cmdStdInCtxKey{}).(*BlockBuffer)

ctx, cmd := wrapCmdOutputs(ctx)

Expand Down
2 changes: 1 addition & 1 deletion internal/cli/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func AddUpgradeSteps(s *godog.ScenarioContext) {
func iRunUpgrade(ctx context.Context, recipe string) (context.Context, error) {
projectDir := ctx.Value(projectDirectoryPathCtxKey{}).(string)
additionalFlags := ctx.Value(cmdAdditionalFlagsCtxKey{}).(map[string]string)
stdIn := ctx.Value(cmdStdInCtxKey{}).(*bytes.Buffer)
stdIn := ctx.Value(cmdStdInCtxKey{}).(*BlockBuffer)

ctx, cmd := wrapCmdOutputs(ctx)

Expand Down
14 changes: 14 additions & 0 deletions test/upgrade-recipe.feature
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ Feature: Upgrade sauce
Then CLI produced an output "README.md: override"
And the project directory should contain file "README.md" with "New version"

Scenario: Attempt upgrade when user overrides the locally modified file while using arrow keys
Given a project directory
And a recipes directory
And a recipe "foo" that generates file "README.md"
And I execute recipe "foo"
And I change recipe "foo" to version "v0.0.2"
And I change recipe "foo" template "README.md" to render "New version"
And I change project file "README.md" to contain "Locally modified"
And I buffer key presses "\x1b[C"
And I buffer key presses "\r"
When I upgrade recipe "foo"
Then CLI produced an output "README.md: override"
And the project directory should contain file "README.md" with "New version"

Scenario: Attempt upgrade when new file conflicts with existing manually created file
Given a project directory
And a recipes directory
Expand Down

0 comments on commit ae6c253

Please sign in to comment.