package view import ( "bytes" "net/http" "testing" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/internal/browser" "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmd/repo/autolink/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" "github.com/cli/cli/v2/pkg/jsonfieldstest" "github.com/google/shlex" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestJSONFields(t *testing.T) { jsonfieldstest.ExpectCommandToSupportJSONFields(t, NewCmdView, []string{ "id", "isAlphanumeric", "keyPrefix", "urlTemplate", }) } func TestNewCmdView(t *testing.T) { tests := []struct { name string input string output viewOptions wantErr bool wantExporter bool errMsg string }{ { name: "no argument", input: "", wantErr: true, errMsg: "accepts 1 arg(s), received 0", }, { name: "id provided", input: "123", output: viewOptions{ID: "123"}, }, { name: "json flag", input: "123 --json id", output: viewOptions{ID: "123"}, wantExporter: true, }, { name: "invalid json flag", input: "123 --json invalid", wantErr: true, errMsg: "Unknown JSON field: \"invalid\"\nAvailable fields:\n id\n isAlphanumeric\n keyPrefix\n urlTemplate", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ios, _, _, _ := iostreams.Test() f := &cmdutil.Factory{ IOStreams: ios, } f.HttpClient = func() (*http.Client, error) { return &http.Client{}, nil } argv, err := shlex.Split(tt.input) require.NoError(t, err) var gotOpts *viewOptions cmd := NewCmdView(f, func(opts *viewOptions) error { gotOpts = opts return nil }) cmd.SetArgs(argv) cmd.SetIn(&bytes.Buffer{}) cmd.SetOut(&bytes.Buffer{}) cmd.SetErr(&bytes.Buffer{}) _, err = cmd.ExecuteC() if tt.wantErr { require.EqualError(t, err, tt.errMsg) } else { require.NoError(t, err) assert.Equal(t, tt.wantExporter, gotOpts.Exporter != nil) assert.Equal(t, tt.output.ID, gotOpts.ID) } }) } } type stubAutolinkViewer struct { autolink *shared.Autolink err error } func (g stubAutolinkViewer) View(repo ghrepo.Interface, id string) (*shared.Autolink, error) { return g.autolink, g.err } type testAutolinkClientViewError struct{} func (e testAutolinkClientViewError) Error() string { return "autolink client view error" } func TestViewRun(t *testing.T) { tests := []struct { name string opts *viewOptions stubViewer stubAutolinkViewer expectedErr error wantStdout string }{ { name: "view", opts: &viewOptions{ ID: "1", }, stubViewer: stubAutolinkViewer{ autolink: &shared.Autolink{ ID: 1, KeyPrefix: "TICKET-", URLTemplate: "https://example.com/TICKET?query=", IsAlphanumeric: true, }, }, wantStdout: heredoc.Doc(` Autolink in OWNER/REPO ID: 1 Key Prefix: TICKET- URL Template: https://example.com/TICKET?query= Alphanumeric: true `), }, { name: "view json", opts: &viewOptions{ Exporter: func() cmdutil.Exporter { exporter := cmdutil.NewJSONExporter() exporter.SetFields([]string{"id"}) return exporter }(), }, stubViewer: stubAutolinkViewer{ autolink: &shared.Autolink{ ID: 1, KeyPrefix: "TICKET-", URLTemplate: "https://example.com/TICKET?query=", IsAlphanumeric: true, }, }, wantStdout: "{\"id\":1}\n", }, { name: "client error", opts: &viewOptions{}, stubViewer: stubAutolinkViewer{ autolink: nil, err: testAutolinkClientViewError{}, }, expectedErr: testAutolinkClientViewError{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ios, _, stdout, _ := iostreams.Test() opts := tt.opts opts.IO = ios opts.Browser = &browser.Stub{} opts.IO = ios opts.BaseRepo = func() (ghrepo.Interface, error) { return ghrepo.New("OWNER", "REPO"), nil } opts.AutolinkClient = &tt.stubViewer err := viewRun(opts) if tt.expectedErr != nil { require.Error(t, err) assert.ErrorIs(t, err, tt.expectedErr) } else { require.NoError(t, err) assert.Equal(t, tt.wantStdout, stdout.String()) } }) } }