Files
tia-love/internal/app/settings_test.go
T
oxpoe 2d07935f83
CI / test (push) Successful in 39s
feat: layar Pengaturan (PRD §5.1.5) + tombol Setting beranda + toggle suara
- Layar Pengaturan (',' atau klik chip Pengaturan beranda): bahasa, mode tema,
  efek suara, volume, animasi, timestamp — semua berlaku langsung & tersimpan
  ke config (config.Save), plus path config + catatan.
- Audio live: Engine.SetEnabled/SetVolume/Enabled/Volume; init idempoten
  (readyOnce/started) sehingga engine yang lahir mati bisa dinyalakan tanpa
  restart — komentar 'shortcut' F-024 lama dihapus.
- Beranda: kolom tengah kini CTA + hint '[m] suara: …' (klik = toggle) +
  chip Pengaturan — draf dashboard lengkap.
- Tombol lama 'T'/'a'/'S' kini lewat applySetting yang sama (DRY + persist).
- TIA_LANG dihapus (tak perlu lagi): e2e memakai XDG_CONFIG_HOME temp
  (config bersih per tes) → tes tidak tergantung config pengguna.
- Toast: klik di luar kotak toast tidak lagi menutupnya (hanya klik pada toast)
  — tombol lain tetap bisa diklik saat notifikasi tampil.
- Tes: unit settings (apply/persist/jepit volume, baris plain==styled tanpa
  ANSI) + e2e TestSettingsScreen (klik chip, toggle, bahasa→Inggris,
  verifikasi config.yaml).
2026-10-16 04:07:33 +07:00

97 lines
2.9 KiB
Go

package app
import (
"os"
"strings"
"testing"
"github.com/charmbracelet/x/ansi"
"gitea.oxpoe.qzz.io/oxpoe/tia-love/internal/audio"
"gitea.oxpoe.qzz.io/oxpoe/tia-love/internal/config"
"gitea.oxpoe.qzz.io/oxpoe/tia-love/internal/i18n"
"gitea.oxpoe.qzz.io/oxpoe/tia-love/internal/ui/components"
"gitea.oxpoe.qzz.io/oxpoe/tia-love/internal/ui/theme"
)
// TestSettingsApply — setiap perubahan pengaturan berlaku + tersimpan ke config
// (tanpa restart, tanpa edit file); volume dijepit 0-100.
func TestSettingsApply(t *testing.T) {
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
m := Model{
cfg: config.Default(),
sound: audio.New(audio.Options{Enabled: true, Volume: 70}),
toast: components.NewToast(),
}
// volume: +10 lalu jepit di 100
m.applySetting("volume", 10)
if got := m.sound.Volume(); got != 80 {
t.Fatalf("volume = %d, mau 80", got)
}
m.sound.SetVolume(95)
m.cfg.UI.SoundVolume = 95
m.applySetting("volume", 10)
if got := m.sound.Volume(); got != 100 {
t.Fatalf("volume harus dijepit 100, dapat %d", got)
}
// efek suara: nyala → mati
m.applySetting("sound", 0)
if m.sound.Enabled() {
t.Fatal("efek suara harus mati setelah toggle")
}
// bahasa: id → en (katalog aktif ikut berubah)
m.applySetting("language", 0)
if m.cfg.UI.Language != "en" {
t.Fatalf("bahasa config = %q, mau en", m.cfg.UI.Language)
}
if got := i18n.T("settings.language"); got != "Language" {
t.Fatalf("katalog belum ikut ganti: %q", got)
}
i18n.SetLang("id") // kembalikan default untuk tes lain
// tema mundur: auto ← terminal
if got := cycleBack(theme.ModeAuto); got != theme.ModeTerminal {
t.Fatalf("cycleBack(auto) = %q", got)
}
// semua tercatat di config.yaml
b, err := os.ReadFile(config.Path())
if err != nil {
t.Fatalf("config tidak terbaca: %v", err)
}
for _, want := range []string{"language: en", "sound_enabled: false", "sound_volume: 100"} {
if !strings.Contains(string(b), want) {
t.Fatalf("config tidak memuat %q:\n%s", want, b)
}
}
}
// TestSettingsRowGeometry — teks baris (setelah ANSI dibuang) harus sama dengan
// teks plain yang dipakai hit-test klik, termasuk zona volume - / +.
func TestSettingsRowGeometry(t *testing.T) {
m := Model{cfg: config.Default(), sound: audio.New(audio.Options{Volume: 70}), settingsRow: -1}
for i := range settingsRowIDs {
plain := m.settingsRowPlain(i)
if plain == "" {
t.Fatalf("baris %d kosong", i)
}
if strings.ContainsRune(plain, 0x1b) {
t.Fatalf("baris %d (plain) tidak boleh memuat ANSI: %q", i, plain)
}
if got := ansi.Strip(m.settingsRowLine(i, 60)); got != plain {
t.Fatalf("baris %d: styled=%q plain=%q", i, got, plain)
}
}
m.settingsRow = 0
if got := ansi.Strip(m.settingsRowLine(0, 60)); !strings.HasPrefix(got, m.settingsRowPlain(0)) {
t.Fatalf("baris terpilih tidak selaras: %q", got)
}
vol := m.settingsRowPlain(3)
if !strings.Contains(vol, "[ - ]") || !strings.Contains(vol, "[ + ]") {
t.Fatalf("baris volume tanpa zona -/+: %q", vol)
}
}