mirror of
https://github.com/Dvorinka/Dash.git
synced 2026-06-03 23:12:56 +00:00
b17a06fbba
A clean, customizable homelab dashboard inspired by CasaOS. Features: - Empty-first dashboard (no demo data) - 3 themes: Light, Dark, CasaOS glassmorphism - Widgets: Clock (multi-timezone), Pi-hole, Memos, Immich, Image - Drag & drop app organization - Grid + list view for apps - Groups with collapse/expand - Proper widget refresh handling - Visual timezone picker - Square app cards with hover effects Stack: Go + Gin + PostgreSQL + Next.js 15 + React 19 + Tailwind CSS + shadcn/ui
67 lines
1.6 KiB
Go
67 lines
1.6 KiB
Go
package services
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"dash/backend/internal/store"
|
|
)
|
|
|
|
func TestNormalizeServicePrimaryFallback(t *testing.T) {
|
|
input := store.ServiceInput{
|
|
Name: " Router ",
|
|
URLs: []store.ServiceURLInput{
|
|
{Label: "local", Kind: "local", URL: "http://router.local"},
|
|
},
|
|
}
|
|
got, err := NormalizeService(input)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got.Name != "Router" {
|
|
t.Fatalf("name = %q", got.Name)
|
|
}
|
|
if !got.URLs[0].IsPrimary {
|
|
t.Fatal("first URL not made primary")
|
|
}
|
|
}
|
|
|
|
func TestNormalizeServiceRejectsTwoPrimary(t *testing.T) {
|
|
_, err := NormalizeService(store.ServiceInput{
|
|
Name: "Router",
|
|
URLs: []store.ServiceURLInput{
|
|
{Label: "local", Kind: "local", URL: "http://router.local", IsPrimary: true},
|
|
{Label: "wan", Kind: "external", URL: "https://router.example.com", IsPrimary: true},
|
|
},
|
|
})
|
|
if err == nil {
|
|
t.Fatal("accepted two primary URLs")
|
|
}
|
|
}
|
|
|
|
func TestMaskWidget(t *testing.T) {
|
|
widget := store.WidgetInstance{
|
|
Type: "pihole",
|
|
Config: json.RawMessage(`{"baseUrl":"http://pihole.local","apiToken":"secret"}`),
|
|
}
|
|
got := MaskWidget(widget)
|
|
if strings.Contains(string(got.Config), "secret") {
|
|
t.Fatalf("token leaked: %s", got.Config)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeWidgetPatchValidatesCurrentType(t *testing.T) {
|
|
current := store.WidgetInstance{
|
|
Type: "image",
|
|
Title: "Photo",
|
|
Config: json.RawMessage(`{"imageUrl":"https://example.com/a.png"}`),
|
|
}
|
|
_, err := NormalizeWidgetPatch(current, store.WidgetInput{
|
|
Config: json.RawMessage(`{"imageUrl":"/relative.png"}`),
|
|
})
|
|
if err == nil {
|
|
t.Fatal("accepted invalid image config without explicit type")
|
|
}
|
|
}
|