detached 70c00ad

test: use Store.Mutate for the merge-mode upgrade test and skip id-only events in the inbox stream test

commit
70c00ad2d5a23676a0759d7ae2dcab5e5dcd4425
author
brice · · 2026-10-19 18:50 UTC
parent
bda2a5e
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
8/8
2 files · +20 -5
M internal/adapters/kvstore/mergerequests_test.go +5 -2
@@ -609,8 +609,11 @@ func TestStoredOldDefaultModesGainMerge(t *testing.T) {
609609 assert.Equal(t, []domain.MergeMode{domain.MergeModeSquash}, single.Settings.AllowedMergeModes)
610610
611611 // An explicit {ff, squash} written now is kept.
612- old.Settings.AllowedMergeModes = []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}
613- require.NoError(t, s.Update(ctx, old))
612+ _, err = s.Mutate(ctx, old.Name, func(r *domain.Repo) (bool, error) {
613+ r.Settings.AllowedMergeModes = []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}
614+ return true, nil
615+ })
616+ require.NoError(t, err)
614617 again, err := s.Get(ctx, name(t, "old"))
615618 require.NoError(t, err)
616619 assert.Equal(t, []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}, again.Settings.AllowedMergeModes)
@@ -609,8 +609,11 @@ func TestStoredOldDefaultModesGainMerge(t *testing.T) {
609 assert.Equal(t, []domain.MergeMode{domain.MergeModeSquash}, single.Settings.AllowedMergeModes)609 assert.Equal(t, []domain.MergeMode{domain.MergeModeSquash}, single.Settings.AllowedMergeModes)
610 610
611 // An explicit {ff, squash} written now is kept.611 // An explicit {ff, squash} written now is kept.
612- old.Settings.AllowedMergeModes = []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}612+ _, err = s.Mutate(ctx, old.Name, func(r *domain.Repo) (bool, error) {
613- require.NoError(t, s.Update(ctx, old))613+ r.Settings.AllowedMergeModes = []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}
614+ return true, nil
615+ })
616+ require.NoError(t, err)
614 again, err := s.Get(ctx, name(t, "old"))617 again, err := s.Get(ctx, name(t, "old"))
615 require.NoError(t, err)618 require.NoError(t, err)
616 assert.Equal(t, []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}, again.Settings.AllowedMergeModes)619 assert.Equal(t, []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}, again.Settings.AllowedMergeModes)
M internal/app/web_inbox_test.go +15 -3
@@ -48,17 +48,17 @@ func TestWebInboxEndToEnd(t *testing.T) {
4848 root := domain.Root()
4949 _, err = r.forge.MergeRequests.Create(r.ctx, root, r.name("proj"), ports.CreateMergeRequestParams{Title: "add search", Source: "feat/search", Target: "main"})
5050 require.NoError(t, err)
51- ev := stream.next(t, watchWait)
51+ ev := nextFragment(t, stream)
5252 assert.Equal(t, "inbox", ev.name)
5353 assert.Contains(t, ev.data, `id="inbox-counts"`)
5454 for range 4 { // the other fragments of this event
55- stream.next(t, watchWait)
55+ nextFragment(t, stream)
5656 }
5757 _, err = r.forge.Issues.Create(r.ctx, root, r.name("other"), ports.CreateIssueParams{Title: "search is slow"})
5858 require.NoError(t, err)
5959 var seen strings.Builder
6060 for range 5 { // the five fragments of this event
61- seen.WriteString(stream.next(t, watchWait).data)
61+ seen.WriteString(nextFragment(t, stream).data)
6262 }
6363 assert.Contains(t, seen.String(), "search is slow", "an event of the second repository")
6464 _, err = r.forge.MergeRequests.Create(r.ctx, root, r.name("other"), ports.CreateMergeRequestParams{Title: "other work", Source: "feat/search", Target: "main"})
@@ -109,6 +109,18 @@ func TestWebInboxEndToEnd(t *testing.T) {
109109 assert.Equal(t, unknown.status, b.get("/-/events?topic=owner&view=inbox", map[string]string{"Authorization": "Bearer " + adminToken}).status)
110110 }
111111
112+// nextFragment returns the next event that carries a fragment. Events the
113+// inbox does not show (a mergeability check) still send their id alone, so a
114+// resumed stream starts after them; they are skipped.
115+func nextFragment(t *testing.T, s *sseStream) sseEvent {
116+ t.Helper()
117+ for {
118+ if ev := s.next(t, watchWait); ev.name != "" {
119+ return ev
120+ }
121+ }
122+}
123+
112124 // ownerStream opens the owner topic with the session cookie.
113125 func ownerStream(t *testing.T, h *harness, token string) *sseStream {
114126 t.Helper()
@@ -48,17 +48,17 @@ func TestWebInboxEndToEnd(t *testing.T) {
48 root := domain.Root()48 root := domain.Root()
49 _, err = r.forge.MergeRequests.Create(r.ctx, root, r.name("proj"), ports.CreateMergeRequestParams{Title: "add search", Source: "feat/search", Target: "main"})49 _, err = r.forge.MergeRequests.Create(r.ctx, root, r.name("proj"), ports.CreateMergeRequestParams{Title: "add search", Source: "feat/search", Target: "main"})
50 require.NoError(t, err)50 require.NoError(t, err)
51- ev := stream.next(t, watchWait)51+ ev := nextFragment(t, stream)
52 assert.Equal(t, "inbox", ev.name)52 assert.Equal(t, "inbox", ev.name)
53 assert.Contains(t, ev.data, `id="inbox-counts"`)53 assert.Contains(t, ev.data, `id="inbox-counts"`)
54 for range 4 { // the other fragments of this event54 for range 4 { // the other fragments of this event
55- stream.next(t, watchWait)55+ nextFragment(t, stream)
56 }56 }
57 _, err = r.forge.Issues.Create(r.ctx, root, r.name("other"), ports.CreateIssueParams{Title: "search is slow"})57 _, err = r.forge.Issues.Create(r.ctx, root, r.name("other"), ports.CreateIssueParams{Title: "search is slow"})
58 require.NoError(t, err)58 require.NoError(t, err)
59 var seen strings.Builder59 var seen strings.Builder
60 for range 5 { // the five fragments of this event60 for range 5 { // the five fragments of this event
61- seen.WriteString(stream.next(t, watchWait).data)61+ seen.WriteString(nextFragment(t, stream).data)
62 }62 }
63 assert.Contains(t, seen.String(), "search is slow", "an event of the second repository")63 assert.Contains(t, seen.String(), "search is slow", "an event of the second repository")
64 _, err = r.forge.MergeRequests.Create(r.ctx, root, r.name("other"), ports.CreateMergeRequestParams{Title: "other work", Source: "feat/search", Target: "main"})64 _, err = r.forge.MergeRequests.Create(r.ctx, root, r.name("other"), ports.CreateMergeRequestParams{Title: "other work", Source: "feat/search", Target: "main"})
@@ -109,6 +109,18 @@ func TestWebInboxEndToEnd(t *testing.T) {
109 assert.Equal(t, unknown.status, b.get("/-/events?topic=owner&view=inbox", map[string]string{"Authorization": "Bearer " + adminToken}).status)109 assert.Equal(t, unknown.status, b.get("/-/events?topic=owner&view=inbox", map[string]string{"Authorization": "Bearer " + adminToken}).status)
110 }110 }
111 111
112+// nextFragment returns the next event that carries a fragment. Events the
113+// inbox does not show (a mergeability check) still send their id alone, so a
114+// resumed stream starts after them; they are skipped.
115+func nextFragment(t *testing.T, s *sseStream) sseEvent {
116+ t.Helper()
117+ for {
118+ if ev := s.next(t, watchWait); ev.name != "" {
119+ return ev
120+ }
121+ }
122+}
123+
112 // ownerStream opens the owner topic with the session cookie.124 // ownerStream opens the owner topic with the session cookie.
113 func ownerStream(t *testing.T, h *harness, token string) *sseStream {125 func ownerStream(t *testing.T, h *harness, token string) *sseStream {
114 t.Helper()126 t.Helper()

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 45

↑↓ moveenter openesc close