package main import ( "strings" "testing" ) // The exact list an operator's machine produced: COM1 and COM3 each claimed by // two devices in the Windows port map, and no order to speak of. The dropdown // showed every duplicate, and rendered its own value as "COM3COM3" because two // entries with the same value both counted as selected. func TestTidySerialPortsDeduplicatesAndOrders(t *testing.T) { got := tidySerialPorts([]string{"COM1", "COM1", "COM3", "COM8", "COM9", "COM4", "COM3"}) want := []string{"COM1", "COM3", "COM4", "COM8", "COM9"} if strings.Join(got, ",") != strings.Join(want, ",") { t.Errorf("got %v, want %v", got, want) } } // COM10 after COM9, not between COM1 and COM2 — lexical order is how a port // gets overlooked on a machine with a dozen of them. func TestTidySerialPortsSortsNaturally(t *testing.T) { got := tidySerialPorts([]string{"COM10", "COM2", "COM1", "COM20", "COM3"}) want := []string{"COM1", "COM2", "COM3", "COM10", "COM20"} if strings.Join(got, ",") != strings.Join(want, ",") { t.Errorf("got %v, want %v", got, want) } } // Not every port is a COMn: a device path or a Unix name must survive, after // the numbered ones, in its own order. func TestTidySerialPortsKeepsOtherNames(t *testing.T) { got := tidySerialPorts([]string{"/dev/ttyUSB1", "COM3", "/dev/ttyUSB0", "COM1", "", " "}) want := []string{"COM1", "COM3", "/dev/ttyUSB0", "/dev/ttyUSB1"} if strings.Join(got, ",") != strings.Join(want, ",") { t.Errorf("got %v, want %v", got, want) } } // Case is not identity on Windows: "com3" and "COM3" are one port, and letting // both through would put the same duplicate back in the list. func TestTidySerialPortsIgnoresCase(t *testing.T) { if got := tidySerialPorts([]string{"COM3", "com3"}); len(got) != 1 || got[0] != "COM3" { t.Errorf("got %v, want [COM3]", got) } }