github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/extension/browse/browse_test.go (about)

     1  package browse
     2  
     3  import (
     4  	"encoding/base64"
     5  	"io"
     6  	"log"
     7  	"net/http"
     8  	"net/url"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/ungtb10d/cli/v2/internal/config"
    13  	"github.com/ungtb10d/cli/v2/internal/ghrepo"
    14  	"github.com/ungtb10d/cli/v2/pkg/cmd/repo/view"
    15  	"github.com/ungtb10d/cli/v2/pkg/extensions"
    16  	"github.com/ungtb10d/cli/v2/pkg/httpmock"
    17  	"github.com/ungtb10d/cli/v2/pkg/search"
    18  	"github.com/rivo/tview"
    19  	"github.com/stretchr/testify/assert"
    20  )
    21  
    22  func Test_getSelectedReadme(t *testing.T) {
    23  	reg := httpmock.Registry{}
    24  	defer reg.Verify(t)
    25  
    26  	content := base64.StdEncoding.EncodeToString([]byte("lol"))
    27  
    28  	reg.Register(
    29  		httpmock.REST("GET", "repos/cli/gh-cool/readme"),
    30  		httpmock.JSONResponse(view.RepoReadme{Content: content}))
    31  
    32  	client := &http.Client{Transport: &reg}
    33  
    34  	rg := newReadmeGetter(client, time.Second)
    35  	opts := ExtBrowseOpts{
    36  		Rg: rg,
    37  	}
    38  	readme := tview.NewTextView()
    39  	ui := uiRegistry{
    40  		List: tview.NewList(),
    41  	}
    42  	extEntries := []extEntry{
    43  		{
    44  			Name:        "gh-cool",
    45  			FullName:    "cli/gh-cool",
    46  			Installed:   false,
    47  			Official:    true,
    48  			description: "it's just cool ok",
    49  		},
    50  		{
    51  			Name:        "gh-screensaver",
    52  			FullName:    "vilmibm/gh-screensaver",
    53  			Installed:   true,
    54  			Official:    false,
    55  			description: "animations in your terminal",
    56  		},
    57  	}
    58  	el := newExtList(opts, ui, extEntries)
    59  
    60  	content, err := getSelectedReadme(opts, readme, el)
    61  	assert.NoError(t, err)
    62  	assert.Contains(t, content, "lol")
    63  }
    64  
    65  func Test_getExtensionRepos(t *testing.T) {
    66  	reg := httpmock.Registry{}
    67  	defer reg.Verify(t)
    68  
    69  	client := &http.Client{Transport: &reg}
    70  
    71  	values := url.Values{
    72  		"page":     []string{"1"},
    73  		"per_page": []string{"100"},
    74  		"q":        []string{"topic:gh-extension"},
    75  	}
    76  	cfg := config.NewBlankConfig()
    77  
    78  	cfg.DefaultHostFunc = func() (string, string) { return "github.com", "" }
    79  
    80  	reg.Register(
    81  		httpmock.QueryMatcher("GET", "search/repositories", values),
    82  		httpmock.JSONResponse(search.RepositoriesResult{
    83  			IncompleteResults: false,
    84  			Items: []search.Repository{
    85  				{
    86  					FullName:    "vilmibm/gh-screensaver",
    87  					Name:        "gh-screensaver",
    88  					Description: "terminal animations",
    89  					Owner: search.User{
    90  						Login: "vilmibm",
    91  					},
    92  				},
    93  				{
    94  					FullName:    "cli/gh-cool",
    95  					Name:        "gh-cool",
    96  					Description: "it's just cool ok",
    97  					Owner: search.User{
    98  						Login: "cli",
    99  					},
   100  				},
   101  				{
   102  					FullName:    "samcoe/gh-triage",
   103  					Name:        "gh-triage",
   104  					Description: "helps with triage",
   105  					Owner: search.User{
   106  						Login: "samcoe",
   107  					},
   108  				},
   109  				{
   110  					FullName:    "github/gh-gei",
   111  					Name:        "gh-gei",
   112  					Description: "something something enterprise",
   113  					Owner: search.User{
   114  						Login: "github",
   115  					},
   116  				},
   117  			},
   118  			Total: 4,
   119  		}),
   120  	)
   121  
   122  	searcher := search.NewSearcher(client, "github.com")
   123  	emMock := &extensions.ExtensionManagerMock{}
   124  	emMock.ListFunc = func() []extensions.Extension {
   125  		return []extensions.Extension{
   126  			&extensions.ExtensionMock{
   127  				URLFunc: func() string {
   128  					return "https://github.com/vilmibm/gh-screensaver"
   129  				},
   130  			},
   131  			&extensions.ExtensionMock{
   132  				URLFunc: func() string {
   133  					return "https://github.com/github/gh-gei"
   134  				},
   135  			},
   136  		}
   137  	}
   138  
   139  	opts := ExtBrowseOpts{
   140  		Searcher: searcher,
   141  		Em:       emMock,
   142  		Cfg:      cfg,
   143  	}
   144  
   145  	extEntries, err := getExtensions(opts)
   146  	assert.NoError(t, err)
   147  
   148  	expectedEntries := []extEntry{
   149  		{
   150  			URL:         "https://github.com/vilmibm/gh-screensaver",
   151  			Name:        "gh-screensaver",
   152  			FullName:    "vilmibm/gh-screensaver",
   153  			Installed:   true,
   154  			Official:    false,
   155  			description: "terminal animations",
   156  		},
   157  		{
   158  			URL:         "https://github.com/cli/gh-cool",
   159  			Name:        "gh-cool",
   160  			FullName:    "cli/gh-cool",
   161  			Installed:   false,
   162  			Official:    true,
   163  			description: "it's just cool ok",
   164  		},
   165  		{
   166  			URL:         "https://github.com/samcoe/gh-triage",
   167  			Name:        "gh-triage",
   168  			FullName:    "samcoe/gh-triage",
   169  			Installed:   false,
   170  			Official:    false,
   171  			description: "helps with triage",
   172  		},
   173  		{
   174  			URL:         "https://github.com/github/gh-gei",
   175  			Name:        "gh-gei",
   176  			FullName:    "github/gh-gei",
   177  			Installed:   true,
   178  			Official:    true,
   179  			description: "something something enterprise",
   180  		},
   181  	}
   182  
   183  	assert.Equal(t, expectedEntries, extEntries)
   184  }
   185  
   186  func Test_extEntry(t *testing.T) {
   187  	cases := []struct {
   188  		name          string
   189  		ee            extEntry
   190  		expectedTitle string
   191  		expectedDesc  string
   192  	}{
   193  		{
   194  			name: "official",
   195  			ee: extEntry{
   196  				Name:        "gh-cool",
   197  				FullName:    "cli/gh-cool",
   198  				Installed:   false,
   199  				Official:    true,
   200  				description: "it's just cool ok",
   201  			},
   202  			expectedTitle: "cli/gh-cool [yellow](official)",
   203  			expectedDesc:  "it's just cool ok",
   204  		},
   205  		{
   206  			name: "no description",
   207  			ee: extEntry{
   208  				Name:        "gh-nodesc",
   209  				FullName:    "barryburton/gh-nodesc",
   210  				Installed:   false,
   211  				Official:    false,
   212  				description: "",
   213  			},
   214  			expectedTitle: "barryburton/gh-nodesc",
   215  			expectedDesc:  "no description provided",
   216  		},
   217  		{
   218  			name: "installed",
   219  			ee: extEntry{
   220  				Name:        "gh-screensaver",
   221  				FullName:    "vilmibm/gh-screensaver",
   222  				Installed:   true,
   223  				Official:    false,
   224  				description: "animations in your terminal",
   225  			},
   226  			expectedTitle: "vilmibm/gh-screensaver [green](installed)",
   227  			expectedDesc:  "animations in your terminal",
   228  		},
   229  		{
   230  			name: "neither",
   231  			ee: extEntry{
   232  				Name:        "gh-triage",
   233  				FullName:    "samcoe/gh-triage",
   234  				Installed:   false,
   235  				Official:    false,
   236  				description: "help with triage",
   237  			},
   238  			expectedTitle: "samcoe/gh-triage",
   239  			expectedDesc:  "help with triage",
   240  		},
   241  		{
   242  			name: "both",
   243  			ee: extEntry{
   244  				Name:        "gh-gei",
   245  				FullName:    "github/gh-gei",
   246  				Installed:   true,
   247  				Official:    true,
   248  				description: "something something enterprise",
   249  			},
   250  			expectedTitle: "github/gh-gei [yellow](official) [green](installed)",
   251  			expectedDesc:  "something something enterprise",
   252  		},
   253  	}
   254  
   255  	for _, tt := range cases {
   256  		t.Run(tt.name, func(t *testing.T) {
   257  			assert.Equal(t, tt.expectedTitle, tt.ee.Title())
   258  			assert.Equal(t, tt.expectedDesc, tt.ee.Description())
   259  		})
   260  	}
   261  }
   262  
   263  func Test_extList(t *testing.T) {
   264  	opts := ExtBrowseOpts{
   265  		Logger: log.New(io.Discard, "", 0),
   266  		Em: &extensions.ExtensionManagerMock{
   267  			InstallFunc: func(repo ghrepo.Interface, _ string) error {
   268  				assert.Equal(t, "cli/gh-cool", ghrepo.FullName(repo))
   269  				return nil
   270  			},
   271  			RemoveFunc: func(name string) error {
   272  				assert.Equal(t, "cool", name)
   273  				return nil
   274  			},
   275  		},
   276  	}
   277  	app := tview.NewApplication()
   278  	list := tview.NewList()
   279  	ui := uiRegistry{
   280  		List: list,
   281  		App:  app,
   282  	}
   283  	extEntries := []extEntry{
   284  		{
   285  			Name:        "gh-cool",
   286  			FullName:    "cli/gh-cool",
   287  			Installed:   false,
   288  			Official:    true,
   289  			description: "it's just cool ok",
   290  		},
   291  		{
   292  			Name:        "gh-screensaver",
   293  			FullName:    "vilmibm/gh-screensaver",
   294  			Installed:   true,
   295  			Official:    false,
   296  			description: "animations in your terminal",
   297  		},
   298  		{
   299  			Name:        "gh-triage",
   300  			FullName:    "samcoe/gh-triage",
   301  			Installed:   false,
   302  			Official:    false,
   303  			description: "help with triage",
   304  		},
   305  		{
   306  			Name:        "gh-gei",
   307  			FullName:    "github/gh-gei",
   308  			Installed:   true,
   309  			Official:    true,
   310  			description: "something something enterprise",
   311  		},
   312  	}
   313  
   314  	extList := newExtList(opts, ui, extEntries)
   315  
   316  	extList.Filter("cool")
   317  	assert.Equal(t, 1, extList.ui.List.GetItemCount())
   318  
   319  	title, _ := extList.ui.List.GetItemText(0)
   320  	assert.Equal(t, "cli/gh-cool [yellow](official)", title)
   321  
   322  	extList.InstallSelected()
   323  	assert.True(t, extList.extEntries[0].Installed)
   324  
   325  	extList.Refresh()
   326  	assert.Equal(t, 1, extList.ui.List.GetItemCount())
   327  
   328  	title, _ = extList.ui.List.GetItemText(0)
   329  	assert.Equal(t, "cli/gh-cool [yellow](official) [green](installed)", title)
   330  
   331  	extList.RemoveSelected()
   332  	assert.False(t, extList.extEntries[0].Installed)
   333  
   334  	extList.Refresh()
   335  	assert.Equal(t, 1, extList.ui.List.GetItemCount())
   336  
   337  	title, _ = extList.ui.List.GetItemText(0)
   338  	assert.Equal(t, "cli/gh-cool [yellow](official)", title)
   339  
   340  	extList.Reset()
   341  	assert.Equal(t, 4, extList.ui.List.GetItemCount())
   342  
   343  	ee, ix := extList.FindSelected()
   344  	assert.Equal(t, 0, ix)
   345  	assert.Equal(t, "cli/gh-cool [yellow](official)", ee.Title())
   346  
   347  	extList.ScrollDown()
   348  	ee, ix = extList.FindSelected()
   349  	assert.Equal(t, 1, ix)
   350  	assert.Equal(t, "vilmibm/gh-screensaver [green](installed)", ee.Title())
   351  
   352  	extList.ScrollUp()
   353  	ee, ix = extList.FindSelected()
   354  	assert.Equal(t, 0, ix)
   355  	assert.Equal(t, "cli/gh-cool [yellow](official)", ee.Title())
   356  
   357  	extList.PageDown()
   358  	ee, ix = extList.FindSelected()
   359  	assert.Equal(t, 3, ix)
   360  	assert.Equal(t, "github/gh-gei [yellow](official) [green](installed)", ee.Title())
   361  
   362  	extList.PageUp()
   363  	ee, ix = extList.FindSelected()
   364  	assert.Equal(t, 0, ix)
   365  	assert.Equal(t, "cli/gh-cool [yellow](official)", ee.Title())
   366  }