package prompter import ( "fmt" "strings" "testing" ghPrompter "github.com/cli/go-gh/v2/pkg/prompter" "github.com/stretchr/testify/assert" ) func NewMockPrompter(t *testing.T) *MockPrompter { m := &MockPrompter{ t: t, PrompterMock: *ghPrompter.NewMock(t), authTokenStubs: []authTokenStub{}, confirmDeletionStubs: []confirmDeletionStub{}, inputHostnameStubs: []inputHostnameStub{}, markdownEditorStubs: []markdownEditorStub{}, } t.Cleanup(m.Verify) return m } type MockPrompter struct { t *testing.T ghPrompter.PrompterMock authTokenStubs []authTokenStub confirmDeletionStubs []confirmDeletionStub inputHostnameStubs []inputHostnameStub markdownEditorStubs []markdownEditorStub multiSelectWithSearchStubs []multiSelectWithSearchStub } type authTokenStub struct { fn func() (string, error) } type confirmDeletionStub struct { prompt string fn func(string) error } type inputHostnameStub struct { fn func() (string, error) } type markdownEditorStub struct { prompt string fn func(string, string, bool) (string, error) } type multiSelectWithSearchStub struct { fn func(string, string, []string, []string, func(string) MultiSelectSearchResult) ([]string, error) } func (m *MockPrompter) AuthToken() (string, error) { var s authTokenStub if len(m.authTokenStubs) == 0 { return "", NoSuchPromptErr("AuthToken") } s = m.authTokenStubs[0] m.authTokenStubs = m.authTokenStubs[1:len(m.authTokenStubs)] return s.fn() } func (m *MockPrompter) ConfirmDeletion(prompt string) error { var s confirmDeletionStub if len(m.confirmDeletionStubs) == 0 { return NoSuchPromptErr("ConfirmDeletion") } s = m.confirmDeletionStubs[0] m.confirmDeletionStubs = m.confirmDeletionStubs[1:len(m.confirmDeletionStubs)] return s.fn(prompt) } func (m *MockPrompter) InputHostname() (string, error) { var s inputHostnameStub if len(m.inputHostnameStubs) == 0 { return "", NoSuchPromptErr("InputHostname") } s = m.inputHostnameStubs[0] m.inputHostnameStubs = m.inputHostnameStubs[1:len(m.inputHostnameStubs)] return s.fn() } func (m *MockPrompter) MarkdownEditor(prompt, defaultValue string, blankAllowed bool) (string, error) { var s markdownEditorStub if len(m.markdownEditorStubs) == 0 { return "", NoSuchPromptErr(prompt) } s = m.markdownEditorStubs[0] m.markdownEditorStubs = m.markdownEditorStubs[1:len(m.markdownEditorStubs)] if s.prompt != prompt { return "", NoSuchPromptErr(prompt) } return s.fn(prompt, defaultValue, blankAllowed) } func (m *MockPrompter) MultiSelectWithSearch(prompt, searchPrompt string, defaults []string, persistentOptions []string, searchFunc func(string) MultiSelectSearchResult) ([]string, error) { var s multiSelectWithSearchStub if len(m.multiSelectWithSearchStubs) == 0 { return nil, NoSuchPromptErr(prompt) } s = m.multiSelectWithSearchStubs[0] m.multiSelectWithSearchStubs = m.multiSelectWithSearchStubs[1:len(m.multiSelectWithSearchStubs)] return s.fn(prompt, searchPrompt, defaults, persistentOptions, searchFunc) } func (m *MockPrompter) RegisterAuthToken(stub func() (string, error)) { m.authTokenStubs = append(m.authTokenStubs, authTokenStub{fn: stub}) } func (m *MockPrompter) RegisterConfirmDeletion(prompt string, stub func(string) error) { m.confirmDeletionStubs = append(m.confirmDeletionStubs, confirmDeletionStub{prompt: prompt, fn: stub}) } func (m *MockPrompter) RegisterInputHostname(stub func() (string, error)) { m.inputHostnameStubs = append(m.inputHostnameStubs, inputHostnameStub{fn: stub}) } func (m *MockPrompter) RegisterMarkdownEditor(prompt string, stub func(string, string, bool) (string, error)) { m.markdownEditorStubs = append(m.markdownEditorStubs, markdownEditorStub{prompt: prompt, fn: stub}) } func (m *MockPrompter) Verify() { errs := []string{} if len(m.authTokenStubs) > 0 { errs = append(errs, "AuthToken") } if len(m.confirmDeletionStubs) > 0 { errs = append(errs, "ConfirmDeletion") } if len(m.inputHostnameStubs) > 0 { errs = append(errs, "inputHostname") } if len(m.markdownEditorStubs) > 0 { errs = append(errs, "markdownEditorStubs") } if len(errs) > 0 { m.t.Helper() m.t.Errorf("%d unmatched calls to %s", len(errs), strings.Join(errs, ",")) } } func AssertOptions(t *testing.T, expected, actual []string) { assert.Equal(t, expected, actual) } func IndexFor(options []string, answer string) (int, error) { for ix, a := range options { if a == answer { return ix, nil } } return -1, NoSuchAnswerErr(answer, options) } func IndexesFor(options []string, answers ...string) ([]int, error) { indexes := make([]int, len(answers)) for i, answer := range answers { index, err := IndexFor(options, answer) if err != nil { return nil, err } indexes[i] = index } return indexes, nil } func NoSuchPromptErr(prompt string) error { return fmt.Errorf("no such prompt '%s'", prompt) } func NoSuchAnswerErr(answer string, options []string) error { return fmt.Errorf("no such answer '%s' in [%s]", answer, strings.Join(options, ", ")) }