Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions cmd/help/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func HelpFunc(
if help, _ := clients.Config.Flags.GetBool("help"); help {
clients.Config.LoadExperiments(ctx, clients.IO.PrintDebug)
}
style.ToggleCharm(clients.Config.WithExperimentOn(experiment.Charm))
experiments := []string{}
for _, exp := range clients.Config.GetExperiments() {
if experiment.Includes(exp) {
Expand Down Expand Up @@ -66,15 +67,64 @@ func PrintHelpTemplate(cmd *cobra.Command, data style.TemplateData) {
cmd.PrintErrln(err)
}
cmd.Long = cmdLongF.String()
tmpl := helpTemplate
tmpl := legacyHelpTemplate
if style.IsCharmEnabled() {
tmpl = charmHelpTemplate
}
err = style.PrintTemplate(cmd.OutOrStdout(), tmpl, templateInfo{cmd, data})
if err != nil {
cmd.PrintErrln(err)
}
}

// helpTemplate formats values and information for a helpful output
const helpTemplate string = `{{.Long}}
// ════════════════════════════════════════════════════════════════════════════════
// Charm help template — lipgloss styling
// ════════════════════════════════════════════════════════════════════════════════

const charmHelpTemplate string = `{{.Long | ToDescription}}

{{Header "Usage"}}{{if .Runnable}}
{{ToPrompt "$ "}}{{ToCommandText .UseLine}}{{end}}{{if gt (len .Aliases) 0}}

{{Header "Aliases"}}
{{.NameAndAliases | ToCommandText}}{{end}}{{if .HasAvailableSubCommands}}

{{if eq .Name (GetProcessName)}}{{Header "Commands"}}{{range .Commands}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}
{{.Name | ToGroupName }}{{range .Commands}}{{if (not .Hidden)}}
{{rpad .Name .NamePadding | ToCommandText}} {{.Short | ToDescription}}{{end}}{{end}}{{end}}{{end}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}{{range .Commands}}{{if and (not .HasAvailableSubCommands) (not .Hidden)}}{{if not (IsAlias .Name $.Data.Aliases)}}
{{(rpad .Name .NamePadding) | ToGroupName }}{{.Short | ToDescription}}{{end}}{{end}}{{end}}{{end}}{{else}}{{Header "Subcommands"}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}{{range .Commands}}{{if not .HasAvailableSubCommands}}
{{(rpad .Name .NamePadding) | ToCommandText }} {{.Short | ToDescription}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}

{{Header "Flags"}}
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces | ToFlags}}{{end}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}{{if or (HasAliasSubcommands .Name .Data.Aliases) (eq .Name (GetProcessName))}}

{{Header "Global aliases"}}{{range .Commands}}{{if and (IsAlias .Name $.Data.Aliases) (not .Hidden)}}
{{(rpad .Name .NamePadding) | ToGroupName }} {{rpad (AliasParent .Name $.Data.Aliases) AliasPadding | ToAliasParent}} {{ToPrompt "❱"}} {{.Name | ToGroupName}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableInheritedFlags}}

{{Header "Global flags"}}
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces | ToFlags}}{{end}}{{if .HasExample}}

{{Header "Example"}}
{{ Examples .Example}}{{end}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}

{{Header "Experiments"}}
{{ Experiments .Data.Experiments }}

{{Header "Additional help"}}
{{ToSecondary "For more information about a specific command, run:"}}
{{ToPrompt "$ "}}{{ToCommandText .CommandPath}}{{if eq .Name (GetProcessName)}}{{ToCommandText " <command>"}}{{end}}{{ToCommandText " <subcommand> --help"}}

{{ToSecondary "For guides and documentation, head over to "}}{{LinkText "https://docs.slack.dev/tools/slack-cli"}}{{end}}

`

// ════════════════════════════════════════════════════════════════════════════════
// DEPRECATED: Legacy help template — aurora styling
//
// Delete this entire block when the charm experiment is permanently enabled.
// ════════════════════════════════════════════════════════════════════════════════

const legacyHelpTemplate string = `{{.Long}}

{{Header "Usage"}}{{if .Runnable}}
$ {{.UseLine}}{{end}}{{if gt (len .Aliases) 0}}
Expand Down
4 changes: 2 additions & 2 deletions cmd/manifest/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ func NewValidateCommand(clients *shared.ClientFactory) *cobra.Command {
cmd.Printf(
"\n%s: %s\n",
style.Bold("App Manifest Validation Result"),
style.Styler().Green("Valid"),
style.Green("Valid"),
)
clients.IO.PrintTrace(ctx, slacktrace.ManifestValidateSuccess)
} else {
cmd.Printf(
"\n%s: %s\n",
style.Bold("App Manifest Validation Result"),
style.Styler().Red("InValid"),
style.Red("InValid"),
)
}
return nil
Expand Down
34 changes: 29 additions & 5 deletions cmd/manifest/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ type ManifestValidatePkgMock struct {
}

