From 7c99f80c7f44e8c25490bc6e5475d9595528decf Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Thu, 12 Feb 2026 12:40:45 -0500 Subject: [PATCH 1/4] fix: show generated app name in hint line instead of input default --- cmd/project/create.go | 16 +++++++ cmd/project/create_test.go | 90 +++++++++++++++++++++++++++++++++++ internal/iostreams/survey.go | 4 +- internal/pkg/create/create.go | 6 +-- 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/cmd/project/create.go b/cmd/project/create.go index 9a489120..5a163a48 100644 --- a/cmd/project/create.go +++ b/cmd/project/create.go @@ -20,6 +20,7 @@ import ( "path/filepath" "strings" + "github.com/slackapi/slack-cli/internal/iostreams" "github.com/slackapi/slack-cli/internal/logger" "github.com/slackapi/slack-cli/internal/pkg/create" "github.com/slackapi/slack-cli/internal/shared" @@ -127,6 +128,21 @@ func runCreateCommand(clients *shared.ClientFactory, cmd *cobra.Command, args [] return err } + // Prompt for app name if not provided via flag or argument + if appNameArg == "" { + defaultName := create.GenerateRandomAppName() + cmd.Print(style.Secondary(fmt.Sprintf(" Press Enter to use the generated name: %s", defaultName)), "\n") + name, err := clients.IO.InputPrompt(ctx, "Name your app:", iostreams.InputPromptConfig{}) + if err != nil { + return err + } + if name != "" { + appNameArg = name + } else { + appNameArg = defaultName + } + } + // Set up spinners appCreateSpinner = style.NewSpinner(cmd.OutOrStdout()) diff --git a/cmd/project/create_test.go b/cmd/project/create_test.go index 7007f988..e094dd51 100644 --- a/cmd/project/create_test.go +++ b/cmd/project/create_test.go @@ -62,6 +62,8 @@ func TestCreateCommand(t *testing.T) { }, nil, ) + cm.IO.On("InputPrompt", mock.Anything, "Name your app:", mock.Anything). + Return("my-app", nil) createClientMock = new(CreateClientMock) createClientMock.On("Create", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return("", nil) CreateFunc = createClientMock.Create @@ -70,9 +72,11 @@ func TestCreateCommand(t *testing.T) { template, err := create.ResolveTemplateURL("slack-samples/bolt-js-starter-template") require.NoError(t, err) expected := create.CreateArgs{ + AppName: "my-app", Template: template, } createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) + cm.IO.AssertCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) }, }, "creates a deno application from flags": { @@ -94,6 +98,8 @@ func TestCreateCommand(t *testing.T) { }, nil, ) + cm.IO.On("InputPrompt", mock.Anything, "Name your app:", mock.Anything). + Return("my-deno-app", nil) createClientMock = new(CreateClientMock) createClientMock.On("Create", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return("", nil) CreateFunc = createClientMock.Create @@ -102,9 +108,11 @@ func TestCreateCommand(t *testing.T) { template, err := create.ResolveTemplateURL("slack-samples/deno-starter-template") require.NoError(t, err) expected := create.CreateArgs{ + AppName: "my-deno-app", Template: template, } createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) + cm.IO.AssertCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) }, }, "creates an agent app using agent argument shortcut": { @@ -119,6 +127,8 @@ func TestCreateCommand(t *testing.T) { }, nil, ) + cm.IO.On("InputPrompt", mock.Anything, "Name your app:", mock.Anything). + Return("my-agent", nil) createClientMock = new(CreateClientMock) createClientMock.On("Create", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return("", nil) CreateFunc = createClientMock.Create @@ -127,11 +137,13 @@ func TestCreateCommand(t *testing.T) { template, err := create.ResolveTemplateURL("slack-samples/bolt-js-assistant-template") require.NoError(t, err) expected := create.CreateArgs{ + AppName: "my-agent", Template: template, } createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) // Verify that category prompt was NOT called cm.IO.AssertNotCalled(t, "SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything) + cm.IO.AssertCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) }, }, "creates an agent app with app name using agent argument": { @@ -160,6 +172,8 @@ func TestCreateCommand(t *testing.T) { createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) // Verify that category prompt was NOT called cm.IO.AssertNotCalled(t, "SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything) + // Verify that name prompt was NOT called since name was provided as arg + cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) }, }, "creates an app named agent when template flag is provided": { @@ -193,6 +207,8 @@ func TestCreateCommand(t *testing.T) { Template: template, } createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) + // Verify that name prompt was NOT called since name was provided as arg + cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) }, }, "creates an app named agent using name flag without triggering shortcut": { @@ -229,6 +245,8 @@ func TestCreateCommand(t *testing.T) { createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) // Verify that category prompt WAS called (shortcut was not triggered) cm.IO.AssertCalled(t, "SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything) + // Verify that name prompt was NOT called since --name flag was provided + cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) }, }, "creates an agent app with name flag overriding positional arg": { @@ -290,6 +308,8 @@ func TestCreateCommand(t *testing.T) { Template: template, } createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) + // Verify that name prompt was NOT called since --name flag was provided + cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) }, }, "name flag overrides positional app name argument with agent shortcut": { @@ -318,6 +338,76 @@ func TestCreateCommand(t *testing.T) { createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) // Verify that category prompt was NOT called (agent shortcut was triggered) cm.IO.AssertNotCalled(t, "SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything) + // Verify that name prompt was NOT called since --name flag was provided + cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) + }, + }, + "user accepts default name from prompt": { + Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) { + cm.IO.On("SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything). + Return( + iostreams.SelectPromptResponse{ + Prompt: true, + Index: 0, + }, + nil, + ) + cm.IO.On("SelectPrompt", mock.Anything, "Select a language:", mock.Anything, mock.Anything). + Return( + iostreams.SelectPromptResponse{ + Prompt: true, + Index: 0, + }, + nil, + ) + // Return empty string to simulate pressing Enter (accepting default) + cm.IO.On("InputPrompt", mock.Anything, "Name your app:", mock.Anything). + Return("", nil) + createClientMock = new(CreateClientMock) + createClientMock.On("Create", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return("", nil) + CreateFunc = createClientMock.Create + }, + ExpectedAsserts: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock) { + cm.IO.AssertCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) + // When the user accepts the default (empty return), the generated name is used + createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, mock.MatchedBy(func(args create.CreateArgs) bool { + return args.AppName != "" + })) + }, + }, + "positional arg skips name prompt": { + CmdArgs: []string{"my-project"}, + Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) { + cm.IO.On("SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything). + Return( + iostreams.SelectPromptResponse{ + Prompt: true, + Index: 0, + }, + nil, + ) + cm.IO.On("SelectPrompt", mock.Anything, "Select a language:", mock.Anything, mock.Anything). + Return( + iostreams.SelectPromptResponse{ + Prompt: true, + Index: 0, + }, + nil, + ) + createClientMock = new(CreateClientMock) + createClientMock.On("Create", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return("", nil) + CreateFunc = createClientMock.Create + }, + ExpectedAsserts: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock) { + template, err := create.ResolveTemplateURL("slack-samples/bolt-js-starter-template") + require.NoError(t, err) + expected := create.CreateArgs{ + AppName: "my-project", + Template: template, + } + createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, expected) + // Verify that name prompt was NOT called since name was provided as positional arg + cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) }, }, }, func(cf *shared.ClientFactory) *cobra.Command { diff --git a/internal/iostreams/survey.go b/internal/iostreams/survey.go index 1f26f79e..f804633c 100644 --- a/internal/iostreams/survey.go +++ b/internal/iostreams/survey.go @@ -175,7 +175,8 @@ var InputQuestionTemplate = fmt.Sprintf(` // InputPromptConfig holds additional config for an Input prompt type InputPromptConfig struct { - Required bool // Whether the input must be non-empty + Required bool // Whether the input must be non-empty + Default string // Default value pre-filled in the prompt } // GetFlags returns all flags for the Input prompt @@ -200,6 +201,7 @@ func (io *IOStreams) InputPrompt(ctx context.Context, message string, cfg InputP var input string err := survey.AskOne(&survey.Input{ Message: message, + Default: cfg.Default, }, &input, SurveyOptions(cfg)...) if err != nil { diff --git a/internal/pkg/create/create.go b/internal/pkg/create/create.go index 6e37f41b..335a4ced 100644 --- a/internal/pkg/create/create.go +++ b/internal/pkg/create/create.go @@ -150,8 +150,8 @@ func Create(ctx context.Context, clients *shared.ClientFactory, log *logger.Logg return appDirPath, nil } -// generateRandomAppName will create a random app name based on two words and a number -func generateRandomAppName() string { +// GenerateRandomAppName will create a random app name based on two words and a number +func GenerateRandomAppName() string { rand.New(rand.NewSource(time.Now().UnixNano())) var firstRandomNum = rand.Intn(len(adjectives)) var secondRandomNum = rand.Intn(len(animals)) @@ -162,7 +162,7 @@ func generateRandomAppName() string { // getAppDirName will validate and return the app's directory name func getAppDirName(appName string) (string, error) { if len(appName) <= 0 { - return generateRandomAppName(), nil + return GenerateRandomAppName(), nil } // trim whitespace From af97eca70d91427199c072ffb9e1416a36608db5 Mon Sep 17 00:00:00 2001 From: Ale Mercado <104795114+srtaalej@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:45:42 -0500 Subject: [PATCH 2/4] Update cmd/project/create.go Co-authored-by: Eden Zimbelman --- cmd/project/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/project/create.go b/cmd/project/create.go index 5a163a48..61414a5a 100644 --- a/cmd/project/create.go +++ b/cmd/project/create.go @@ -129,7 +129,7 @@ func runCreateCommand(clients *shared.ClientFactory, cmd *cobra.Command, args [] } // Prompt for app name if not provided via flag or argument - if appNameArg == "" { + if appNameArg == "" && clients.IO.IsTTY() { defaultName := create.GenerateRandomAppName() cmd.Print(style.Secondary(fmt.Sprintf(" Press Enter to use the generated name: %s", defaultName)), "\n") name, err := clients.IO.InputPrompt(ctx, "Name your app:", iostreams.InputPromptConfig{}) From 5ed7e88e4963225a331f79d5cc5a5c7933da59ef Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Wed, 18 Feb 2026 17:02:59 -0500 Subject: [PATCH 3/4] fix: update imports in cmd/ --- cmd/project/create.go | 13 ++++++++++++- cmd/project/create_test.go | 4 ++++ internal/iostreams/survey.go | 4 +--- internal/pkg/create/constants.go | 4 ++-- internal/pkg/create/create.go | 16 +++------------- internal/pkg/create/create_test.go | 20 +++++++++++++++++--- 6 files changed, 39 insertions(+), 22 deletions(-) diff --git a/cmd/project/create.go b/cmd/project/create.go index 61414a5a..cb961a79 100644 --- a/cmd/project/create.go +++ b/cmd/project/create.go @@ -17,8 +17,10 @@ package project import ( "context" "fmt" + "math/rand" "path/filepath" "strings" + "time" "github.com/slackapi/slack-cli/internal/iostreams" "github.com/slackapi/slack-cli/internal/logger" @@ -130,7 +132,7 @@ func runCreateCommand(clients *shared.ClientFactory, cmd *cobra.Command, args [] // Prompt for app name if not provided via flag or argument if appNameArg == "" && clients.IO.IsTTY() { - defaultName := create.GenerateRandomAppName() + defaultName := generateRandomAppName() cmd.Print(style.Secondary(fmt.Sprintf(" Press Enter to use the generated name: %s", defaultName)), "\n") name, err := clients.IO.InputPrompt(ctx, "Name your app:", iostreams.InputPromptConfig{}) if err != nil { @@ -286,6 +288,15 @@ func printCreateSuccess(ctx context.Context, clients *shared.ClientFactory, appP clients.IO.PrintTrace(ctx, slacktrace.CreateSuccess) } +// generateRandomAppName will create a random app name based on two words and a number +func generateRandomAppName() string { + rand.New(rand.NewSource(time.Now().UnixNano())) + var firstRandomNum = rand.Intn(len(create.Adjectives)) + var secondRandomNum = rand.Intn(len(create.Animals)) + var randomName = fmt.Sprintf("%s-%s-%d", create.Adjectives[firstRandomNum], create.Animals[secondRandomNum], rand.Intn(1000)) + return randomName +} + // printAppCreateError stops the creation spinners and displays the returned error message func printAppCreateError(clients *shared.ClientFactory, cmd *cobra.Command, err error) { ctx := cmd.Context() diff --git a/cmd/project/create_test.go b/cmd/project/create_test.go index e094dd51..1033f17d 100644 --- a/cmd/project/create_test.go +++ b/cmd/project/create_test.go @@ -46,6 +46,7 @@ func TestCreateCommand(t *testing.T) { testutil.TableTestCommand(t, testutil.CommandTests{ "creates a bolt application from prompts": { Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) { + cm.IO.On("IsTTY").Return(true) cm.IO.On("SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything). Return( iostreams.SelectPromptResponse{ @@ -82,6 +83,7 @@ func TestCreateCommand(t *testing.T) { "creates a deno application from flags": { CmdArgs: []string{"--template", "slack-samples/deno-starter-template"}, Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) { + cm.IO.On("IsTTY").Return(true) cm.IO.On("SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything). Return( iostreams.SelectPromptResponse{ @@ -118,6 +120,7 @@ func TestCreateCommand(t *testing.T) { "creates an agent app using agent argument shortcut": { CmdArgs: []string{"agent"}, Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) { + cm.IO.On("IsTTY").Return(true) // Should skip category prompt and go directly to language selection cm.IO.On("SelectPrompt", mock.Anything, "Select a language:", mock.Anything, mock.Anything). Return( @@ -344,6 +347,7 @@ func TestCreateCommand(t *testing.T) { }, "user accepts default name from prompt": { Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) { + cm.IO.On("IsTTY").Return(true) cm.IO.On("SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything). Return( iostreams.SelectPromptResponse{ diff --git a/internal/iostreams/survey.go b/internal/iostreams/survey.go index f804633c..1f26f79e 100644 --- a/internal/iostreams/survey.go +++ b/internal/iostreams/survey.go @@ -175,8 +175,7 @@ var InputQuestionTemplate = fmt.Sprintf(` // InputPromptConfig holds additional config for an Input prompt type InputPromptConfig struct { - Required bool // Whether the input must be non-empty - Default string // Default value pre-filled in the prompt + Required bool // Whether the input must be non-empty } // GetFlags returns all flags for the Input prompt @@ -201,7 +200,6 @@ func (io *IOStreams) InputPrompt(ctx context.Context, message string, cfg InputP var input string err := survey.AskOne(&survey.Input{ Message: message, - Default: cfg.Default, }, &input, SurveyOptions(cfg)...) if err != nil { diff --git a/internal/pkg/create/constants.go b/internal/pkg/create/constants.go index 992e30d3..2ba866cf 100644 --- a/internal/pkg/create/constants.go +++ b/internal/pkg/create/constants.go @@ -14,7 +14,7 @@ package create -var adjectives = []string{ +var Adjectives = []string{ "admiring", "adoring", "affectionate", @@ -113,7 +113,7 @@ var adjectives = []string{ "zen", } -var animals = []string{ +var Animals = []string{ "aardvark", "alligator", "alpaca", diff --git a/internal/pkg/create/create.go b/internal/pkg/create/create.go index 335a4ced..0011867f 100644 --- a/internal/pkg/create/create.go +++ b/internal/pkg/create/create.go @@ -18,13 +18,11 @@ import ( "context" "fmt" "io" - "math/rand" "net/http" "os" "os/exec" "path/filepath" "strings" - "time" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" @@ -150,23 +148,15 @@ func Create(ctx context.Context, clients *shared.ClientFactory, log *logger.Logg return appDirPath, nil } -// GenerateRandomAppName will create a random app name based on two words and a number -func GenerateRandomAppName() string { - rand.New(rand.NewSource(time.Now().UnixNano())) - var firstRandomNum = rand.Intn(len(adjectives)) - var secondRandomNum = rand.Intn(len(animals)) - var randomName = fmt.Sprintf("%s-%s-%d", adjectives[firstRandomNum], animals[secondRandomNum], rand.Intn(1000)) - return randomName -} - // getAppDirName will validate and return the app's directory name func getAppDirName(appName string) (string, error) { if len(appName) <= 0 { - return GenerateRandomAppName(), nil + return "", fmt.Errorf("app name is required") } // trim whitespace - appName = strings.ReplaceAll(appName, " ", "") + appName = strings.TrimSpace(appName) + appName = strings.ReplaceAll(appName, " ", "-") // name cannot be a reserved word if goutils.Contains(reserved, appName, false) { diff --git a/internal/pkg/create/create_test.go b/internal/pkg/create/create_test.go index 67b8991d..13c30d42 100644 --- a/internal/pkg/create/create_test.go +++ b/internal/pkg/create/create_test.go @@ -39,16 +39,30 @@ func TestGetProjectDirectoryName(t *testing.T) { var appName string var err error - // Test without app name test removed because more than one possible default name + // Test with empty name returns an error + appName, err = getAppDirName("") + assert.Error(t, err, "should return an error for empty name") + assert.Equal(t, "", appName) + // Test with app name appName, err = getAppDirName("my-app") assert.NoError(t, err, "should not return an error") - assert.Equal(t, appName, "my-app", "should return 'my-app'") + assert.Equal(t, "my-app", appName, "should return 'my-app'") // Test with a dot in the app name appName, err = getAppDirName(".my-app") assert.NoError(t, err, "should not return an error") - assert.Equal(t, appName, ".my-app", "should return '.my-app'") + assert.Equal(t, ".my-app", appName, "should return '.my-app'") + + // Spaces replaced with hyphens + appName, err = getAppDirName("my cool app") + assert.NoError(t, err) + assert.Equal(t, "my-cool-app", appName) + + // Leading/trailing spaces trimmed + appName, err = getAppDirName(" my-app ") + assert.NoError(t, err) + assert.Equal(t, "my-app", appName) } func TestGetAvailableDirectory(t *testing.T) { From a1203961675aa8ea12ad00e629b3f02128add9a2 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Thu, 19 Feb 2026 13:23:45 -0500 Subject: [PATCH 4/4] fix: edge case --- cmd/project/create.go | 24 ++++++++++++++---------- cmd/project/create_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/cmd/project/create.go b/cmd/project/create.go index 4ecd3ea5..d4be7ede 100644 --- a/cmd/project/create.go +++ b/cmd/project/create.go @@ -138,17 +138,21 @@ func runCreateCommand(clients *shared.ClientFactory, cmd *cobra.Command, args [] } // Prompt for app name if not provided via flag or argument - if appNameArg == "" && clients.IO.IsTTY() { - defaultName := generateRandomAppName() - cmd.Print(style.Secondary(fmt.Sprintf(" Press Enter to use the generated name: %s", defaultName)), "\n") - name, err := clients.IO.InputPrompt(ctx, "Name your app:", iostreams.InputPromptConfig{}) - if err != nil { - return err - } - if name != "" { - appNameArg = name + if appNameArg == "" { + if clients.IO.IsTTY() { + defaultName := generateRandomAppName() + cmd.Print(style.Secondary(fmt.Sprintf(" Press Enter to use the generated name: %s", defaultName)), "\n") + name, err := clients.IO.InputPrompt(ctx, "Name your app:", iostreams.InputPromptConfig{}) + if err != nil { + return err + } + if name != "" { + appNameArg = name + } else { + appNameArg = defaultName + } } else { - appNameArg = defaultName + appNameArg = generateRandomAppName() } } diff --git a/cmd/project/create_test.go b/cmd/project/create_test.go index 6f3a3b47..5109d6a5 100644 --- a/cmd/project/create_test.go +++ b/cmd/project/create_test.go @@ -379,6 +379,39 @@ func TestCreateCommand(t *testing.T) { })) }, }, + "non-TTY without name falls back to generated name": { + CmdArgs: []string{"--template", "slack-samples/bolt-js-starter-template"}, + Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) { + // IsTTY defaults to false via AddDefaultMocks, simulating piped output + cm.IO.On("SelectPrompt", mock.Anything, "Select an app:", mock.Anything, mock.Anything). + Return( + iostreams.SelectPromptResponse{ + Flag: true, + Option: "slack-samples/bolt-js-starter-template", + }, + nil, + ) + cm.IO.On("SelectPrompt", mock.Anything, "Select a language:", mock.Anything, mock.Anything). + Return( + iostreams.SelectPromptResponse{ + Flag: true, + Option: "slack-samples/bolt-js-starter-template", + }, + nil, + ) + createClientMock = new(CreateClientMock) + createClientMock.On("Create", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return("", nil) + CreateFunc = createClientMock.Create + }, + ExpectedAsserts: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock) { + // Should NOT prompt for name since not a TTY + cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything) + // Should still call Create with a non-empty generated name + createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.Anything, mock.MatchedBy(func(args create.CreateArgs) bool { + return args.AppName != "" + })) + }, + }, "positional arg skips name prompt": { CmdArgs: []string{"my-project"}, Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {