| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- package main
- import (
- "bytes"
- "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")
- }
- }
- // The zone is a positional argument, so it is spelled only where a command reads
- // one. A flag the root carries is a flag every help lists, which told `keyboard
- // info` about a channel it cannot address and then ignored it.
- func TestNoCommandCarriesAZoneFlag(t *testing.T) {
- root := newRootCommand()
- registerCommands(root)
- var found []string
- var walk func(*cobra.Command)
- walk = func(cmd *cobra.Command) {
- for _, name := range []string{"zone", "all"} {
- if cmd.Flags().Lookup(name) != nil || cmd.PersistentFlags().Lookup(name) != nil {
- found = append(found, cmd.CommandPath()+" --"+name)
- }
- }
- for _, sub := range cmd.Commands() {
- walk(sub)
- }
- }
- walk(root)
- if len(found) > 0 {
- t.Errorf("zone flags still registered: %v; the zone is a positional argument", found)
- }
- }
- // A command that names no channel must not accept one, and one that does must
- // show it in its usage line, which is where a positional argument is documented.
- func TestZoneIsSpelledOnlyWhereACommandReadsOne(t *testing.T) {
- usageOf := func(args ...string) string {
- var out bytes.Buffer
- cmd := newRootCommand()
- registerCommands(cmd)
- cmd.SetOut(&out)
- cmd.SetErr(&out)
- cmd.SetArgs(args)
- if err := cmd.Execute(); err != nil {
- t.Fatalf("%v --help returned error: %v", args, err)
- }
- return out.String()
- }
- for _, args := range [][]string{{"effect", "--help"}, {"brightness", "--help"}, {"load", "--help"}} {
- if !strings.Contains(usageOf(args...), "zone") {
- t.Errorf("%v --help does not show a zone argument", args)
- }
- }
- // list, delete and the keyboard commands take a name or nothing, and a zone
- // in their usage line would promise a channel they never read.
- for _, args := range [][]string{{"list", "--help"}, {"keyboard", "info", "--help"}} {
- if strings.Contains(usageOf(args...), "<zone>") {
- t.Errorf("%v --help shows a zone argument, want none", args)
- }
- }
- }
- // 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{})
- _, _, _, err := openTarget("matx")
- 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)
- }
- }
|