package tui import ( "strings" "testing" "github.com/charmbracelet/lipgloss" "github.com/lwoodard/rtsp-streamer/internal/config" ) // TestRenderGrid prints a representative editor grid so the layout can be // eyeballed with `go test -run RenderGrid -v ./internal/tui`. func TestRenderGrid(t *testing.T) { lipgloss.SetColorProfile(0) // strip ANSI so the plain grid is readable in logs cfg := &config.Config{ Layouts: []config.Layout{{ Name: "main-plus", Grid: "4x3", Tiles: []config.Tile{ {Camera: "Front Door", Col: 0, Row: 0, ColSpan: 3, RowSpan: 3}, {Camera: "Driveway West", Col: 3, Row: 0}, {Camera: "Back Yard", Col: 3, Row: 1}, {Camera: "G3 Flex", Col: 3, Row: 2}, }, }}, } m := &model{cfg: cfg, editLayout: 0, edCol: 3, edRow: 0} t.Log("\n" + m.viewLayoutEdit()) // A long name (>cellW) must clip with an ellipsis, never produce the // U+FFFD replacement char from slicing a multi-byte rune mid-way. cols, rows := m.gridDims() grid := m.renderGrid(cols, rows) if strings.ContainsRune(grid, '�') { t.Errorf("grid contains a broken multi-byte character:\n%s", grid) } } // TestRenderPicker prints the camera picker (with the live grid and "already // placed" markers) for a layout that has a long camera name. func TestRenderPicker(t *testing.T) { lipgloss.SetColorProfile(0) cfg := &config.Config{ Cameras: []config.Camera{ {Name: "Driveway West"}, {Name: "Front Door"}, {Name: "Back Yard"}, {Name: "Garage"}, }, Layouts: []config.Layout{{ Name: "quad", Grid: "2x2", Tiles: []config.Tile{ {Camera: "Driveway West", Col: 0, Row: 0}, {Camera: "Front Door", Col: 1, Row: 0}, }, }}, } m := &model{cfg: cfg, editLayout: 0, edCol: 0, edRow: 1, cursor: 1, screen: screenCameraPicker} out := m.viewCameraPicker() if strings.ContainsRune(out, '�') { t.Errorf("picker contains a broken character:\n%s", out) } t.Log("\n" + out) }