detached bdf6220

test(palette): consolidate session creation coverage

commit
bdf62201e10a3a3784f5f88b0b440ee448aea2dd
author
brice · · 2026-08-11 14:48 UTC
parent
5a3cc80
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +29 -60
M internal/usecase/daemon/palette_test.go +29 -38
@@ -708,45 +708,36 @@ func TestPaletteCNSPromptsForSessionNameThenCreatesAndSwitches(t *testing.T) {
708708 require.NotContains(t, string(finalOutput.Data), "Create session")
709709 }
710710
711-func TestPaletteCNSArgumentCreatesNamedSessionWithoutPrompt(t *testing.T) {
712- p1, release1 := newBlockingPTY(t)
713- p2, release2 := newBlockingPTY(t)
714- d, sess, ac, sends := newManualSessionWithPTYs(t, p1)
715- defer release1()
716- defer release2()
717- d.ptys = newFactorySeq(t, p2)
718-
719- d.handleInput(sess, ac, []byte("\x1b "))
720- awaitFrame(t, sends, ports.MsgOutput)
721- d.handleInput(sess, ac, []byte("CNS scratch\r"))
722- awaitFrame(t, sends, ports.MsgOutput)
723-
724- require.False(t, ac.overlays.paletteActive())
725- require.False(t, ac.overlays.promptActive())
726- require.Equal(t, 2, sessionCount(d))
727- newSess := ac.currentSession()
728- require.Equal(t, "scratch", newSess.name)
729- require.False(t, newSess.ephemeral)
730-}
731-
732-func TestPaletteCESCreatesAndSwitchesToEphemeralSession(t *testing.T) {
733- p1, release1 := newBlockingPTY(t)
734- p2, release2 := newBlockingPTY(t)
735- d, sess, ac, sends := newManualSessionWithPTYs(t, p1)
736- defer release1()
737- defer release2()
738- d.ptys = newFactorySeq(t, p2)
739-
740- d.handleInput(sess, ac, []byte("\x1b "))
741- awaitFrame(t, sends, ports.MsgOutput)
742- d.handleInput(sess, ac, []byte("CES\r"))
743- awaitFrame(t, sends, ports.MsgOutput)
711+func TestPaletteDirectSessionCreation(t *testing.T) {
712+ cases := []struct {
713+ name, input, wantName string
714+ ephemeral bool
715+ }{
716+ {name: "named", input: "CNS scratch\r", wantName: "scratch"},
717+ {name: "ephemeral", input: "CES\r", wantName: "0", ephemeral: true},
718+ }
719+ for _, tc := range cases {
720+ t.Run(tc.name, func(t *testing.T) {
721+ p1, release1 := newBlockingPTY(t)
722+ p2, release2 := newBlockingPTY(t)
723+ d, sess, ac, sends := newManualSessionWithPTYs(t, p1)
724+ defer release1()
725+ defer release2()
726+ d.ptys = newFactorySeq(t, p2)
744727
745- require.False(t, ac.overlays.paletteActive())
746- require.Equal(t, 2, sessionCount(d))
747- newSess := ac.currentSession()
748- require.Equal(t, "0", newSess.name)
749- require.True(t, newSess.ephemeral)
728+ d.handleInput(sess, ac, []byte("\x1b "))
729+ awaitFrame(t, sends, ports.MsgOutput)
730+ d.handleInput(sess, ac, []byte(tc.input))
731+ awaitFrame(t, sends, ports.MsgOutput)
732+
733+ require.False(t, ac.overlays.paletteActive())
734+ require.False(t, ac.overlays.promptActive())
735+ require.Equal(t, 2, sessionCount(d))
736+ newSess := ac.currentSession()
737+ require.Equal(t, tc.wantName, newSess.name)
738+ require.Equal(t, tc.ephemeral, newSess.ephemeral)
739+ })
740+ }
750741 }
751742
752743 func TestPaletteReopensWithSuccessfulCommandFirst(t *testing.T) {
@@ -708,45 +708,36 @@ func TestPaletteCNSPromptsForSessionNameThenCreatesAndSwitches(t *testing.T) {
708 require.NotContains(t, string(finalOutput.Data), "Create session")708 require.NotContains(t, string(finalOutput.Data), "Create session")
709 }709 }
710 710
711-func TestPaletteCNSArgumentCreatesNamedSessionWithoutPrompt(t *testing.T) {711+func TestPaletteDirectSessionCreation(t *testing.T) {
712- p1, release1 := newBlockingPTY(t)712+ cases := []struct {
713- p2, release2 := newBlockingPTY(t)713+ name, input, wantName string
714- d, sess, ac, sends := newManualSessionWithPTYs(t, p1)714+ ephemeral bool
715- defer release1()715+ }{
716- defer release2()716+ {name: "named", input: "CNS scratch\r", wantName: "scratch"},
717- d.ptys = newFactorySeq(t, p2)717+ {name: "ephemeral", input: "CES\r", wantName: "0", ephemeral: true},
718-718+ }
719- d.handleInput(sess, ac, []byte("\x1b "))719+ for _, tc := range cases {
720- awaitFrame(t, sends, ports.MsgOutput)720+ t.Run(tc.name, func(t *testing.T) {
721- d.handleInput(sess, ac, []byte("CNS scratch\r"))721+ p1, release1 := newBlockingPTY(t)
722- awaitFrame(t, sends, ports.MsgOutput)722+ p2, release2 := newBlockingPTY(t)
723-723+ d, sess, ac, sends := newManualSessionWithPTYs(t, p1)
724- require.False(t, ac.overlays.paletteActive())724+ defer release1()
725- require.False(t, ac.overlays.promptActive())725+ defer release2()
726- require.Equal(t, 2, sessionCount(d))726+ d.ptys = newFactorySeq(t, p2)
727- newSess := ac.currentSession()
728- require.Equal(t, "scratch", newSess.name)
729- require.False(t, newSess.ephemeral)
730-}
731-
732-func TestPaletteCESCreatesAndSwitchesToEphemeralSession(t *testing.T) {
733- p1, release1 := newBlockingPTY(t)
734- p2, release2 := newBlockingPTY(t)
735- d, sess, ac, sends := newManualSessionWithPTYs(t, p1)
736- defer release1()
737- defer release2()
738- d.ptys = newFactorySeq(t, p2)
739-
740- d.handleInput(sess, ac, []byte("\x1b "))
741- awaitFrame(t, sends, ports.MsgOutput)
742- d.handleInput(sess, ac, []byte("CES\r"))
743- awaitFrame(t, sends, ports.MsgOutput)
744 727
745- require.False(t, ac.overlays.paletteActive())728+ d.handleInput(sess, ac, []byte("\x1b "))
746- require.Equal(t, 2, sessionCount(d))729+ awaitFrame(t, sends, ports.MsgOutput)
747- newSess := ac.currentSession()730+ d.handleInput(sess, ac, []byte(tc.input))
748- require.Equal(t, "0", newSess.name)731+ awaitFrame(t, sends, ports.MsgOutput)
749- require.True(t, newSess.ephemeral)732+
733+ require.False(t, ac.overlays.paletteActive())
734+ require.False(t, ac.overlays.promptActive())
735+ require.Equal(t, 2, sessionCount(d))
736+ newSess := ac.currentSession()
737+ require.Equal(t, tc.wantName, newSess.name)
738+ require.Equal(t, tc.ephemeral, newSess.ephemeral)
739+ })
740+ }
750 }741 }
751 742
752 func TestPaletteReopensWithSuccessfulCommandFirst(t *testing.T) {743 func TestPaletteReopensWithSuccessfulCommandFirst(t *testing.T) {
D scripts/dev/Dockerfile +0 -22
@@ -1,22 +0,0 @@
1-# syntax=docker/dockerfile:1
2-FROM golang:1.26 AS build
3-WORKDIR /src
4-COPY go.mod go.sum ./
5-RUN go mod download
6-COPY . .
7-RUN CGO_ENABLED=0 go build -trimpath -o /out/vev .
8-
9-FROM debian:bookworm-slim
10-RUN apt-get update \
11- && apt-get install --yes --no-install-recommends bash ca-certificates \
12- && rm -rf /var/lib/apt/lists/* \
13- && useradd --create-home --uid 1000 --shell /bin/bash vev
14-COPY --from=build /out/vev /usr/local/bin/vev
15-USER vev
16-WORKDIR /home/vev
17-ENV HOME=/home/vev \
18- SHELL=/bin/bash \
19- TERM=xterm-256color \
20- COLORTERM=truecolor \
21- XDG_STATE_HOME=/home/vev/.local/state
22-ENTRYPOINT ["/usr/local/bin/vev"]
@@ -1,22 +0,0 @@
1-# syntax=docker/dockerfile:1
2-FROM golang:1.26 AS build
3-WORKDIR /src
4-COPY go.mod go.sum ./
5-RUN go mod download
6-COPY . .
7-RUN CGO_ENABLED=0 go build -trimpath -o /out/vev .
8-
9-FROM debian:bookworm-slim
10-RUN apt-get update \
11- && apt-get install --yes --no-install-recommends bash ca-certificates \
12- && rm -rf /var/lib/apt/lists/* \
13- && useradd --create-home --uid 1000 --shell /bin/bash vev
14-COPY --from=build /out/vev /usr/local/bin/vev
15-USER vev
16-WORKDIR /home/vev
17-ENV HOME=/home/vev \
18- SHELL=/bin/bash \
19- TERM=xterm-256color \
20- COLORTERM=truecolor \
21- XDG_STATE_HOME=/home/vev/.local/state
22-ENTRYPOINT ["/usr/local/bin/vev"]

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 12

Tags 11

↑↓ moveenter openesc close