package main import ( "reflect" "strings" "testing" "github.com/spf13/cobra" intdevice "netdome.biz/paul/qmk-rgb/internal/device" "netdome.biz/paul/qmk-rgb/internal/via" ) func TestLightingEnabledRequiresActiveEffectAndBrightness(t *testing.T) { cases := []struct { name string mode uint8 brightness uint8 want bool }{ {"active", 1, 160, true}, {"zero brightness", 1, 0, false}, {"disabled effect", 0, 160, false}, {"both zero", 0, 0, false}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { if got := lightingEnabled(tc.mode, tc.brightness); got != tc.want { t.Errorf("lightingEnabled(%d, %d) = %t, want %t", tc.mode, tc.brightness, got, tc.want) } }) } } // stubOneImpact80 puts one keyboard in front of the root command's validation, // which now resolves the target before a subcommand runs. func stubOneImpact80(t *testing.T) { t.Helper() stubDiscovery(t, []intdevice.Device{{Index: 1, Path: "hid-device-0", VendorID: 0x36B0, ProductID: 0x309F}}) } func TestDeviceFlagIsInheritedByCommands(t *testing.T) { stubOneImpact80(t) ran := false cmd := newRootCommand() cmd.AddCommand(&cobra.Command{ Use: "probe", Run: func(*cobra.Command, []string) { ran = true }, }) cmd.SetArgs([]string{"--device", "1", "probe"}) if err := cmd.Execute(); err != nil { t.Fatalf("Execute() error = %v", err) } if !ran { t.Fatal("child command did not run") } if targetDevice != "1" { t.Errorf("targetDevice = %q, want %q", targetDevice, "1") } } func TestResolveChannelsDefaultsToEveryDetectedChannel(t *testing.T) { proto := &verifyingProtocol{} got, err := resolveChannels(proto, targetDeviceData{}) if err != nil { t.Fatalf("resolveChannels() unexpected error: %v", err) } want := []via.Channel{via.ChannelRgblight, via.ChannelRgbMatrix, via.ChannelAudio} if !reflect.DeepEqual(got, want) { t.Errorf("resolveChannels() = %v, want %v", got, want) } } func TestResolveChannelsRejectsAChannelTheKeyboardDoesNotHave(t *testing.T) { proto := &verifyingProtocol{channels: []via.Channel{via.ChannelRgblight}} target := targetDeviceData{Requested: []via.Channel{via.ChannelAudio}} if _, err := resolveChannels(proto, target); err == nil { t.Fatal("resolveChannels() expected an error, want the missing channel reported") } } func TestResolveChannelsRejectsAShadowedDisplayName(t *testing.T) { proto := &verifyingProtocol{channels: []via.Channel{via.ChannelBacklight, via.ChannelRgbMatrix}} target := targetDeviceData{Display: map[uint16]string{3: "backlight"}} if _, err := resolveChannels(proto, target); err == nil { t.Fatal("resolveChannels() expected an error, want the shadowed name reported") } } func TestResolveChannelsReportsWhenNoChannelIsPresent(t *testing.T) { proto := &verifyingProtocol{channels: []via.Channel{}} if _, err := resolveChannels(proto, targetDeviceData{}); err == nil { t.Fatal("resolveChannels() expected an error when the keyboard has no channels") } } func TestZoneFlagIsInheritedByCommands(t *testing.T) { stubOneImpact80(t) ran := false cmd := newRootCommand() cmd.AddCommand(&cobra.Command{ Use: "probe", Run: func(*cobra.Command, []string) { ran = true }, }) cmd.SetArgs([]string{"--zone", "backlight", "probe"}) if err := cmd.Execute(); err != nil { t.Fatalf("Execute() error = %v", err) } if !ran { t.Fatal("child command did not run") } if targetZone != "backlight" { t.Errorf("targetZone = %q, want %q", targetZone, "backlight") } } // Precedence, documented because two errors can apply at once: a board that // cannot be selected is reported first, since a zone name is resolved against // the board's own names. func TestNoKeyboardIsReportedBeforeAnUnknownZone(t *testing.T) { stubDiscovery(t, []intdevice.Device{}) originalZone := targetZone t.Cleanup(func() { targetZone = originalZone }) targetZone = "matx" _, _, _, err := openTarget() if err == nil { t.Fatal("openTarget() expected an error, got nil") } if !strings.Contains(err.Error(), "no QMK keyboard found") { t.Errorf("openTarget() error = %v, want the missing keyboard reported", err) } }