github.com/martinohmann/rfoutlet@v1.2.1-0.20220707195255-8a66aa411105/internal/command/commands_test.go (about)

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"testing"
     7  
     8  	"github.com/martinohmann/rfoutlet/internal/outlet"
     9  	"github.com/martinohmann/rfoutlet/internal/schedule"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  type fakeSender struct {
    15  	buf bytes.Buffer
    16  }
    17  
    18  func (s *fakeSender) Send(msg []byte) {
    19  	s.buf.Write(msg)
    20  }
    21  
    22  func TestStatusCommand(t *testing.T) {
    23  	ctx, r, _ := NewTestContext()
    24  
    25  	s := &fakeSender{}
    26  
    27  	r.RegisterGroups(&outlet.Group{ID: "foo"})
    28  
    29  	cmd := StatusCommand{}
    30  	cmd.SetSender(s)
    31  
    32  	broadcast, err := cmd.Execute(ctx)
    33  
    34  	require.NoError(t, err)
    35  	assert.False(t, broadcast)
    36  
    37  	assert.Equal(t, `[{"id":"foo","displayName":"","outlets":null}]`, s.buf.String())
    38  }
    39  
    40  func TestOutletCommand(t *testing.T) {
    41  	ctx, r, _ := NewTestContext()
    42  
    43  	o := &outlet.Outlet{ID: "foo"}
    44  
    45  	r.RegisterOutlets(o)
    46  
    47  	cmd := OutletCommand{"foo", "on"}
    48  
    49  	broadcast, err := cmd.Execute(ctx)
    50  
    51  	require.NoError(t, err)
    52  	assert.True(t, broadcast)
    53  	assert.Equal(t, outlet.StateOn, o.GetState())
    54  }
    55  
    56  func TestGroupCommand(t *testing.T) {
    57  	ctx, r, _ := NewTestContext()
    58  
    59  	o1 := &outlet.Outlet{ID: "foo", State: outlet.StateOn}
    60  	o2 := &outlet.Outlet{ID: "baz"}
    61  	o3 := &outlet.Outlet{
    62  		ID: "qux",
    63  		Schedule: schedule.NewWithIntervals([]schedule.Interval{
    64  			{
    65  				Enabled: true,
    66  			},
    67  		}),
    68  	}
    69  
    70  	r.RegisterGroups(&outlet.Group{
    71  		ID:      "bar",
    72  		Outlets: []*outlet.Outlet{o1, o2, o3},
    73  	})
    74  
    75  	cmd := GroupCommand{"bar", "toggle"}
    76  
    77  	broadcast, err := cmd.Execute(ctx)
    78  
    79  	require.NoError(t, err)
    80  	assert.True(t, broadcast)
    81  	assert.Equal(t, outlet.StateOff, o1.GetState())
    82  	assert.Equal(t, outlet.StateOn, o2.GetState())
    83  	assert.Equal(t, outlet.StateOff, o3.GetState())
    84  }
    85  
    86  func TestIntervalCommand(t *testing.T) {
    87  	ctx, r, _ := NewTestContext()
    88  
    89  	o := &outlet.Outlet{ID: "foo", Schedule: schedule.New()}
    90  
    91  	r.RegisterOutlets(o)
    92  
    93  	cmd := IntervalCommand{"foo", "create", schedule.Interval{ID: "bar"}}
    94  
    95  	broadcast, err := cmd.Execute(ctx)
    96  
    97  	require.NoError(t, err)
    98  	assert.True(t, broadcast)
    99  
   100  	cmd = IntervalCommand{"foo", "create", schedule.Interval{ID: "bar"}}
   101  
   102  	broadcast, err = cmd.Execute(ctx)
   103  
   104  	require.Error(t, err)
   105  	assert.False(t, broadcast)
   106  
   107  	cmd = IntervalCommand{"foo", "update", schedule.Interval{ID: "bar"}}
   108  
   109  	broadcast, err = cmd.Execute(ctx)
   110  
   111  	require.NoError(t, err)
   112  	assert.True(t, broadcast)
   113  
   114  	cmd = IntervalCommand{"foo", "delete", schedule.Interval{ID: "bar"}}
   115  
   116  	broadcast, err = cmd.Execute(ctx)
   117  
   118  	require.NoError(t, err)
   119  	assert.True(t, broadcast)
   120  }
   121  
   122  func TestStateCorrectionCommand(t *testing.T) {
   123  	tests := []struct {
   124  		name              string
   125  		outletState       outlet.State
   126  		desiredState      outlet.State
   127  		switchErr         error
   128  		expectedState     outlet.State
   129  		expectedBroadcast bool
   130  		expectedErr       error
   131  	}{
   132  		{
   133  			name:          "outlet is already in desired state",
   134  			outletState:   outlet.StateOn,
   135  			desiredState:  outlet.StateOn,
   136  			expectedState: outlet.StateOn,
   137  		},
   138  		{
   139  			name:              "outlet is not in desired state",
   140  			outletState:       outlet.StateOn,
   141  			desiredState:      outlet.StateOff,
   142  			expectedState:     outlet.StateOff,
   143  			expectedBroadcast: true,
   144  		},
   145  		{
   146  			name:              "outlet is not in desired state, switch error",
   147  			outletState:       outlet.StateOn,
   148  			desiredState:      outlet.StateOff,
   149  			switchErr:         errors.New("whoops"),
   150  			expectedState:     outlet.StateOn,
   151  			expectedBroadcast: false,
   152  			expectedErr:       errors.New("whoops"),
   153  		},
   154  	}
   155  
   156  	for _, test := range tests {
   157  		t.Run(test.name, func(t *testing.T) {
   158  			o := &outlet.Outlet{State: test.outletState}
   159  			cmd := StateCorrectionCommand{
   160  				Outlet:       o,
   161  				DesiredState: test.desiredState,
   162  			}
   163  
   164  			ctx, _, s := NewTestContext()
   165  			s.Err = test.switchErr
   166  
   167  			broadcast, err := cmd.Execute(ctx)
   168  
   169  			assert.Equal(t, test.expectedErr, err)
   170  			assert.Equal(t, test.expectedBroadcast, broadcast)
   171  			assert.Equal(t, test.expectedState, o.GetState())
   172  		})
   173  	}
   174  }