mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-16 14:49:09 +02:00
Surface the running server build version in the Help popover so self-hosted operators can confirm what's deployed and include it in bug reports. - Backend exposes it via /api/config's server_version (from main.version), omitempty so older/unstamped builds omit the field. - Unstamped "dev" builds are normalized to empty and the row stays hidden. - The row is suppressed on the managed cloud (frontend host multica.ai) and shown only on self-hosted deployments. - Frontend renders a muted footer row in the Help popover only when the value is non-empty; i18n added for en/ja/ko/zh-Hans.
136 lines
4.2 KiB
Go
136 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
func TestRedisClientName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
existing string
|
|
suffix string
|
|
want string
|
|
}{
|
|
{"empty_suffix_returns_existing", "multica-api:store", "", "multica-api:store"},
|
|
{"empty_existing_uses_default_prefix", "", "store", "multica-api:store"},
|
|
{"both_set_joins_with_colon", "custom", "store", "custom:store"},
|
|
{"empty_both_returns_empty", "", "", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := redisClientName(tt.existing, tt.suffix)
|
|
if got != tt.want {
|
|
t.Errorf("redisClientName(%q, %q) = %q, want %q", tt.existing, tt.suffix, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewNamedRedisClient_SetsClientName(t *testing.T) {
|
|
t.Setenv("REDIS_DISABLE_CLIENT_NAME", "")
|
|
base := &redis.Options{Addr: "localhost:6379"}
|
|
client := newNamedRedisClient(base, "store")
|
|
defer client.Close()
|
|
|
|
opts := client.Options()
|
|
if opts.ClientName != "multica-api:store" {
|
|
t.Errorf("ClientName = %q, want %q", opts.ClientName, "multica-api:store")
|
|
}
|
|
}
|
|
|
|
func TestNewNamedRedisClient_DisableClientName(t *testing.T) {
|
|
t.Setenv("REDIS_DISABLE_CLIENT_NAME", "true")
|
|
base := &redis.Options{Addr: "localhost:6379"}
|
|
client := newNamedRedisClient(base, "store")
|
|
defer client.Close()
|
|
|
|
opts := client.Options()
|
|
if opts.ClientName != "" {
|
|
t.Errorf("ClientName = %q, want empty when REDIS_DISABLE_CLIENT_NAME=true", opts.ClientName)
|
|
}
|
|
}
|
|
|
|
func TestNewNamedRedisClient_DisableClientName_ClearsPreExistingName(t *testing.T) {
|
|
t.Setenv("REDIS_DISABLE_CLIENT_NAME", "true")
|
|
// Simulate REDIS_URL with ?client_name=foo — ParseURL sets ClientName.
|
|
base := &redis.Options{Addr: "localhost:6379", ClientName: "foo"}
|
|
client := newNamedRedisClient(base, "store")
|
|
defer client.Close()
|
|
|
|
opts := client.Options()
|
|
if opts.ClientName != "" {
|
|
t.Errorf("ClientName = %q, want empty: REDIS_DISABLE_CLIENT_NAME must clear pre-existing name from URL", opts.ClientName)
|
|
}
|
|
}
|
|
|
|
func TestNewNamedRedisClient_DisableClientName_InvalidValue(t *testing.T) {
|
|
t.Setenv("REDIS_DISABLE_CLIENT_NAME", "not-a-bool")
|
|
base := &redis.Options{Addr: "localhost:6379"}
|
|
client := newNamedRedisClient(base, "store")
|
|
defer client.Close()
|
|
|
|
opts := client.Options()
|
|
// Invalid value falls back to default (false), so ClientName IS set
|
|
if opts.ClientName != "multica-api:store" {
|
|
t.Errorf("ClientName = %q, want %q (invalid env should fall back to naming enabled)", opts.ClientName, "multica-api:store")
|
|
}
|
|
}
|
|
|
|
// TestNormalizeServerVersion covers the router-config wiring path (not just
|
|
// a hand-set handler.Config field): an unstamped "dev" build must not leak
|
|
// into /api/config's server_version, or the Help popover would render
|
|
// "Server version dev" instead of hiding the row.
|
|
func TestNormalizeServerVersion(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
want string
|
|
}{
|
|
{"unstamped_dev_default_becomes_empty", "dev", ""},
|
|
{"already_empty_stays_empty", "", ""},
|
|
{"stamped_release_tag_passes_through", "v0.4.0", "v0.4.0"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := normalizeServerVersion(tt.in); got != tt.want {
|
|
t.Errorf("normalizeServerVersion(%q) = %q, want %q", tt.in, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEnvBool(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
value string
|
|
def bool
|
|
want bool
|
|
}{
|
|
{"empty_returns_default_false", "TEST_ENV_BOOL_1", "", false, false},
|
|
{"empty_returns_default_true", "TEST_ENV_BOOL_2", "", true, true},
|
|
{"true_string", "TEST_ENV_BOOL_3", "true", false, true},
|
|
{"false_string", "TEST_ENV_BOOL_4", "false", true, false},
|
|
{"one_is_true", "TEST_ENV_BOOL_5", "1", false, true},
|
|
{"zero_is_false", "TEST_ENV_BOOL_6", "0", true, false},
|
|
{"invalid_returns_default", "TEST_ENV_BOOL_7", "maybe", false, false},
|
|
{"invalid_returns_default_true", "TEST_ENV_BOOL_8", "maybe", true, true},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.value != "" {
|
|
t.Setenv(tt.key, tt.value)
|
|
} else {
|
|
os.Unsetenv(tt.key)
|
|
}
|
|
got := envBool(tt.key, tt.def)
|
|
if got != tt.want {
|
|
t.Errorf("envBool(%q, %v) = %v, want %v", tt.key, tt.def, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|