Files
llmgw/internal/web/i18n_mirror_test.go
T
Ilker ManapandClaude Opus 5.5 11231d8c2b The portal in English and Turkish: a catalogue per language, a switcher at the foot of every page, landing.language, Turkish numbers and dates
Every template and handler message in internal/web goes through a JSON
catalogue under internal/web/locales/<code>/, with English as the fallback.
The language is the person's choice (a cookie set by /_lang/{code}), else
Accept-Language, else landing.language. Tests refuse a key some language
lacks, a translation with other arguments than English, and template text
left in English.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 00:12:53 +02:00

151 lines
6.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package web
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"
"gitea.mynodes.xyz/ilker/llmgw/internal/control/catalog"
"gitea.mynodes.xyz/ilker/llmgw/internal/hf"
"gitea.mynodes.xyz/ilker/llmgw/internal/mirror"
)
// mirrorInTurkish asks the mirror page for path as somebody who chose
// Turkish, with a form when there is one.
func mirrorInTurkish(t *testing.T, mux *http.ServeMux, path string, form url.Values) string {
t.Helper()
method, body := http.MethodGet, ""
if form != nil {
method, body = http.MethodPost, form.Encode()
}
r := httptest.NewRequest(method, path, strings.NewReader(body))
if form != nil {
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
r.AddCookie(&http.Cookie{Name: SessionCookie, Value: "good"})
r.AddCookie(&http.Cookie{Name: csrfCookie, Value: "tok"})
r.AddCookie(&http.Cookie{Name: langCookie, Value: "tr"})
w := httptest.NewRecorder()
mux.ServeHTTP(w, r)
return w.Body.String()
}
func wantAll(t *testing.T, what, body string, want ...string) {
t.Helper()
for _, s := range want {
if !strings.Contains(body, s) {
t.Errorf("%s lacks %q", what, s)
}
}
}
func TestTheMirrorPageSpeaksTurkishWhenAsked(t *testing.T) {
m := &fakeMirror{models: []mirror.Status{
{Model: "qwen", Version: "2026-09", File: "model.gguf", State: mirror.Present,
BytesDone: 491400032, BytesTotal: 491400032},
{Model: "llama", Version: "v1", File: "l.gguf", State: mirror.Fetching,
BytesDone: 1 << 20, BytesTotal: 4 << 20},
}}
reg := &fakeRegistry{results: []hf.Model{{ID: "Qwen/Qwen3-8B-GGUF", Downloads: 1247,
CreatedAt: time.Now().Add(-3 * time.Hour)}}}
mux := mirrorPageWith(t, m, reg, true)
held := mirrorInTurkish(t, mux, "/admin/mirror", nil)
wantAll(t, "the held tab", held,
`<html lang="tr">`, "<h1>Model aynası</h1>", ">Aynadakiler <span class=\"count\">1 · 1 iniyor</span>",
"Hugging Face&#39;i keşfet", "URL ile indir",
"468,6 MiB", // the size, written the Turkish way
"4,0 MiB içinden %25",
"adresi kopyala", "sunulmuyor",
`data-confirm="qwen/2026-09 ve içindeki tüm dosyalar kaldırılsın mı?"`,
`"kopyalandı"`, // the copy button's script speaks it too
)
for _, english := range []string{"Model mirror", "copy address", "not served", "so far"} {
if strings.Contains(held, english) {
t.Errorf("the Turkish page still says %q", english)
}
}
explore := mirrorInTurkish(t, mux, "/admin/mirror?tab=explore", nil)
wantAll(t, "the explorer", explore,
"Gündemde", "En çok indirilen", "Her boyut", ">Ara</button>",
"<th>Depo</th>", "1,2 bin", ">3 sa<", `"Yükleniyor…"`)
fetch := mirrorInTurkish(t, mux, "/admin/mirror?tab=fetch", nil)
wantAll(t, "the fetch tab", fetch, "Kaynak URL", "İndirmeyi başlat", "Yine de indir")
// What a change answers is in the same language as the page it came from.
done := mirrorInTurkish(t, mux, "/admin/mirror/fetch", url.Values{"csrf": {"tok"},
"source": {"http://x/a.gguf", "http://x/b.gguf"}, "model": {"qwen"}, "version": {"2026-10"}})
wantAll(t, "the fetch's answer", done, "qwen/2026-10 indirilmeye başlandı (2 dosya)")
refused := mirrorInTurkish(t, mux, "/admin/mirror/fetch", url.Values{"csrf": {"tok"}, "tab": {"fetch"}})
wantAll(t, "the refusal", refused, "bir kaynak URL gerekli")
}
func TestAHeldModelsCardSpeaksTurkish(t *testing.T) {
fleet := &roomyFleet{more: 2, blocked: []string{"n2: 2 GB free of 32, profile needs 6"}}
cat := coderCatalog()
mux := mirrorPageDeps(t, MirrorDeps{Mirror: &fakeMirror{models: []mirror.Status{
{Model: "coder", Version: "v1", File: "c.gguf", State: mirror.Present, BytesDone: 5 << 30},
}}, Catalog: cat, Fleet: fleet}, true)
card := mirrorInTurkish(t, mux, "/admin/mirror?tab=held&open=coder:v1", nil)
wantAll(t, "the card", card,
"Şu anda 2 tane daha için yer var: n1, n1.", ">hazır</span>", "1sa01dk", "3,5 çekirdek",
"Sürekli çalışan", "varsayılan (standart)", "Kaydet", "LoRA adaptörleri")
msg := mirrorInTurkish(t, mux, "/admin/mirror/replicas", url.Values{"csrf": {"tok"},
"model": {"coder"}, "min": {"2"}, "max": {"4"}, "open": {"coder:v1"}})
wantAll(t, "the change's answer", msg,
"coder 2 replikayla, yük altında en çok 4 replikayla çalışıyor; şu anda 3 tanesine yer var")
}
func TestServingPlansAreDescribedInTurkish(t *testing.T) {
tr := langByCode("tr")
form := url.Values{
"name": {"m"}, "source": {"http://x/m"}, "engine": {"llamacpp"}, "replicas": {"1"},
"context_length": {"4096"}, "ctx_size": {"16384"}, "parallel": {"4"},
"placement": {"gpu:t4"}, "gpus": {"4"}, "min_memory_gb": {"8"},
}
m, err := buildModel(tr, form.Get)
if err != nil {
t.Fatal(err)
}
if got, want := describeServe(tr, m), "llama.cpp, tek düğümün 4 adet t4 GPU'su üzerinde, "+
"8 GB ana makine belleği, 16.384 token bağlam havuzu, 4 paralel isteğe bölünmüş (her birine 4.096)"; got != want {
t.Errorf("got %q, want %q", got, want)
}
cpu := catalog.Model{Profiles: []catalog.Profile{{Engine: "llamacpp", CPUCores: 6}}}
if got := describeServe(tr, cpu); got != "llama.cpp, CPU üzerinde, 6 çekirdek" {
t.Errorf("on the CPU: %q", got)
}
form.Set("context_length", "çok")
if _, err := buildModel(tr, form.Get); err == nil || err.Error() != "bağlam uzunluğu tam sayı olmalı" {
t.Errorf("a bad number is refused as %v", err)
}
form.Set("context_length", "4096")
form.Set("engine", "vllm")
form.Set("placement", "cpu")
if _, err := buildModel(tr, form.Get); err == nil || !strings.Contains(err.Error(), "GPU sınıfı seçin") {
t.Errorf("vLLM on the CPU is refused as %v", err)
}
// The plan the form opens with, on a fleet with no GPU and no vLLM.
page := mirrorInTurkish(t, servePage(t, []mirror.Status{held("coder", "v1", "m.gguf")}, &fakeCatalog{}, 0),
"/admin/mirror?serve=coder:v1", nil)
wantAll(t, "the serve form", page,
"<code>http://mirror:8081/coder/v1/m.gguf</code>, <strong>llamacpp</strong> ile sunulacak.",
`<option value="cpu" selected>CPU: bu kümede GPU yok</option>`,
"Kataloğa ekle", "Gereken RAM (GB)", "Bellek: ağırlıkların bir buçuk katı artı iki.",
`"Şöyle çalışacak: %s."`)
vllm := mirrorInTurkish(t, servePage(t, []mirror.Status{held("big", "v1", "model.safetensors")}, &fakeCatalog{}, 0, "llamacpp"),
"/admin/mirror?serve=big:v1", nil)
wantAll(t, "the vLLM warning", vllm,
"hiçbir düğüm vllm kurulu olduğunu bildirmiyor", "Bu kümede GPU da yok")
}