返回 DeepSeek-Reasonix
icon_repair_windows_test.go
根目录 / desktop / icon_repair_windows_test.go
1 //go:build windows
2
3 package main
4
5 import (
6 "os"
7 "path/filepath"
8 "testing"
9 )
10
11 func TestRepairExistingWindowsShortcutsRepairsOnlyExistingFiles(t *testing.T) {
12 root := t.TempDir()
13 existing := filepath.Join(root, "Reasonix.lnk")
14 custom := filepath.Join(root, "Custom.lnk")
15 missing := filepath.Join(root, "Missing.lnk")
16 if err := os.WriteFile(existing, []byte("old shortcut"), 0o600); err != nil {
17 t.Fatal(err)
18 }
19 if err := os.WriteFile(custom, []byte("custom shortcut"), 0o600); err != nil {
20 t.Fatal(err)
21 }
22 launcher := filepath.Join(root, "reasonix-launcher.exe")
23 var wrote, notified []string
24 originalNotify := windowsNotifyShortcutChange
25 windowsNotifyShortcutChange = func(path string) { notified = append(notified, path) }
26 t.Cleanup(func() { windowsNotifyShortcutChange = originalNotify })
27
28 err := repairExistingWindowsShortcuts(
29 []string{existing, custom, missing},
30 launcher,
31 func(path, target string) (bool, error) {
32 if target != launcher {
33 t.Fatalf("shortcut target = %q, want %q", target, launcher)
34 }
35 wrote = append(wrote, path)
36 return path == existing, nil
37 },
38 )
39 if err != nil {
40 t.Fatal(err)
41 }
42 if len(wrote) != 2 || wrote[0] != existing || wrote[1] != custom {
43 t.Fatalf("repair attempts = %v, want %q and %q", wrote, existing, custom)
44 }
45 if len(notified) != 1 || notified[0] != existing {
46 t.Fatalf("shell notifications = %v, want only %q", notified, existing)
47 }
48 }
49
50 func TestReasonixWindowsShortcutTargetRequiresCurrentInstall(t *testing.T) {
51 root := filepath.Join(`C:\Program Files`, "Reasonix")
52 launcher := filepath.Join(root, "reasonix-launcher.exe")
53 tests := []struct {
54 name string
55 target string
56 want bool
57 }{
58 {name: "launcher", target: launcher, want: true},
59 {name: "flat desktop", target: filepath.Join(root, "reasonix-desktop.exe"), want: true},
60 {name: "launcher alias", target: filepath.Join(root, "Reasonix.exe"), want: true},
61 {name: "versioned desktop", target: filepath.Join(root, "versions", "v1.19.3", "reasonix-desktop.exe"), want: true},
62 {name: "other install", target: filepath.Join(`D:\Apps`, "Reasonix", "reasonix-launcher.exe"), want: false},
63 {name: "unrelated app", target: filepath.Join(root, "other.exe"), want: false},
64 {name: "empty", target: "", want: false},
65 }
66 for _, tt := range tests {
67 t.Run(tt.name, func(t *testing.T) {
68 if got := reasonixWindowsShortcutTarget(tt.target, launcher); got != tt.want {
69 t.Fatalf("reasonixWindowsShortcutTarget(%q, %q) = %v, want %v", tt.target, launcher, got, tt.want)
70 }
71 })
72 }
73 }
74
75 func TestReasonixWindowsStaleIconOnlyMatchesVersionedDesktop(t *testing.T) {
76 root := filepath.Join(`C:\Program Files, Inc`, "Reasonix")
77 launcher := filepath.Join(root, "reasonix-launcher.exe")
78 tests := []struct {
79 name string
80 icon string
81 want bool
82 }{
83 {name: "versioned", icon: filepath.Join(root, "versions", "v1.19.3", "reasonix-desktop.exe") + ",0", want: true},
84 {name: "quoted versioned", icon: `"` + filepath.Join(root, "versions", "v1.19.3", "reasonix-desktop.exe") + `", 0`, want: true},
85 {name: "stable launcher", icon: launcher + ",0", want: false},
86 {name: "custom icon", icon: filepath.Join(root, "custom.ico") + ",0", want: false},
87 {name: "other install", icon: filepath.Join(`D:\Apps`, "Reasonix", "versions", "v1.19.3", "reasonix-desktop.exe") + ",0", want: false},
88 {name: "empty", icon: "", want: false},
89 }
90 for _, tt := range tests {
91 t.Run(tt.name, func(t *testing.T) {
92 if got := reasonixWindowsStaleIcon(tt.icon, launcher); got != tt.want {
93 t.Fatalf("reasonixWindowsStaleIcon(%q, %q) = %v, want %v", tt.icon, launcher, got, tt.want)
94 }
95 })
96 }
97 }
98
99 func TestReasonixWindowsVersionedTarget(t *testing.T) {
100 root := filepath.Join(`C:\Program Files`, "Reasonix")
101 launcher := filepath.Join(root, "reasonix-launcher.exe")
102 tests := []struct {
103 name string
104 target string
105 want bool
106 }{
107 {name: "versioned desktop", target: filepath.Join(root, "versions", "v1.19.3", "reasonix-desktop.exe"), want: true},
108 {name: "case-insensitive", target: filepath.Join(root, "Versions", "V1.19.3", "Reasonix-Desktop.exe"), want: true},
109 {name: "launcher", target: launcher, want: false},
110 {name: "launcher alias", target: filepath.Join(root, "Reasonix.exe"), want: false},
111 {name: "flat desktop", target: filepath.Join(root, "reasonix-desktop.exe"), want: false},
112 {name: "deeper versioned path", target: filepath.Join(root, "versions", "v1.19.3", "sub", "reasonix-desktop.exe"), want: false},
113 {name: "wrong binary in versions", target: filepath.Join(root, "versions", "v1.19.3", "reasonix-cli.exe"), want: false},
114 {name: "other install", target: filepath.Join(`D:\Apps`, "Reasonix", "versions", "v1.19.3", "reasonix-desktop.exe"), want: false},
115 {name: "empty", target: "", want: false},
116 }
117 for _, tt := range tests {
118 t.Run(tt.name, func(t *testing.T) {
119 if got := reasonixWindowsVersionedTarget(tt.target, launcher); got != tt.want {
120 t.Fatalf("reasonixWindowsVersionedTarget(%q, %q) = %v, want %v", tt.target, launcher, got, tt.want)
121 }
122 })
123 }
124 }
125
126 func TestRepairWindowsShortcutPlan(t *testing.T) {
127 root := filepath.Join(`C:\Program Files`, "Reasonix")
128 launcher := filepath.Join(root, "reasonix-launcher.exe")
129 versioned := filepath.Join(root, "versions", "v1.19.3", "reasonix-desktop.exe")
130 tests := []struct {
131 name string
132 target string
133 icon string
134 wantRepoint bool
135 wantFixIcon bool
136 }{
137 {name: "versioned target + versioned icon", target: versioned, icon: versioned + ",0", wantRepoint: true, wantFixIcon: true},
138 {name: "versioned target + clean icon", target: versioned, icon: launcher + ",0", wantRepoint: true, wantFixIcon: false},
139 {name: "stable target + versioned icon", target: launcher, icon: versioned + ",0", wantRepoint: false, wantFixIcon: true},
140 {name: "stable target + clean icon", target: launcher, icon: launcher + ",0", wantRepoint: false, wantFixIcon: false},
141 {name: "custom target + custom icon", target: filepath.Join(root, "custom.ico"), icon: filepath.Join(root, "custom.ico") + ",0", wantRepoint: false, wantFixIcon: false},
142 }
143 for _, tt := range tests {
144 t.Run(tt.name, func(t *testing.T) {
145 repoint, fixIcon := repairWindowsShortcutPlan(tt.target, tt.icon, launcher)
146 if repoint != tt.wantRepoint || fixIcon != tt.wantFixIcon {
147 t.Fatalf("repairWindowsShortcutPlan(%q, %q) = (%v, %v), want (%v, %v)", tt.target, tt.icon, repoint, fixIcon, tt.wantRepoint, tt.wantFixIcon)
148 }
149 })
150 }
151 }
152
152 lines GO