func (m *ManifestValidatePkgMock) ManifestValidate(ctx context.Context, clients *shared.ClientFactory, app types.App, token string) (bool, slackerror.Warnings, error) {
m.Called(ctx, clients, app, token)
return true, nil, nil
args := m.Called(ctx, clients, app, token)
return args.Bool(0), nil, args.Error(2)
}

func TestManifestValidateCommand(t *testing.T) {
Expand All @@ -63,7 +63,7 @@ func TestManifestValidateCommand(t *testing.T) {
manifestValidatePkgMock := new(ManifestValidatePkgMock)
manifestValidateFunc = manifestValidatePkgMock.ManifestValidate

manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil, nil)
err := cmd.ExecuteContext(ctx)
if err != nil {
assert.Fail(t, "cmd.Execute had unexpected error")
Expand Down Expand Up @@ -138,7 +138,7 @@ func TestManifestValidateCommand_HandleMissingAppInstallError_OneUserAuth(t *tes
// Mock the manifest validate package
manifestValidatePkgMock := new(ManifestValidatePkgMock)
manifestValidateFunc = manifestValidatePkgMock.ManifestValidate
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil, nil)

// Should execute without error
err := cmd.ExecuteContext(ctx)
Expand Down Expand Up @@ -200,14 +200,38 @@ func TestManifestValidateCommand_HandleMissingAppInstallError_MoreThanOneUserAut
// Mock the manifest validate package
manifestValidatePkgMock := new(ManifestValidatePkgMock)
manifestValidateFunc = manifestValidatePkgMock.ManifestValidate
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil, nil)

// Should execute without error
err := cmd.ExecuteContext(ctx)
require.NoError(t, err)
clientsMock.Auth.AssertCalled(t, "SetSelectedAuth", mock.Anything, mock.Anything, mock.Anything, mock.Anything)
}

func TestManifestValidateCommand_InvalidManifest(t *testing.T) {
ctx := slackcontext.MockContext(t.Context())
clientsMock := shared.NewClientsMock()
clientsMock.AddDefaultMocks()

clients := shared.NewClientFactory(clientsMock.MockClientFactory(), func(clients *shared.ClientFactory) {
clients.SDKConfig = hooks.NewSDKConfigMock()
})

cmd := NewValidateCommand(clients)
testutil.MockCmdIO(clients.IO, cmd)

appSelectMock := prompts.NewAppSelectMock()
appSelectPromptFunc = appSelectMock.AppSelectPrompt
appSelectMock.On("AppSelectPrompt", mock.Anything, mock.Anything, prompts.ShowAllEnvironments, prompts.ShowInstalledAppsOnly).Return(prompts.SelectedApp{}, nil)

manifestValidatePkgMock := new(ManifestValidatePkgMock)
manifestValidateFunc = manifestValidatePkgMock.ManifestValidate
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(false, nil, nil)

err := cmd.ExecuteContext(ctx)
require.NoError(t, err)
}

