cli/pkg/cmd/release/view/view_test.go
Mislav Marohnić 36ffbe18de
Improve looking up draft releases by tag name
This changes the FetchRelease implementation to look up draft releases directly using by its pending tag name, as opposed to resorting to the Releases list API which is backed by Elastic Search and thus suffers replication lag after the creation of a draft release.

Bonus: all release lookup functions now accept a context for cancellation.
2022-12-14 21:24:08 +01:00

313 lines
6.6 KiB
Go

package view
import (
"bytes"
"fmt"
"io"
"net/http"
"testing"
"time"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/internal/ghrepo"
"github.com/cli/cli/v2/pkg/cmd/release/shared"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/httpmock"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/google/shlex"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_NewCmdView(t *testing.T) {
tests := []struct {
name string
args string
isTTY bool
want ViewOptions
wantErr string
}{
{
name: "version argument",
args: "v1.2.3",
isTTY: true,
want: ViewOptions{
TagName: "v1.2.3",
WebMode: false,
},
},
{
name: "no arguments",
args: "",
isTTY: true,
want: ViewOptions{
TagName: "",
WebMode: false,
},
},
{
name: "web mode",
args: "-w",
isTTY: true,
want: ViewOptions{
TagName: "",
WebMode: true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ios, _, _, _ := iostreams.Test()
ios.SetStdoutTTY(tt.isTTY)
ios.SetStdinTTY(tt.isTTY)
ios.SetStderrTTY(tt.isTTY)
f := &cmdutil.Factory{
IOStreams: ios,
}
var opts *ViewOptions
cmd := NewCmdView(f, func(o *ViewOptions) error {
opts = o
return nil
})
cmd.PersistentFlags().StringP("repo", "R", "", "")
argv, err := shlex.Split(tt.args)
require.NoError(t, err)
cmd.SetArgs(argv)
cmd.SetIn(&bytes.Buffer{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
_, err = cmd.ExecuteC()
if tt.wantErr != "" {
require.EqualError(t, err, tt.wantErr)
return
} else {
require.NoError(t, err)
}
assert.Equal(t, tt.want.TagName, opts.TagName)
assert.Equal(t, tt.want.WebMode, opts.WebMode)
})
}
}
func Test_viewRun(t *testing.T) {
oneHourAgo := time.Now().Add(time.Duration(-24) * time.Hour)
frozenTime, err := time.Parse(time.RFC3339, "2020-08-31T15:44:24+02:00")
require.NoError(t, err)
tests := []struct {
name string
isTTY bool
releaseBody string
releasedAt time.Time
opts ViewOptions
wantErr string
wantStdout string
wantStderr string
}{
{
name: "view specific release",
isTTY: true,
releaseBody: `* Fixed bugs\n`,
releasedAt: oneHourAgo,
opts: ViewOptions{
TagName: "v1.2.3",
},
wantStdout: heredoc.Doc(`
v1.2.3
MonaLisa released this about 1 day ago
• Fixed bugs
Assets
windows.zip 12 B
linux.tgz 34 B
View on GitHub: https://github.com/OWNER/REPO/releases/tags/v1.2.3
`),
wantStderr: ``,
},
{
name: "view latest release",
isTTY: true,
releaseBody: `* Fixed bugs\n`,
releasedAt: oneHourAgo,
opts: ViewOptions{
TagName: "",
},
wantStdout: heredoc.Doc(`
v1.2.3
MonaLisa released this about 1 day ago
• Fixed bugs
Assets
windows.zip 12 B
linux.tgz 34 B
View on GitHub: https://github.com/OWNER/REPO/releases/tags/v1.2.3
`),
wantStderr: ``,
},
{
name: "view machine-readable",
isTTY: false,
releaseBody: `* Fixed bugs\n`,
releasedAt: frozenTime,
opts: ViewOptions{
TagName: "v1.2.3",
},
wantStdout: heredoc.Doc(`
title:
tag: v1.2.3
draft: false
prerelease: false
author: MonaLisa
created: 2020-08-31T15:44:24+02:00
published: 2020-08-31T15:44:24+02:00
url: https://github.com/OWNER/REPO/releases/tags/v1.2.3
asset: windows.zip
asset: linux.tgz
--
* Fixed bugs
`),
wantStderr: ``,
},
{
name: "view machine-readable but body has no ending newline",
isTTY: false,
releaseBody: `* Fixed bugs`,
releasedAt: frozenTime,
opts: ViewOptions{
TagName: "v1.2.3",
},
wantStdout: heredoc.Doc(`
title:
tag: v1.2.3
draft: false
prerelease: false
author: MonaLisa
created: 2020-08-31T15:44:24+02:00
published: 2020-08-31T15:44:24+02:00
url: https://github.com/OWNER/REPO/releases/tags/v1.2.3
asset: windows.zip
asset: linux.tgz
--
* Fixed bugs
`),
wantStderr: ``,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ios, _, stdout, stderr := iostreams.Test()
ios.SetStdoutTTY(tt.isTTY)
ios.SetStdinTTY(tt.isTTY)
ios.SetStderrTTY(tt.isTTY)
fakeHTTP := &httpmock.Registry{}
shared.StubFetchRelease(t, fakeHTTP, "OWNER", "REPO", tt.opts.TagName, fmt.Sprintf(`{
"tag_name": "v1.2.3",
"draft": false,
"author": { "login": "MonaLisa" },
"body": "%[2]s",
"created_at": "%[1]s",
"published_at": "%[1]s",
"html_url": "https://github.com/OWNER/REPO/releases/tags/v1.2.3",
"assets": [
{ "name": "windows.zip", "size": 12 },
{ "name": "linux.tgz", "size": 34 }
]
}`, tt.releasedAt.Format(time.RFC3339), tt.releaseBody))
tt.opts.IO = ios
tt.opts.HttpClient = func() (*http.Client, error) {
return &http.Client{Transport: fakeHTTP}, nil
}
tt.opts.BaseRepo = func() (ghrepo.Interface, error) {
return ghrepo.FromFullName("OWNER/REPO")
}
err := viewRun(&tt.opts)
if tt.wantErr != "" {
require.EqualError(t, err, tt.wantErr)
return
} else {
require.NoError(t, err)
}
assert.Equal(t, tt.wantStdout, stdout.String())
assert.Equal(t, tt.wantStderr, stderr.String())
})
}
}
func Test_humanFileSize(t *testing.T) {
tests := []struct {
name string
size int64
want string
}{
{
name: "min bytes",
size: 1,
want: "1 B",
},
{
name: "max bytes",
size: 1023,
want: "1023 B",
},
{
name: "min kibibytes",
size: 1024,
want: "1.00 KiB",
},
{
name: "max kibibytes",
size: 1024*1024 - 1,
want: "1023.99 KiB",
},
{
name: "min mibibytes",
size: 1024 * 1024,
want: "1.00 MiB",
},
{
name: "fractional mibibytes",
size: 1024*1024*12 + 1024*350,
want: "12.34 MiB",
},
{
name: "max mibibytes",
size: 1024*1024*1024 - 1,
want: "1023.99 MiB",
},
{
name: "min gibibytes",
size: 1024 * 1024 * 1024,
want: "1.00 GiB",
},
{
name: "fractional gibibytes",
size: 1024 * 1024 * 1024 * 1.5,
want: "1.50 GiB",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := humanFileSize(tt.size); got != tt.want {
t.Errorf("humanFileSize() = %v, want %v", got, tt.want)
}
})
}
}