feat: add a --save option to avoid the interactive prompt on mire record for save
This commit is contained in:
+8
-2
@@ -11,13 +11,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func newRecordCommand() *cobra.Command {
|
func newRecordCommand() *cobra.Command {
|
||||||
return &cobra.Command{
|
var save bool
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "record <path>",
|
Use: "record <path>",
|
||||||
Short: "Record a new CLI scenario",
|
Short: "Record a new CLI scenario",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
path := filepath.Clean(args[0])
|
path := filepath.Clean(args[0])
|
||||||
createdPath, err := mire.Record(path)
|
createdPath, err := mire.Record(path, mire.RecordOptions{Save: save})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, mire.ErrRecordingDiscarded) {
|
if errors.Is(err, mire.ErrRecordingDiscarded) {
|
||||||
return nil
|
return nil
|
||||||
@@ -30,4 +32,8 @@ func newRecordCommand() *cobra.Command {
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd.Flags().BoolVar(&save, "save", false, "Save the recording without prompting")
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,48 @@ func TestRunRecord(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRunRecordSaveFlagSkipsPrompt(t *testing.T) {
|
||||||
|
testutil.AddFakeRecordDependencies(t, "bwrap", "bash")
|
||||||
|
|
||||||
|
root := t.TempDir()
|
||||||
|
wantDir := filepath.Join(root, "e2e")
|
||||||
|
|
||||||
|
testutil.WithWorkingDir(t, root, func() struct{} {
|
||||||
|
initStdout, initStderr := testutil.CaptureOutput(t, func() {
|
||||||
|
if got := Run([]string{"init"}); got != 0 {
|
||||||
|
t.Fatalf("Run() code = %d, want %d", got, 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if initStdout != prefixed("Done initialising...\n") {
|
||||||
|
t.Fatalf("stdout = %q, want %q", initStdout, prefixed("Done initialising...\n"))
|
||||||
|
}
|
||||||
|
if initStderr != "" {
|
||||||
|
t.Fatalf("stderr = %q, want empty", initStderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout, stderr := testutil.CapturePromptedOutput(t, "exit\n", "", "", func() {
|
||||||
|
if got := Run([]string{"record", "--save", "suite/spec"}); got != 0 {
|
||||||
|
t.Fatalf("Run() code = %d, want %d", got, 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
createdPath := filepath.Join(wantDir, "suite", "spec")
|
||||||
|
if !strings.Contains(stdout, createdPath) {
|
||||||
|
t.Fatalf("stdout = %q, want created path", stdout)
|
||||||
|
}
|
||||||
|
if strings.Contains(stderr, "Save recording?") {
|
||||||
|
t.Fatalf("stderr = %q, want save prompt omitted", stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range []string{"in", "out"} {
|
||||||
|
if _, err := os.Stat(filepath.Join(createdPath, name)); err != nil {
|
||||||
|
t.Fatalf("Stat(%q) error = %v", filepath.Join(createdPath, name), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return struct{}{}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestRunRewrite(t *testing.T) {
|
func TestRunRewrite(t *testing.T) {
|
||||||
testutil.AddFakeRecordDependencies(t, "bwrap", "bash")
|
testutil.AddFakeRecordDependencies(t, "bwrap", "bash")
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type RecordOptions struct {
|
||||||
|
Save bool
|
||||||
|
}
|
||||||
|
|
||||||
// Record creates the requested scenario path under the resolved test directory
|
// Record creates the requested scenario path under the resolved test directory
|
||||||
// and records an interactive shell session into in/out fixtures when saved.
|
// and records an interactive shell session into in/out fixtures when saved.
|
||||||
func Record(path string) (string, error) {
|
func Record(path string, opts RecordOptions) (string, error) {
|
||||||
root, err := currentProjectRoot()
|
root, err := currentProjectRoot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -46,7 +50,7 @@ func Record(path string) (string, error) {
|
|||||||
in: os.Stdin,
|
in: os.Stdin,
|
||||||
out: os.Stdout,
|
out: os.Stdout,
|
||||||
err: os.Stderr,
|
err: os.Stderr,
|
||||||
}, cfg.Sandbox, cfg.Mounts, cfg.Paths, setupScripts); err != nil {
|
}, cfg.Sandbox, cfg.Mounts, cfg.Paths, setupScripts, opts.Save); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ type recordIO struct {
|
|||||||
err io.Writer
|
err io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func recordScenario(target, shellPath string, rio recordIO, sandboxConfig map[string]string, mounts, paths, setupScripts []string) error {
|
func recordScenario(target, shellPath string, rio recordIO, sandboxConfig map[string]string, mounts, paths, setupScripts []string, save bool) error {
|
||||||
rawIn, rawOut, cleanup, err := newRecordFiles()
|
rawIn, rawOut, cleanup, err := newRecordFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -45,13 +45,15 @@ func recordScenario(target, shellPath string, rio recordIO, sandboxConfig map[st
|
|||||||
// as an error
|
// as an error
|
||||||
runRecordSession(target, rawIn, rawOut, shellPath, sandbox, rio, sandboxConfig, mounts, paths, setupScripts)
|
runRecordSession(target, rawIn, rawOut, shellPath, sandbox, rio, sandboxConfig, mounts, paths, setupScripts)
|
||||||
|
|
||||||
save, err := confirmRecordSave(rio)
|
if !save {
|
||||||
|
save, err = confirmRecordSave(rio)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !save {
|
if !save {
|
||||||
return ErrRecordingDiscarded
|
return ErrRecordingDiscarded
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
recordedIn, recordedOut, err := loadRecordedFixtures(rawIn, rawOut)
|
recordedIn, recordedOut, err := loadRecordedFixtures(rawIn, rawOut)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func TestRecordCreatesRelativePath(t *testing.T) {
|
|||||||
var got string
|
var got string
|
||||||
testutil.WithWorkingDir(t, root, func() struct{} {
|
testutil.WithWorkingDir(t, root, func() struct{} {
|
||||||
testutil.CapturePromptedOutput(t, "exit\n", "Save recording?", "y\n", func() {
|
testutil.CapturePromptedOutput(t, "exit\n", "Save recording?", "y\n", func() {
|
||||||
path, err := Record(filepath.Join("a", "b", "c") + string(os.PathSeparator))
|
path, err := Record(filepath.Join("a", "b", "c")+string(os.PathSeparator), RecordOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Record() error = %v", err)
|
t.Fatalf("Record() error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ func TestRecordReturnsDiscardedErrorWhenSaveDeclined(t *testing.T) {
|
|||||||
target := filepath.Join(testDir, "a", "b", "c")
|
target := filepath.Join(testDir, "a", "b", "c")
|
||||||
testutil.MustMkdirAll(t, target)
|
testutil.MustMkdirAll(t, target)
|
||||||
return withRecordStreams(t, "exit\nn\n", func(rio recordIO) error {
|
return withRecordStreams(t, "exit\nn\n", func(rio recordIO) error {
|
||||||
return recordScenario(target, recordShellPath(testDir), rio, defaultSandboxConfig(), nil, nil, nil)
|
return recordScenario(target, recordShellPath(testDir), rio, defaultSandboxConfig(), nil, nil, nil, false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ func TestRecordReturnsDiscardedErrorWhenOverwriteDeclined(t *testing.T) {
|
|||||||
|
|
||||||
err := testutil.WithWorkingDir(t, root, func() error {
|
err := testutil.WithWorkingDir(t, root, func() error {
|
||||||
return withRecordStreams(t, "n\n", func(rio recordIO) error {
|
return withRecordStreams(t, "n\n", func(rio recordIO) error {
|
||||||
return recordScenario(target, recordShellPath(testDir), rio, defaultSandboxConfig(), nil, nil, nil)
|
return recordScenario(target, recordShellPath(testDir), rio, defaultSandboxConfig(), nil, nil, nil, false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -281,7 +281,7 @@ func TestRecordScenarioUsesDeterministicSandbox(t *testing.T) {
|
|||||||
"y\n",
|
"y\n",
|
||||||
func(rio recordIO) error {
|
func(rio recordIO) error {
|
||||||
rio.out = ioDiscard{}
|
rio.out = ioDiscard{}
|
||||||
return recordScenario(target, recordShellPath(testDir), rio, sandboxConfig, nil, nil, nil)
|
return recordScenario(target, recordShellPath(testDir), rio, sandboxConfig, nil, nil, nil, false)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -377,7 +377,7 @@ func TestRecordScenarioStripsInterruptsFromSavedFixtures(t *testing.T) {
|
|||||||
in: reader,
|
in: reader,
|
||||||
out: ioDiscard{},
|
out: ioDiscard{},
|
||||||
err: errWriter,
|
err: errWriter,
|
||||||
}, defaultSandboxConfig(), nil, nil, nil)
|
}, defaultSandboxConfig(), nil, nil, nil, false)
|
||||||
if writeErr := <-writeDone; writeErr != nil {
|
if writeErr := <-writeDone; writeErr != nil {
|
||||||
t.Fatalf("write record input: %v", writeErr)
|
t.Fatalf("write record input: %v", writeErr)
|
||||||
}
|
}
|
||||||
@@ -412,7 +412,7 @@ func TestRecordFailsWhenRecorderShellMissing(t *testing.T) {
|
|||||||
|
|
||||||
target := filepath.Join(testDir, "suite", "spec")
|
target := filepath.Join(testDir, "suite", "spec")
|
||||||
err := testutil.WithWorkingDir(t, root, func() error {
|
err := testutil.WithWorkingDir(t, root, func() error {
|
||||||
_, err := Record(filepath.Join("suite", "spec"))
|
_, err := Record(filepath.Join("suite", "spec"), RecordOptions{})
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user