func TestManifestValidateCommand_HandleOtherErrors(t *testing.T) {
// Create mocks
ctx := slackcontext.MockContext(t.Context())
Expand Down
2 changes: 1 addition & 1 deletion cmd/project/create_template_charm.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
"context"
"strings"

"github.com/charmbracelet/huh"
huh "charm.land/huh/v2"
"github.com/slackapi/slack-cli/internal/shared"
"github.com/slackapi/slack-cli/internal/slackerror"
"github.com/slackapi/slack-cli/internal/slacktrace"
Expand Down
44 changes: 22 additions & 22 deletions cmd/project/create_template_charm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import (
"fmt"
"testing"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/huh"
tea "charm.land/bubbletea/v2"
huh "charm.land/huh/v2"
"github.com/charmbracelet/x/ansi"
"github.com/slackapi/slack-cli/internal/shared"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -77,7 +77,7 @@ func TestBuildTemplateSelectionForm(t *testing.T) {
doAllUpdates(f, f.Init())

// Submit first option (Starter app -> getting-started)
_, cmd := f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd := f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)

view := ansi.Strip(f.View())
Expand All @@ -95,13 +95,13 @@ func TestBuildTemplateSelectionForm(t *testing.T) {
doAllUpdates(f, f.Init())

// Navigate down to "View more samples" (4th option, index 3)
_, cmd := f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd := f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)

assert.Equal(t, viewMoreSamples, category)
Expand All @@ -119,11 +119,11 @@ func TestBuildTemplateSelectionForm(t *testing.T) {
doAllUpdates(f, f.Init())

// Navigate to Automation app (3rd option, index 2) and submit
_, cmd := f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd := f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)

view := ansi.Strip(f.View())
Expand All @@ -140,10 +140,10 @@ func TestBuildTemplateSelectionForm(t *testing.T) {
doAllUpdates(f, f.Init())

// Select first category (Starter app)
_, cmd := f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd := f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
// Select first template (Bolt for JavaScript)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)

assert.Equal(t, "slack-cli#getting-started", category)
Expand Down Expand Up @@ -176,10 +176,10 @@ func TestCharmPromptTemplateSelection(t *testing.T) {
runForm = func(f *huh.Form) error {
doAllUpdates(f, f.Init())
// Select first category (Starter app)
_, cmd := f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd := f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
// Select first template (Bolt for JavaScript)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
return nil
}
Expand Down Expand Up @@ -212,16 +212,16 @@ func TestCharmPromptTemplateSelection(t *testing.T) {
runForm = func(f *huh.Form) error {
doAllUpdates(f, f.Init())
// Navigate to "View more samples" (4th option)
_, cmd := f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd := f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
// Select "Browse sample gallery..."
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
return nil
}
Expand All @@ -240,12 +240,12 @@ func TestCharmPromptTemplateSelection(t *testing.T) {
runForm = func(f *huh.Form) error {
doAllUpdates(f, f.Init())
// Navigate to "AI Agent app" (2nd option)
_, cmd := f.Update(tea.KeyMsg{Type: tea.KeyDown})
_, cmd := f.Update(tea.KeyPressMsg{Code: tea.KeyDown})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
// Select first template (Bolt for JavaScript)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
return nil
}
Expand Down
8 changes: 4 additions & 4 deletions cmd/project/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import (
"fmt"
"testing"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/huh"
tea "charm.land/bubbletea/v2"
huh "charm.land/huh/v2"
"github.com/slackapi/slack-cli/internal/config"
"github.com/slackapi/slack-cli/internal/experiment"
"github.com/slackapi/slack-cli/internal/iostreams"
Expand Down Expand Up @@ -573,9 +573,9 @@ func TestCreateCommand(t *testing.T) {
runForm = func(f *huh.Form) error {
doAllUpdates(f, f.Init())
// Select first category (Starter app) then first template (Bolt for JS)
_, cmd := f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd := f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
_, cmd = f.Update(tea.KeyMsg{Type: tea.KeyEnter})
_, cmd = f.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
doAllUpdates(f, cmd)
return nil
}
Expand Down
4 changes: 3 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"strings"
"syscall"

"github.com/charmbracelet/huh"
huh "charm.land/huh/v2"
"github.com/slackapi/slack-cli/cmd/app"
"github.com/slackapi/slack-cli/cmd/auth"
"github.com/slackapi/slack-cli/cmd/collaborators"
Expand All @@ -44,6 +44,7 @@ import (
"github.com/slackapi/slack-cli/cmd/upgrade"
versioncmd "github.com/slackapi/slack-cli/cmd/version"
"github.com/slackapi/slack-cli/internal/cmdutil"
"github.com/slackapi/slack-cli/internal/experiment"
"github.com/slackapi/slack-cli/internal/iostreams"
"github.com/slackapi/slack-cli/internal/pkg/version"
"github.com/slackapi/slack-cli/internal/shared"
Expand Down Expand Up @@ -297,6 +298,7 @@ func InitConfig(ctx context.Context, clients *shared.ClientFactory, rootCmd *cob

// Init configurations
clients.Config.LoadExperiments(ctx, clients.IO.PrintDebug)
style.ToggleCharm(clients.Config.WithExperimentOn(experiment.Charm))
// TODO(slackcontext) Consolidate storing CLI version to slackcontext
clients.Config.Version = clients.CLIVersion

Expand Down
4 changes: 2 additions & 2 deletions cmd/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ func checkForUpdates(clients *shared.ClientFactory, cmd *cobra.Command) error {
}

if clients.SDKConfig.Hooks.CheckUpdate.IsAvailable() {
cmd.Printf("%s You are using the latest Slack CLI and SDK versions\n", style.Styler().Green("✔").String())
cmd.Printf("%s You are using the latest Slack CLI and SDK versions\n", style.Green("✔"))
} else {
cmd.Printf("%s You are using the latest Slack CLI version\n", style.Styler().Green("✔").String())
cmd.Printf("%s You are using the latest Slack CLI version\n", style.Green("✔"))
}

return nil
Expand Down
Loading
Loading