package main import ( "strings" "testing" intdevice "netdome.biz/paul/qmk-rgb/internal/device" ) func testDevices() []intdevice.Device { return []intdevice.Device{ {Index: 1, Path: "/dev/hidraw7", VendorID: 0x36b0, ProductID: 0x309f, Name: "Wobkey Impact 80"}, {Index: 2, Path: "/dev/hidraw9", VendorID: 0x1234, ProductID: 0x5678, Name: "Unknown QMK keyboard"}, } } func TestSelectDeviceByIndex(t *testing.T) { tests := []struct { selector string wantPath string }{ {"1", "/dev/hidraw7"}, {"2", "/dev/hidraw9"}, } for _, tt := range tests { dev, err := selectDevice(testDevices(), tt.selector) if err != nil { t.Errorf("selectDevice(%q) returned error: %v", tt.selector, err) continue } if dev.Path != tt.wantPath { t.Errorf("selectDevice(%q) = %q, want %q", tt.selector, dev.Path, tt.wantPath) } } } func TestSelectDeviceEmptySelectorRequiresSingle(t *testing.T) { single := testDevices()[:1] dev, err := selectDevice(single, "") if err != nil { t.Fatalf("selectDevice(single, \"\") returned error: %v", err) } if dev.Path != "/dev/hidraw7" { t.Errorf("selectDevice(single, \"\") = %q, want %q", dev.Path, "/dev/hidraw7") } } func TestSelectDeviceEmptySelectorRejectsMultiple(t *testing.T) { _, err := selectDevice(testDevices(), "") if err == nil { t.Fatal("selectDevice(multiple, \"\") expected error, got nil") } if !strings.Contains(err.Error(), "--device") { t.Errorf("selectDevice(multiple, \"\") error = %q, want it to mention --device", err) } if !strings.Contains(err.Error(), "/dev/hidraw7") || !strings.Contains(err.Error(), "/dev/hidraw9") { t.Errorf("selectDevice(multiple, \"\") error = %q, want it to list both device paths", err) } } func TestSelectDeviceEmptySelectorRejectsNone(t *testing.T) { _, err := selectDevice(nil, "") if err == nil { t.Fatal("selectDevice(nil, \"\") expected error, got nil") } if !strings.Contains(err.Error(), "no QMK keyboard") { t.Errorf("selectDevice(nil, \"\") error = %q, want it to report no QMK keyboard", err) } } func TestSelectDeviceOutOfRange(t *testing.T) { tests := []string{"0", "3", "-1"} for _, selector := range tests { _, err := selectDevice(testDevices(), selector) if err == nil { t.Errorf("selectDevice(%q) expected error, got nil", selector) } } } func TestSelectDeviceRejectsNonNumeric(t *testing.T) { tests := []string{"/dev/hidraw7", "abc", "1a", " ", "0x1"} for _, selector := range tests { _, err := selectDevice(testDevices(), selector) if err == nil { t.Errorf("selectDevice(%q) expected error, got nil", selector) } } } func TestSelectDeviceReportsMissingKeyboardBeforeBadSelector(t *testing.T) { _, err := selectDevice(nil, "1") if err == nil { t.Fatal("selectDevice(nil, \"1\") expected error, got nil") } if !strings.Contains(err.Error(), "no QMK keyboard") { t.Errorf("selectDevice(nil, \"1\") error = %q, want it to report no QMK keyboard", err) } } func TestSelectDeviceErrorListsDevicesOnSeparateLines(t *testing.T) { _, err := selectDevice(testDevices(), "9") if err == nil { t.Fatal("selectDevice(devices, \"9\") expected error, got nil") } if !strings.Contains(err.Error(), "\n 1 Wobkey Impact 80") { t.Errorf("selectDevice() error = %q, want the device list to start on its own indented line", err) } } func TestFormatDeviceList(t *testing.T) { got := formatDeviceList(testDevices()) for _, want := range []string{"1", "2", "Wobkey Impact 80", "Unknown QMK keyboard", "/dev/hidraw7", "/dev/hidraw9"} { if !strings.Contains(got, want) { t.Errorf("formatDeviceList() = %q, want it to contain %q", got, want) } } }