package webui import ( "strings" "testing" ) // ---- Toaster ---- // The whole point of Toaster over ToastProvider: it removes toasts by itself. On // the server there is no clock (SetTimeout is a no-op), so nothing is scheduled — // but the toast still renders, which is what SSR should show. func TestToasterPushAndDismiss(t *testing.T) { tr := NewToaster(ToasterOptions{}) id := tr.Success("Saved.") if len(tr.Toasts()) != 1 { t.Fatalf("Push added %d toasts, want 1", len(tr.Toasts())) } got := tr.Toasts()[0] if got.ID != id || got.Type != ToastSuccess || got.Message != "Saved." { t.Errorf("unexpected toast: %+v", got) } // An unset duration must become the default, NOT "forever": a toast that never // leaves is how a notification area silently fills up. if got.Duration != DefaultToastDuration { t.Errorf("Duration = %d, want the default %d", got.Duration, DefaultToastDuration) } if !got.ShowProgress { t.Error("an auto-dismissing toast should show its countdown") } tr.Dismiss(id) if len(tr.Toasts()) != 0 { t.Errorf("Dismiss left %d toasts", len(tr.Toasts())) } } func TestToasterSticky(t *testing.T) { tr := NewToaster(ToasterOptions{}) tr.Push(Toast{Message: "stays", Duration: ToastSticky}) got := tr.Toasts()[0] if got.Duration != ToastSticky { t.Errorf("Duration = %d, want ToastSticky", got.Duration) } // No countdown bar on something that is not counting down. if got.ShowProgress { t.Error("a sticky toast should not show a progress bar") } } func TestToasterIDsAreUnique(t *testing.T) { tr := NewToaster(ToasterOptions{}) seen := map[string]bool{} for range 5 { id := tr.Info("x") if seen[id] { t.Fatalf("duplicate toast ID %q", id) } seen[id] = true } tr.Clear() if len(tr.Toasts()) != 0 { t.Error("Clear left toasts behind") } } func TestToasterRendersCountdownBar(t *testing.T) { tr := NewToaster(ToasterOptions{}) tr.Success("Saved.") html := renderNode(tr.Render()) // The bar is DECLARED at full width; the countdown is an imperative transition // from there to 0. If the declared width ever stopped being 100%, the bar would // start empty and the animation would be invisible. if !strings.Contains(html, "width:100%") { t.Errorf("countdown bar not declared at full width:\n%s", html) } if !strings.Contains(html, "circle-check") && !strings.Contains(html, "