Files
tia-love/internal/app/layout_test.go
T
oxpoe 75ead4be8a
CI / test (push) Successful in 27s
layout: bar atas workspace ala mock draf-tia + bar TAB membentang penuh
- Bar workspace jadi panel: judul 'workspace' di border, subjudul daftar seksi
  (stack, kontainer, image, volume, jaringan), pill Cari + tombol [+ stack]
  dan [konversi] di kanan — semua klikable (klik = paritas tombol huruf).
- Detail kontainer: bar TAB kini membentang penuh di atas TAB content dan
  kolom Aksi Tab (mock TAB ACTION); hit-test tab & kolom disesuaikan.
- Tes: unit TestWorkspaceBar (lebar 40/80/120) + e2e TestWorkspaceBar
  (subjudul tampil, klik [+ stack] membuka modal); posisi klik e2e lain
  digeser mengikuti tinggi bar.
2026-10-16 03:39:21 +07:00

104 lines
3.6 KiB
Go

package app
import (
"strings"
"testing"
"charm.land/lipgloss/v2"
"gitea.oxpoe.qzz.io/oxpoe/tia-love/internal/docker"
"gitea.oxpoe.qzz.io/oxpoe/tia-love/internal/i18n"
)
// TestDetailWidths — kolom aksi tab tampil hanya bila layar cukup lebar
// (tab bar detail tetap utuh di layar sempit).
func TestDetailWidths(t *testing.T) {
m := Model{width: 120, section: sectionContainers}
wDetail, wAct := m.detailWidths()
if wAct == 0 {
t.Fatalf("layar 120: kolom aksi harus tampil (wDetail=%d)", wDetail)
}
if wDetail+wAct != 120-m.leftWidth() {
t.Fatalf("layar 120: lebar tidak menjumlah (wDetail=%d wAct=%d)", wDetail, wAct)
}
m.width = 80
if _, wAct = m.detailWidths(); wAct != 0 {
t.Fatalf("layar 80: kolom aksi harus disembunyikan, dapat %d", wAct)
}
}
// TestWorkspaceBar — bar workspace memuat subjudul seksi + tombol stack,
// menampilkan query saat mode cari, dan tidak melebihi lebar dalam panel.
func TestWorkspaceBar(t *testing.T) {
for _, width := range []int{40, 80, 120} {
m := Model{width: width, view: viewList}
subLine, searchLine := m.workspaceBarPlain()
if !strings.Contains(subLine, i18n.T("toolbar.addStack")) || !strings.Contains(subLine, i18n.T("toolbar.convert")) {
t.Fatalf("w=%d: tombol stack/konversi tidak ada: %q", width, subLine)
}
if !strings.Contains(searchLine, "[ / "+i18n.T("toolbar.search")+" ]") {
t.Fatalf("w=%d: pill cari tidak ada: %q", width, searchLine)
}
inner := width - 4
if w := lipgloss.Width(subLine); w > inner {
t.Fatalf("w=%d: subjudul+tombol lebar %d > %d", width, w, inner)
}
if w := lipgloss.Width(searchLine); w > inner {
t.Fatalf("w=%d: pill cari lebar %d > %d", width, w, inner)
}
m.searching, m.query = true, "abc"
if _, searchLine = m.workspaceBarPlain(); !strings.Contains(searchLine, "/ abc") {
t.Fatalf("w=%d: query tidak tampil di pill: %q", width, searchLine)
}
}
// Subjudul = daftar seksi (mock): "stack, kontainer, image, volume, network".
m := Model{width: 120, view: viewList}
subLine, _ := m.workspaceBarPlain()
want := strings.ToLower(i18n.T("section.stacks")) + ", " +
strings.ToLower(i18n.T("section.containers")) + ", " +
strings.ToLower(i18n.T("section.images")) + ", " +
strings.ToLower(i18n.T("section.volumes")) + ", " +
strings.ToLower(i18n.T("section.networks"))
if !strings.HasPrefix(subLine, want) {
t.Fatalf("subjudul bar salah: %q (mau %q)", subLine, want)
}
}
// TestPanelTitleFits — judul/meta panjang tidak boleh melebihi lebar panel:
// nama kontainer/stack panjang pernah mendorong kolom kanan keluar layar.
func TestPanelTitleFits(t *testing.T) {
long := strings.Repeat("GITEA-ACTIONS-TASK-", 8)
for _, w := range []int{6, 10, 40, 100} {
for _, meta := range []string{"", "running", long} {
out := panel(long, meta, []string{"isi"}, w, 4, false)
for _, line := range strings.Split(out, "\n") {
if got := lipgloss.Width(line); got > w {
t.Fatalf("w=%d meta=%q: baris lebar %d > %d: %q", w, meta, got, w, line)
}
}
}
}
}
// TestSearchJump — pencarian melompat ke item pertama yang cocok (daftar tetap
// utuh), dan nama item mengikuti seksi aktif.
func TestSearchJump(t *testing.T) {
m := Model{
section: sectionContainers,
containers: []docker.Container{{Name: "alfa"}, {Name: "beta"}, {Name: "betawi"}},
}
m.query = "beta"
m.searchJumpCmd()
if got := m.cur(); got != 1 {
t.Fatalf("kursor = %d, mau 1 (kecocokan pertama)", got)
}
if m.itemName(2) != "betawi" {
t.Fatalf("itemName(2) = %q", m.itemName(2))
}
m.query = "tidak-ada"
m.searchJumpCmd()
if got := m.cur(); got != 1 {
t.Fatalf("tanpa kecocokan kursor harus tetap: %d", got)
}
}