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
3 changes: 3 additions & 0 deletions pkg/tui/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ func (m *ErrorModel) View() string {
if errors.As(m.Err, userFacingError) {
title = userFacingError.Title
message = userFacingError.Message
if message == "" && userFacingError.Err != nil {
message = userFacingError.Err.Error()
}
} else {
message = m.Err.Error()
}
Expand Down
81 changes: 81 additions & 0 deletions pkg/tui/error_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package tui_test

import (
"errors"
"fmt"
"os/exec"
"testing"

"github.com/render-oss/cli/pkg/tui"
"github.com/stretchr/testify/require"
)

func renderErrorView(err error) string {
m := tui.NewErrorModel(err)
m.Update(tui.StackSizeMsg{Width: 120, Height: 20})
return m.View()
}

func TestErrorModelView(t *testing.T) {
t.Run("wrapped user facing error without message shows underlying error", func(t *testing.T) {
view := renderErrorView(tui.UserFacingError{
Title: "An error occurred while running kv-cli",
Err: errors.New("exit status 1"),
})
require.Contains(t, view, "An error occurred while running kv-cli")
require.Contains(t, view, "exit status 1")
})

t.Run("child process exit error is shown", func(t *testing.T) {
falsePath, err := exec.LookPath("false")
if err != nil {
t.Skip("false not available")
}
runErr := exec.Command(falsePath).Run()
var exitErr *exec.ExitError
require.ErrorAs(t, runErr, &exitErr)

view := renderErrorView(tui.UserFacingError{
Title: "An error occurred while running psql",
Err: runErr,
})
require.Contains(t, view, "An error occurred while running psql")
require.Contains(t, view, runErr.Error())
})

t.Run("user facing error nested in another error shows underlying error", func(t *testing.T) {
view := renderErrorView(fmt.Errorf("context: %w", tui.UserFacingError{
Title: "An error occurred while running pgcli",
Err: errors.New("exit status 2"),
}))
require.Contains(t, view, "An error occurred while running pgcli")
require.Contains(t, view, "exit status 2")
})

t.Run("explicit message takes precedence over underlying error", func(t *testing.T) {
view := renderErrorView(tui.UserFacingError{
Title: "Failed to SSH",
Message: "explicit message",
Err: errors.New("hidden underlying error"),
})
require.Contains(t, view, "Failed to SSH")
require.Contains(t, view, "explicit message")
require.NotContains(t, view, "hidden underlying error")
})

t.Run("title only error shows title", func(t *testing.T) {
view := renderErrorView(tui.UserFacingError{Title: "only a title"})
require.Contains(t, view, "only a title")
require.NotContains(t, view, "unknown error")
})

t.Run("message only error shows message", func(t *testing.T) {
view := renderErrorView(tui.UserFacingError{Message: "No Key Value named 'x'."})
require.Contains(t, view, "No Key Value named 'x'.")
})

t.Run("ordinary error shows error string", func(t *testing.T) {
view := renderErrorView(errors.New("plain failure"))
require.Contains(t, view, "plain failure")
})
}
27 changes: 27 additions & 0 deletions pkg/tui/views/execerror_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package views

import (
"errors"
"testing"

"github.com/render-oss/cli/pkg/tui"
"github.com/stretchr/testify/require"
)

func TestDatastoreExecErrorsShowUnderlyingError(t *testing.T) {
childErr := errors.New("exit status 1")

for name, wrapped := range map[string]error{
"kv-cli": handleRedisCLIError(childErr),
"psql": handlePSQLError(PSQL)(childErr),
"pgcli": handlePSQLError(PGCLI)(childErr),
} {
t.Run(name, func(t *testing.T) {
m := tui.NewErrorModel(wrapped)
m.Update(tui.StackSizeMsg{Width: 120, Height: 20})
view := m.View()
require.Contains(t, view, "An error occurred while running "+name)
require.Contains(t, view, "exit status 1")
})
}
}