| 1 | //go:build windows |
| 2 | |
| 3 | package notify |
| 4 | |
| 5 | import ( |
| 6 | "crypto/rand" |
| 7 | "errors" |
| 8 | "path/filepath" |
| 9 | "testing" |
| 10 | |
| 11 | "git.sr.ht/~jackmordaunt/go-toast/v2" |
| 12 | "golang.org/x/sys/windows/registry" |
| 13 | ) |
| 14 | |
| 15 | func TestWindowsNotificationsKeepDesktopIdentityAndReadableName(t *testing.T) { |
| 16 | registered := false |
| 17 | err := registerDesktopNotifications(func(data toast.AppData) error { |
| 18 | if data.AppID != "io.reasonix.desktop" { |
| 19 | t.Fatalf("registered ID = %q", data.AppID) |
| 20 | } |
| 21 | registered = true |
| 22 | return nil |
| 23 | }, func(id, name string) error { |
| 24 | if !registered || id != "io.reasonix.desktop" || name != "Reasonix" { |
| 25 | t.Fatalf("display name update = %q/%q, registered=%t", id, name, registered) |
| 26 | } |
| 27 | return nil |
| 28 | }) |
| 29 | if err != nil { |
| 30 | t.Fatal(err) |
| 31 | } |
| 32 | n := desktopNotification(Message{Title: "Done", Body: "Task completed"}) |
| 33 | if n.AppID != "io.reasonix.desktop" || n.Title != "Done" || n.Body != "Task completed" { |
| 34 | t.Fatalf("notification = %+v", n) |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | func TestWindowsNotificationRegistrationFailureDoesNotWriteMetadata(t *testing.T) { |
| 39 | want := errors.New("registration refused") |
| 40 | err := registerDesktopNotifications(func(toast.AppData) error { return want }, func(string, string) error { |
| 41 | t.Fatal("metadata written after registration failed") |
| 42 | return nil |
| 43 | }) |
| 44 | if !errors.Is(err, want) { |
| 45 | t.Fatalf("registration error = %v, want %v", err, want) |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | func TestNotificationDisplayNamePreservesOtherRegistrations(t *testing.T) { |
| 50 | prefix := "Reasonix.IdentityTest." + rand.Text() |
| 51 | ids := []string{prefix + ".Legacy", prefix + ".Desktop"} |
| 52 | for _, id := range ids { |
| 53 | path := filepath.Join("Software", "Classes", "AppUserModelId", id) |
| 54 | key, _, err := registry.CreateKey(registry.CURRENT_USER, path, registry.ALL_ACCESS) |
| 55 | if err != nil { |
| 56 | t.Fatal(err) |
| 57 | } |
| 58 | t.Cleanup(func() { _ = registry.DeleteKey(registry.CURRENT_USER, path) }) |
| 59 | if err := key.SetStringValue("DisplayName", id); err != nil { |
| 60 | t.Fatal(err) |
| 61 | } |
| 62 | if err := key.SetStringValue("CustomActivator", "preserve-activator"); err != nil { |
| 63 | t.Fatal(err) |
| 64 | } |
| 65 | key.Close() |
| 66 | } |
| 67 | if err := setNotificationDisplayName(ids[1], "Reasonix"); err != nil { |
| 68 | t.Fatal(err) |
| 69 | } |
| 70 | for i, id := range ids { |
| 71 | key, err := registry.OpenKey(registry.CURRENT_USER, filepath.Join("Software", "Classes", "AppUserModelId", id), registry.QUERY_VALUE) |
| 72 | if err != nil { |
| 73 | t.Fatal(err) |
| 74 | } |
| 75 | name, _, nameErr := key.GetStringValue("DisplayName") |
| 76 | activator, _, activatorErr := key.GetStringValue("CustomActivator") |
| 77 | key.Close() |
| 78 | want := id |
| 79 | if i == 1 { |
| 80 | want = "Reasonix" |
| 81 | } |
| 82 | if nameErr != nil || activatorErr != nil || name != want || activator != "preserve-activator" { |
| 83 | t.Fatalf("registration %s changed unexpectedly: name=%q (%v), activator=%q (%v)", id, name, nameErr, activator, activatorErr) |
| 84 | } |
| 85 | } |
| 86 | } |
| 87 |