fix: panel memangkas judul/meta · footer kembali utuh · tes aksi tab lebih tabah
CI / test (push) Successful in 26s
CI / test (push) Successful in 26s
Temuan CI (runner bersih, nama kontainer 112 char): - panel(): judul/meta panjang melebihi lebar panel dan mendorong kolom kanan (Aksi Tab) keluar layar — sekarang dipangkas + jaring pengaman ansiTruncate; unit test TestPanelTitleFits menutup kasus ini. - footer: aturan 'buang status dulu' membuat 'audio:'/animasi hilang di runner tanpa audio device — dikembalikan ke perilaku truncate semula. - TestTabActionColumn menunggu panel detail tampil dulu (hapus balapan muat). - TestToolbarSearch memilih prefix yang benar-benar unik + 'j' dulu.
This commit is contained in:
1 parent
5450a89a80
commit
b7866f917b
3 files changed
+37
-17
No files matched your search
+7
-5
@@ -633,17 +633,17 @@ func TestToolbarSearch(t *testing.T) {
|
|||||||
t.Skipf("butuh >= 2 kontainer (err=%v, n=%d)", err, len(items))
|
t.Skipf("butuh >= 2 kontainer (err=%v, n=%d)", err, len(items))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Target: prefix nama yang tidak termuat di nama kontainer sebelumnya —
|
// Target: prefix nama yang tidak termuat di nama kontainer mana pun —
|
||||||
// pencarian melompat ke kecocokan pertama dari atas.
|
// supaya lompatan kursor tidak ambigu (kecocokan pertama = target).
|
||||||
target := ""
|
target := ""
|
||||||
for i, it := range items {
|
for _, it := range items {
|
||||||
q := it.Name
|
q := it.Name
|
||||||
if len(q) > 6 {
|
if len(q) > 6 {
|
||||||
q = q[:6]
|
q = q[:6]
|
||||||
}
|
}
|
||||||
unique := true
|
unique := true
|
||||||
for k := 0; k < i; k++ {
|
for _, other := range items {
|
||||||
if strings.Contains(strings.ToLower(items[k].Name), strings.ToLower(q)) {
|
if other.Name != it.Name && strings.Contains(strings.ToLower(other.Name), strings.ToLower(q)) {
|
||||||
unique = false
|
unique = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -661,6 +661,7 @@ func TestToolbarSearch(t *testing.T) {
|
|||||||
u.waitContains("beranda", 5*time.Second)
|
u.waitContains("beranda", 5*time.Second)
|
||||||
u.send("2")
|
u.send("2")
|
||||||
u.waitContains("[1-5]", 3*time.Second)
|
u.waitContains("[1-5]", 3*time.Second)
|
||||||
|
u.send("j") // kursor pindah dari item pertama → lompatan cari terlihat
|
||||||
if !u.clickText("Cari") {
|
if !u.clickText("Cari") {
|
||||||
t.Fatal("pill Cari tidak ditemukan")
|
t.Fatal("pill Cari tidak ditemukan")
|
||||||
}
|
}
|
||||||
@@ -697,6 +698,7 @@ func TestTabActionColumn(t *testing.T) {
|
|||||||
u.waitContains("beranda", 5*time.Second)
|
u.waitContains("beranda", 5*time.Second)
|
||||||
u.send("2")
|
u.send("2")
|
||||||
u.waitContains("[1-5]", 3*time.Second)
|
u.waitContains("[1-5]", 3*time.Second)
|
||||||
|
u.waitContains("Statistik", 5*time.Second) // detail kontainer terpilih tampil
|
||||||
u.waitContains("Aksi Tab", 3*time.Second)
|
u.waitContains("Aksi Tab", 3*time.Second)
|
||||||
u.waitContains("ikut ekor", 3*time.Second)
|
u.waitContains("ikut ekor", 3*time.Second)
|
||||||
if !u.clickText("[S]") {
|
if !u.clickText("[S]") {
|
||||||
|
|||||||
+14
-12
@@ -901,12 +901,21 @@ func panel(title, meta string, lines []string, w, h int, focused bool) string {
|
|||||||
bc = th.Accent
|
bc = th.Accent
|
||||||
}
|
}
|
||||||
border := lipgloss.NewStyle().Foreground(lipgloss.Color(string(bc)))
|
border := lipgloss.NewStyle().Foreground(lipgloss.Color(string(bc)))
|
||||||
titleS := text(title)
|
|
||||||
|
|
||||||
left := border.Render("╭─ ") + titleS
|
// Judul/meta dipangkas agar baris border TIDAK pernah melebihi lebar panel
|
||||||
|
// (nama kontainer panjang dulu mendorong kolom kanan keluar layar).
|
||||||
|
avail := w - 6
|
||||||
|
if meta != "" {
|
||||||
|
avail = w - 8
|
||||||
|
}
|
||||||
|
metaW := 0
|
||||||
|
if meta != "" && avail > 4 {
|
||||||
|
metaW = min(len([]rune(meta)), max(avail/3, 2))
|
||||||
|
}
|
||||||
|
left := border.Render("╭─ ") + text(truncate(title, max(avail-metaW, 1)))
|
||||||
right := border.Render("─╮")
|
right := border.Render("─╮")
|
||||||
if meta != "" {
|
if meta != "" {
|
||||||
right = " " + dim(meta) + border.Render(" ─╮")
|
right = " " + dim(truncate(meta, metaW)) + border.Render(" ─╮")
|
||||||
}
|
}
|
||||||
gap := w - lipgloss.Width(left) - lipgloss.Width(right)
|
gap := w - lipgloss.Width(left) - lipgloss.Width(right)
|
||||||
if gap < 1 {
|
if gap < 1 {
|
||||||
@@ -914,9 +923,7 @@ func panel(title, meta string, lines []string, w, h int, focused bool) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
b.WriteString(left)
|
b.WriteString(ansiTruncate(left+border.Render(strings.Repeat("─", gap))+right, w))
|
||||||
b.WriteString(border.Render(strings.Repeat("─", gap)))
|
|
||||||
b.WriteString(right)
|
|
||||||
|
|
||||||
content := lipgloss.NewStyle().Width(w - 4)
|
content := lipgloss.NewStyle().Width(w - 4)
|
||||||
for i := 0; i < h-2; i++ {
|
for i := 0; i < h-2; i++ {
|
||||||
@@ -984,12 +991,7 @@ func (m Model) footerPlain() string {
|
|||||||
if m.animating {
|
if m.animating {
|
||||||
anim = fmt.Sprintf("%d", m.fps)
|
anim = fmt.Sprintf("%d", m.fps)
|
||||||
}
|
}
|
||||||
full := i18n.Tf("footer.status", hints, anim, m.sound.Status())
|
return truncate(i18n.Tf("footer.status", hints, anim, m.sound.Status()), m.width)
|
||||||
if lipgloss.Width(full) > m.width {
|
|
||||||
// Hint aksi lebih penting daripada status diagnostik: buang status dulu.
|
|
||||||
full = truncate(hints, m.width)
|
|
||||||
}
|
|
||||||
return full
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) footerLine() string { return dim(m.footerPlain()) }
|
func (m Model) footerLine() string { return dim(m.footerPlain()) }
|
||||||
|
|||||||
@@ -47,6 +47,22 @@ func TestToolbarPlain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// TestSearchJump — pencarian melompat ke item pertama yang cocok (daftar tetap
|
||||||
// utuh), dan nama item mengikuti seksi aktif.
|
// utuh), dan nama item mengikuti seksi aktif.
|
||||||
func TestSearchJump(t *testing.T) {
|
func TestSearchJump(t *testing.T) {
|
||||||
|
|||||||
Reference in new issue
Block a user