`)
assert.Contains(t, body, `
`)
for layout, pressed := range map[string]string{"cards": "true", "split": "false", "compact": "false"} {
assert.Contains(t, body, `data-set-layout="`+layout+`" aria-pressed="`+pressed+`"`)
assert.Contains(t, body, `class="ico i-`+layout+`"`)
}
store := strings.Index(body, "/js/store.")
app := strings.Index(body, "/js/ermite.")
require.NotEqual(t, -1, store)
assert.Less(t, store, app, "the store loads before the app script")
}
func TestHomeActivityOrderAndFallback(t *testing.T) {
t.Parallel()
now := time.Now().UTC()
a, b, c := publicRepo(t, "a"), publicRepo(t, "b"), publicRepo(t, "c")
a.PushedAt = now.Add(-time.Hour)
a.ActiveAt = now
b.PushedAt = now.Add(-time.Minute)
c.CreatedAt = now.Add(-30 * time.Minute)
repos := []ports.RepoView{b, c, a}
sortRepos(repos, "activity", true)
assert.Equal(t, []ports.RepoView{a, b, c}, repos)
sortRepos(repos, "activity", false)
assert.Equal(t, []ports.RepoView{c, b, a}, repos)
assert.Equal(t, rfc3339(now), homeRow(a, now, false, false).ActiveAt)
c.PushedAt = c.CreatedAt.Add(-time.Hour)
assert.Equal(t, c.CreatedAt, repoActiveAt(c), "fallback is the later of creation and push")
}
func TestActivityEventsRefreshTheHomeRow(t *testing.T) {
t.Parallel()
repo := publicRepo(t, "proj")
srv := newTestServer(t, Config{Repos: reposServing(t, repo), Browse: homeBrowse(t)})
mr := domain.MergeRequest{Repo: repo.Name}
issue := domain.Issue{Repo: repo.Name}
for _, ev := range []domain.Event{
domain.PushEvent{Repo: repo.Name},
domain.MergeRequestOpened{MergeRequest: mr}, domain.MergeRequestMerged{MergeRequest: mr},
domain.MergeRequestClosed{MergeRequest: mr}, domain.MergeRequestReady{MergeRequest: mr},
domain.CommentAdded{Repo: repo.Name}, domain.IssueOpened{Issue: issue},
domain.IssueClosed{Issue: issue}, domain.IssueReopened{Issue: issue}, domain.IssueCommented{Repo: repo.Name},
} {
t.Run(ev.EventKind(), func(t *testing.T) {
t.Parallel()
got, err := (&liveStream{s: srv}).home(t.Context(), ports.WatchEvent{Event: ev})
require.NoError(t, err)
require.Len(t, got, 1)
assert.Equal(t, "home-list", got[0].event)
assert.Contains(t, got[0].html, `id="repo-proj"`)
assert.Contains(t, got[0].html, `data-activity`)
assert.Contains(t, got[0].html, "new activity")
})
}
for _, ev := range []domain.Event{domain.IssueSubmitted{Repo: repo.Name}, domain.IssuePendingRemoved{Repo: repo.Name}} {
got, err := (&liveStream{s: srv}).home(t.Context(), ports.WatchEvent{Event: ev})
require.NoError(t, err)
assert.Empty(t, got)
}
}
func TestHomeReleaseAndLicensePills(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
name string
release domain.Release
err error
visible bool
}{
{name: "official release", release: domain.Release{Tag: "v1.2.0", PublishedAt: fixedNow}, visible: true},
{name: "plain tag only", err: domain.ErrNotFound},
{name: "draft", release: domain.Release{Tag: "secret", Draft: true}},
{name: "unpublished", release: domain.Release{Tag: "pending"}},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
repo := publicRepo(t, "proj")
repo.Visibility = domain.VisibilityPrivate
svc := mocks.NewReleaseService(t)
svc.EXPECT().GetRelease(mock.Anything, mock.Anything, repo.Name, ports.ReleaseRef{Latest: true}).Return(tc.release, tc.err).Once()
srv := newTestServer(t, Config{Repos: reposServing(t, repo), Browse: mocks.NewBrowseService(t), Releases: svc})
row := srv.homeRowOf(t.Context(), repo, fixedNow, false)
row.Private, row.Fresh = true, true
row.License = &LicenseBadge{ID: "MIT", Href: "/proj/blob/main/LICENSE"}
out := renderRow(t, row)
assert.Contains(t, out, `class="pill repo-license" href="/proj/blob/main/LICENSE" title="License: MIT">MIT`)
assert.Regexp(t, `(?s)>private.*repo-license.*class="repo-activity" title="new activity">new activity`, out)
if tc.visible {
assert.Regexp(t, `(?s)>proj.*class="pill repo-release".*>v1.2.0.*>private`, out)
assert.Contains(t, out, `href="/proj/releases/tag/v1.2.0"`)
} else {
assert.NotContains(t, out, `repo-release`)
}
})
}
out := renderRow(t, HomeRow{Name: "bare"})
assert.NotContains(t, out, `repo-license`)
assert.NotContains(t, out, `repo-release`)
}
func TestReleaseEventsRefreshTheHomeRow(t *testing.T) {
t.Parallel()
repo := publicRepo(t, "proj")
rel := domain.Release{Repo: repo.Name, Tag: "v2", PublishedAt: fixedNow}
for _, tc := range []struct {
event domain.Event
latest domain.Release
err error
}{
{domain.ReleasePublished{Release: rel}, rel, nil},
{domain.ReleaseUpdated{Release: rel}, domain.Release{Tag: "v1", PublishedAt: fixedNow}, nil},
{domain.ReleaseDeleted{Release: rel}, domain.Release{}, domain.ErrNotFound},
{domain.ReleaseUnpublished{Release: rel}, domain.Release{}, domain.ErrNotFound},
} {
t.Run(tc.event.EventKind(), func(t *testing.T) {
t.Parallel()
releases := mocks.NewReleaseService(t)
releases.EXPECT().GetRelease(mock.Anything, mock.Anything, repo.Name, ports.ReleaseRef{Latest: true}).Return(tc.latest, tc.err).Once()
srv := newTestServer(t, Config{Repos: reposServing(t, repo), Browse: homeBrowse(t), Releases: releases})
got, err := (&liveStream{s: srv}).home(t.Context(), ports.WatchEvent{Event: tc.event})
require.NoError(t, err)
require.Len(t, got, 1)
assert.Equal(t, "home-list", got[0].event)
assert.Contains(t, got[0].html, `id="repo-proj"`)
assert.NotContains(t, got[0].html, `data-activity`)
assert.NotContains(t, got[0].html, `new activity`)
if tc.err != nil {
assert.NotContains(t, got[0].html, `repo-release`)
} else {
assert.Contains(t, got[0].html, `href="/proj/releases/tag/`+tc.latest.Tag+`"`)
}
})
}
}