Files
github__gh-stack/internal/tui/shared/header_test.go
Sameen Karim 0efc764f8c Redesign TUI shared header and embed the GitHub logo as an image (#143)
* Redesign the shared header and embed the GitHub logo as an image

Rework the shared gh-stack header (used by `view` and `modify`, and reused
by `submit` later in this stack) for a cleaner, more responsive look, and
replace the braille/ASCII Invertocat with a real image of the GitHub mark.

- Logo: embed the Invertocat PNG with go:embed and draw it via an inline-
  image protocol (kitty or iTerm2). It is image-or-nothing: when no protocol
  is available, stdout is not a TTY, or we are inside tmux/screen, no logo is
  drawn and the text falls back to the normal left padding. Detection is
  environment-based and cached so it never blocks the TUI, and a fixed kitty
  image id lets the header clear or replace the logo in place instead of
  leaving copies behind.
- Layout: place the logo in the top-left corner beside the title and version,
  with the stack-info lines left-aligned beneath it on the same left margin.
  Size the box to its content for each view so there is no trailing empty row.
- Responsiveness: hide the logo progressively — first when the viewport is too
  narrow, then a little before the rest of the header at short heights, where
  a vertical resize could otherwise leave a ghost of the inline image.
- Add unit tests for the header's responsive thresholds.

* Drop the unused HeaderHeight constant and dedupe the header config build

Follow-up to review feedback on the shared-header redesign:

- Remove the HeaderHeight constant. Nothing referenced it (callers compute
  height via HeaderHeightFor), and its doc described a "maximum" that
  HeaderHeightFor does not actually enforce, so the comment was misleading.
- In the view and modify View() methods, build the header config once and reuse
  it for both RenderHeader and the height reservation instead of rebuilding it
  twice per frame. The click/scroll handlers keep deriving the height from the
  same config, so the header's dimensions remain a single source of truth.
2026-06-29 20:11:08 -04:00

42 lines
1.4 KiB
Go

package shared
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestArtFitsViewport(t *testing.T) {
tests := []struct {
name string
width, height int
want bool
}{
{"wide and tall enough", MinWidthForArt, MinHeightForArt, true},
{"comfortably large", 200, 60, true},
{"too short by one (resize-artifact band)", MinWidthForArt, MinHeightForArt - 1, false},
{"too narrow by one", MinWidthForArt - 1, MinHeightForArt, false},
{"wide but short", 200, 20, false},
{"tall but narrow", 40, 60, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, artFitsViewport(tt.width, tt.height))
})
}
}
// The logo must hide at a larger height than the header so that, while shrinking
// a tall window, the logo is gone before reaching the short heights where a
// vertical resize leaves a ghost of the inline image.
func TestLogoHidesBeforeHeader(t *testing.T) {
assert.Greater(t, MinHeightForArt, MinHeightForHeader,
"logo height threshold should exceed the header's so the logo hides first")
// At heights between the two thresholds the header shows but the logo does not.
for h := MinHeightForHeader; h < MinHeightForArt; h++ {
assert.True(t, ShouldShowHeader(MinWidthForArt, h), "header should show at height %d", h)
assert.False(t, artFitsViewport(MinWidthForArt, h), "logo should be hidden at height %d", h)
}
}