CI / test (push) Successful in 39s
- 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).
97 lines
2.9 KiB
Go
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)
|
|
}
|
|
}
|