Skip to content

Commit fdd1543

Browse files
authored
Add tests for menu sorting and rebuilding logic in tray manager (#9)
- Introduced unit tests for sorting server names and quarantine server names to ensure correct alphanumeric order. - Added tests for menu rebuild logic to verify detection of new servers and proper sorting during updates. - Enhanced existing menu management functions to support sorting and rebuilding based on new server data.
1 parent 91c98cb commit fdd1543

2 files changed

Lines changed: 355 additions & 37 deletions

File tree

internal/tray/managers.go

Lines changed: 100 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package tray
55
import (
66
"context"
77
"fmt"
8+
"sort"
89
"strings"
910
"sync"
1011
"time"
@@ -277,48 +278,83 @@ func (m *MenuManager) UpdateUpstreamServersMenu(servers []map[string]interface{}
277278

278279
// --- Create a map for efficient lookup of current servers ---
279280
currentServerMap := make(map[string]map[string]interface{})
281+
var currentServerNames []string
280282
for _, server := range servers {
281283
if name, ok := server["name"].(string); ok {
282284
currentServerMap[name] = server
285+
currentServerNames = append(currentServerNames, name)
283286
}
284287
}
288+
sort.Strings(currentServerNames)
285289

286-
// --- Hide or Update Existing Menu Items ---
287-
for serverName, menuItem := range m.serverMenuItems {
288-
if serverData, exists := currentServerMap[serverName]; exists {
289-
// Server exists, update its display and ensure it's visible
290-
status, tooltip := m.getServerStatusDisplay(serverData)
291-
menuItem.SetTitle(status)
292-
menuItem.SetTooltip(tooltip)
293-
m.updateServerActionMenus(serverName, serverData) // Update sub-menu items too
294-
menuItem.Show()
295-
} else {
296-
// Server was removed from config, hide it
297-
m.logger.Info("Hiding menu item for removed server", zap.String("server", serverName))
290+
// --- Check if we need to rebuild the menu (new servers added) ---
291+
var newServerNames []string
292+
for serverName := range currentServerMap {
293+
if _, exists := m.serverMenuItems[serverName]; !exists {
294+
newServerNames = append(newServerNames, serverName)
295+
}
296+
}
297+
298+
if len(newServerNames) > 0 {
299+
// New servers detected - rebuild entire menu in sorted order
300+
m.logger.Info("Rebuilding upstream servers menu in sorted order", zap.Int("new_servers", len(newServerNames)))
301+
302+
// Hide all existing menu items
303+
for serverName, menuItem := range m.serverMenuItems {
298304
menuItem.Hide()
299-
// Also hide its sub-menu items if they exist
305+
// Also hide sub-menu items
300306
if actionItem, ok := m.serverActionItems[serverName]; ok {
301307
actionItem.Hide()
302308
}
303309
if quarantineActionItem, ok := m.serverQuarantineItems[serverName]; ok {
304310
quarantineActionItem.Hide()
305311
}
306312
}
307-
}
308313

309-
// --- Create Menu Items for New Servers ---
310-
for serverName, serverData := range currentServerMap {
311-
if _, exists := m.serverMenuItems[serverName]; exists {
312-
continue
314+
// Clear the tracking maps
315+
m.serverMenuItems = make(map[string]*systray.MenuItem)
316+
m.serverActionItems = make(map[string]*systray.MenuItem)
317+
m.serverQuarantineItems = make(map[string]*systray.MenuItem)
318+
319+
// Create all servers in sorted order
320+
for _, serverName := range currentServerNames {
321+
serverData := currentServerMap[serverName]
322+
m.logger.Info("Creating menu item for server", zap.String("server", serverName))
323+
status, tooltip := m.getServerStatusDisplay(serverData)
324+
serverMenuItem := m.upstreamServersMenu.AddSubMenuItem(status, tooltip)
325+
m.serverMenuItems[serverName] = serverMenuItem
326+
327+
// Create its action submenus
328+
m.createServerActionSubmenus(serverMenuItem, serverData)
329+
}
330+
} else {
331+
// No new servers - just update existing items
332+
for _, serverName := range currentServerNames {
333+
if menuItem, exists := m.serverMenuItems[serverName]; exists {
334+
serverData := currentServerMap[serverName]
335+
// Server exists, update its display and ensure it's visible
336+
status, tooltip := m.getServerStatusDisplay(serverData)
337+
menuItem.SetTitle(status)
338+
menuItem.SetTooltip(tooltip)
339+
m.updateServerActionMenus(serverName, serverData) // Update sub-menu items too
340+
menuItem.Show()
341+
}
313342
}
314-
// This is a new server, create its menu item
315-
m.logger.Info("Creating menu item for new server", zap.String("server", serverName))
316-
status, tooltip := m.getServerStatusDisplay(serverData)
317-
serverMenuItem := m.upstreamServersMenu.AddSubMenuItem(status, tooltip)
318-
m.serverMenuItems[serverName] = serverMenuItem
319343

320-
// Create its action submenus
321-
m.createServerActionSubmenus(serverMenuItem, serverData)
344+
// Hide servers that are no longer in the config
345+
for serverName, menuItem := range m.serverMenuItems {
346+
if _, exists := currentServerMap[serverName]; !exists {
347+
m.logger.Info("Hiding menu item for removed server", zap.String("server", serverName))
348+
menuItem.Hide()
349+
// Also hide its sub-menu items if they exist
350+
if actionItem, ok := m.serverActionItems[serverName]; ok {
351+
actionItem.Hide()
352+
}
353+
if quarantineActionItem, ok := m.serverQuarantineItems[serverName]; ok {
354+
quarantineActionItem.Hide()
355+
}
356+
}
357+
}
322358
}
323359
}
324360

@@ -358,29 +394,40 @@ func (m *MenuManager) UpdateQuarantineMenu(quarantinedServers []map[string]inter
358394

359395
// --- Create a map for efficient lookup of current quarantined servers ---
360396
currentQuarantineMap := make(map[string]bool)
397+
var currentQuarantineNames []string
361398
for _, server := range quarantinedServers {
362399
if name, ok := server["name"].(string); ok {
363400
currentQuarantineMap[name] = true
401+
currentQuarantineNames = append(currentQuarantineNames, name)
364402
} else {
365403
m.logger.Warn("Quarantined server missing name field", zap.Any("server", server))
366404
}
367405
}
406+
sort.Strings(currentQuarantineNames)
368407

369-
// --- Hide or Show Existing Menu Items ---
370-
for serverName, menuItem := range m.quarantineMenuItems {
371-
if _, exists := currentQuarantineMap[serverName]; exists {
372-
// Server is still quarantined, ensure it's visible
373-
menuItem.Show()
374-
} else {
375-
// Server is no longer quarantined, hide it
376-
menuItem.Hide()
408+
// --- Check if we need to rebuild the quarantine menu (new servers added) ---
409+
var newQuarantineNames []string
410+
for serverName := range currentQuarantineMap {
411+
if _, exists := m.quarantineMenuItems[serverName]; !exists {
412+
newQuarantineNames = append(newQuarantineNames, serverName)
377413
}
378414
}
379415

380-
// --- Create Menu Items for Newly Quarantined Servers ---
381-
for serverName := range currentQuarantineMap {
382-
if _, exists := m.quarantineMenuItems[serverName]; !exists {
383-
// This is a newly quarantined server, create its menu item
416+
if len(newQuarantineNames) > 0 {
417+
// New quarantined servers detected - rebuild entire menu in sorted order
418+
m.logger.Info("Rebuilding quarantine menu in sorted order", zap.Int("new_quarantined", len(newQuarantineNames)))
419+
420+
// Hide all existing quarantine menu items
421+
for _, menuItem := range m.quarantineMenuItems {
422+
menuItem.Hide()
423+
}
424+
425+
// Clear the tracking map
426+
m.quarantineMenuItems = make(map[string]*systray.MenuItem)
427+
428+
// Create all quarantined servers in sorted order
429+
for _, serverName := range currentQuarantineNames {
430+
// This is a quarantined server, create its menu item
384431
if m.quarantineMenu == nil {
385432
m.logger.Error("Cannot create quarantine menu item - quarantineMenu is nil!", zap.String("server", serverName))
386433
continue
@@ -408,6 +455,22 @@ func (m *MenuManager) UpdateQuarantineMenu(quarantinedServers []map[string]inter
408455
}
409456
}(serverName, quarantineMenuItem)
410457
}
458+
} else {
459+
// No new quarantined servers - just update existing items
460+
for _, serverName := range currentQuarantineNames {
461+
if menuItem, exists := m.quarantineMenuItems[serverName]; exists {
462+
// Server is still quarantined, ensure it's visible
463+
menuItem.Show()
464+
}
465+
}
466+
467+
// Hide servers that are no longer quarantined
468+
for serverName, menuItem := range m.quarantineMenuItems {
469+
if _, exists := currentQuarantineMap[serverName]; !exists {
470+
// Server is no longer quarantined, hide it
471+
menuItem.Hide()
472+
}
473+
}
411474
}
412475
}
413476

0 commit comments

Comments
 (0)