mirror of
https://github.com/Dvorinka/Dash.git
synced 2026-06-03 23:12:56 +00:00
🚀 Dash - Homelab Dashboard
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
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
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")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user