package main import ( "strings" "testing" intdevice "netdome.biz/paul/qmk-rgb/internal/device" "netdome.biz/paul/qmk-rgb/internal/via" ) func TestResolveZoneNameAcceptsASubsystemName(t *testing.T) { got, err := resolveZoneName("rgb_matrix", map[uint16]string{2: "logo"}) if err != nil { t.Fatalf("resolveZoneName() error = %v", err) } if len(got) != 1 || got[0] != via.ChannelRgbMatrix { t.Errorf("resolveZoneName() = %v, want [3]", got) } } func TestResolveZoneNameAcceptsADisplayName(t *testing.T) { got, err := resolveZoneName("logo", map[uint16]string{2: "logo", 3: "backlight", 4: "side"}) if err != nil { t.Fatalf("resolveZoneName() error = %v", err) } if len(got) != 1 || got[0] != via.ChannelRgblight { t.Errorf("resolveZoneName() = %v, want [2]", got) } } func TestResolveZoneNameRejectsAnUnknownName(t *testing.T) { _, err := resolveZoneName("nope", map[uint16]string{2: "logo"}) if err == nil { t.Fatal("resolveZoneName() expected an error, got nil") } if !strings.Contains(err.Error(), "rgb_matrix") { t.Errorf("error = %q, want it to name an accepted form", err) } } // A board that supplies no display names keeps the subsystem vocabulary, so the // physical names that work on the Impact 80 do not work elsewhere. func TestResolveZoneNameIgnoresDisplayNamesForAnotherBoard(t *testing.T) { if _, err := resolveZoneName("logo", nil); err == nil { t.Fatal("resolveZoneName(\"logo\", nil) expected an error, got nil") } } // Two channels carrying the same display name are ambiguous, and the tool // reports that rather than picking one. Whether a display name shadows another // channel's subsystem name cannot be decided here, because presence is only // known after the probe; displayNameConflicts decides that. func TestResolveZoneNameReportsAnAmbiguousName(t *testing.T) { _, err := resolveZoneName("backlight", map[uint16]string{2: "logo", 3: "backlight", 4: "backlight"}) if err == nil { t.Fatal("resolveZoneName() expected an error for a name two channels answer to") } if !strings.Contains(err.Error(), "backlight") { t.Errorf("error = %q, want it to name the conflicting name", err) } } func TestDisplayNameConflictsRejectsAShadowedSubsystemName(t *testing.T) { // Channel 1 is present and its subsystem is "backlight", while the file // also calls channel 3 "backlight": two channels, one name. err := displayNameConflicts( map[uint16]string{3: "backlight"}, []via.Channel{via.ChannelBacklight, via.ChannelRgbMatrix}, ) if err == nil { t.Fatal("displayNameConflicts() expected an error, got nil") } if !strings.Contains(err.Error(), "backlight") { t.Errorf("error = %q, want it to name the conflicting name", err) } } func TestDisplayNameConflictsAllowsTheImpact80Naming(t *testing.T) { // The Impact 80 calls channel 3 "backlight" and has no channel 1, so // nothing shadows anything. err := displayNameConflicts( map[uint16]string{2: "logo", 3: "backlight", 4: "side"}, []via.Channel{via.ChannelRgblight, via.ChannelRgbMatrix, via.ChannelAudio}, ) if err != nil { t.Fatalf("displayNameConflicts() error = %v, want nil", err) } } func TestChannelNamePrefersTheDisplayName(t *testing.T) { display := map[uint16]string{2: "logo"} if got := channelName(via.ChannelRgblight, display); got != "logo" { t.Errorf("channelName(2) = %q, want %q", got, "logo") } if got := channelName(via.ChannelRgbMatrix, display); got != "rgb_matrix" { t.Errorf("channelName(3) = %q, want %q", got, "rgb_matrix") } } // The display names must come from the keyboard the command targets, not from // whichever one enumeration returned first. func TestPrepareTargetUsesTheSelectedKeyboard(t *testing.T) { devices := []intdevice.Device{ {VendorID: 0x6666, ProductID: 0x0001}, {VendorID: 0x36B0, ProductID: 0x309F, Name: "Wobkey Impact 80"}, } originalDiscover := discoverAll originalKeyboardFor := keyboardFor originalTarget := targetDevice originalZone := targetZone t.Cleanup(func() { discoverAll = originalDiscover keyboardFor = originalKeyboardFor targetDevice = originalTarget targetZone = originalZone }) discoverAll = func() ([]intdevice.Device, error) { return devices, nil } keyboardFor = func(vendorID, productID uint16) (intdevice.Keyboard, bool, error) { switch { case vendorID == 0x6666: return intdevice.Keyboard{Name: "Wobkey Rainy 75", Channels: map[uint16]string{2: "deck"}}, true, nil case vendorID == 0x36B0: return intdevice.Keyboard{Name: "Wobkey Impact 80", Channels: map[uint16]string{2: "logo"}}, true, nil } return intdevice.Keyboard{}, false, nil } targetDevice = "2" targetZone = "logo" got, err := prepareTarget() if err != nil { t.Fatalf("prepareTarget() error = %v", err) } if got.Display[2] != "logo" { t.Errorf("display names = %v, want the Impact 80's", got.Display) } }