All checks were successful
CI / changes (push) Successful in 19s
CI / test (push) Successful in 24s
CI / build-ai-gateway (push) Successful in 1m6s
CI / build-ha-gateway (push) Successful in 1m3s
CI / build-discord-bot (push) Successful in 1m4s
CI / build-alexa-bridge (push) Successful in 1m15s
CI / build-tts-gateway (push) Successful in 1m5s
CI / build-tts-sidecar (push) Has been skipped
CI / build-tts-model (push) Has been skipped
- Implemented SetTemperature in ClimateService for setting an absolute target temperature. - Updated ClimateServiceClient and ClimateServiceServer interfaces to include SetTemperature. - Added corresponding handler and tests for SetTemperature in ClimateGRPC. - Modified ClimateApp to handle SetTemperature requests without clamping. - Updated climate.proto to define SetTemperatureRequest message. - Adjusted Dockerfiles to include alexa-bridge dependencies.
462 lines
17 KiB
Go
462 lines
17 KiB
Go
package haclient
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
hav1 "gitea.nik4nao.com/nik/home-services/gen/ha/v1"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
type fakeLightServiceClient struct {
|
|
turnOnFunc func(ctx context.Context, in *hav1.TurnOnRequest) (*hav1.LightResponse, error)
|
|
turnOffFunc func(ctx context.Context, in *hav1.TurnOffRequest) (*hav1.LightResponse, error)
|
|
toggleFunc func(ctx context.Context, in *hav1.ToggleRequest) (*hav1.LightResponse, error)
|
|
}
|
|
|
|
func (f *fakeLightServiceClient) TurnOn(ctx context.Context, in *hav1.TurnOnRequest, _ ...grpc.CallOption) (*hav1.LightResponse, error) {
|
|
if f.turnOnFunc == nil {
|
|
return &hav1.LightResponse{}, nil
|
|
}
|
|
return f.turnOnFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeLightServiceClient) TurnOff(ctx context.Context, in *hav1.TurnOffRequest, _ ...grpc.CallOption) (*hav1.LightResponse, error) {
|
|
if f.turnOffFunc == nil {
|
|
return &hav1.LightResponse{}, nil
|
|
}
|
|
return f.turnOffFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeLightServiceClient) Toggle(ctx context.Context, in *hav1.ToggleRequest, _ ...grpc.CallOption) (*hav1.LightResponse, error) {
|
|
if f.toggleFunc == nil {
|
|
return &hav1.LightResponse{}, nil
|
|
}
|
|
return f.toggleFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeLightServiceClient) ListLights(ctx context.Context, in *hav1.ListLightsRequest, _ ...grpc.CallOption) (*hav1.ListLightsResponse, error) {
|
|
return &hav1.ListLightsResponse{}, nil
|
|
}
|
|
|
|
type fakeSwitchServiceClient struct {
|
|
turnOnFunc func(ctx context.Context, in *hav1.SwitchRequest) (*hav1.SwitchResponse, error)
|
|
turnOffFunc func(ctx context.Context, in *hav1.SwitchRequest) (*hav1.SwitchResponse, error)
|
|
toggleFunc func(ctx context.Context, in *hav1.SwitchRequest) (*hav1.SwitchResponse, error)
|
|
}
|
|
|
|
func (f *fakeSwitchServiceClient) TurnOn(ctx context.Context, in *hav1.SwitchRequest, _ ...grpc.CallOption) (*hav1.SwitchResponse, error) {
|
|
if f.turnOnFunc == nil {
|
|
return &hav1.SwitchResponse{}, nil
|
|
}
|
|
return f.turnOnFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeSwitchServiceClient) TurnOff(ctx context.Context, in *hav1.SwitchRequest, _ ...grpc.CallOption) (*hav1.SwitchResponse, error) {
|
|
if f.turnOffFunc == nil {
|
|
return &hav1.SwitchResponse{}, nil
|
|
}
|
|
return f.turnOffFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeSwitchServiceClient) Toggle(ctx context.Context, in *hav1.SwitchRequest, _ ...grpc.CallOption) (*hav1.SwitchResponse, error) {
|
|
if f.toggleFunc == nil {
|
|
return &hav1.SwitchResponse{}, nil
|
|
}
|
|
return f.toggleFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeSwitchServiceClient) ListSwitches(ctx context.Context, in *hav1.ListSwitchesRequest, _ ...grpc.CallOption) (*hav1.ListSwitchesResponse, error) {
|
|
return &hav1.ListSwitchesResponse{}, nil
|
|
}
|
|
|
|
type fakeClimateServiceClient struct {
|
|
turnOnFunc func(ctx context.Context, in *hav1.ClimateRequest) (*hav1.ClimateResponse, error)
|
|
turnOffFunc func(ctx context.Context, in *hav1.ClimateRequest) (*hav1.ClimateResponse, error)
|
|
increaseTemperatureFunc func(ctx context.Context, in *hav1.ClimateRequest) (*hav1.ClimateResponse, error)
|
|
decreaseTemperatureFunc func(ctx context.Context, in *hav1.ClimateRequest) (*hav1.ClimateResponse, error)
|
|
setTemperatureFunc func(ctx context.Context, in *hav1.SetTemperatureRequest) (*hav1.ClimateResponse, error)
|
|
setHVACModeFunc func(ctx context.Context, in *hav1.SetHVACModeRequest) (*hav1.ClimateResponse, error)
|
|
}
|
|
|
|
func (f *fakeClimateServiceClient) TurnOn(ctx context.Context, in *hav1.ClimateRequest, _ ...grpc.CallOption) (*hav1.ClimateResponse, error) {
|
|
if f.turnOnFunc == nil {
|
|
return &hav1.ClimateResponse{}, nil
|
|
}
|
|
return f.turnOnFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeClimateServiceClient) TurnOff(ctx context.Context, in *hav1.ClimateRequest, _ ...grpc.CallOption) (*hav1.ClimateResponse, error) {
|
|
if f.turnOffFunc == nil {
|
|
return &hav1.ClimateResponse{}, nil
|
|
}
|
|
return f.turnOffFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeClimateServiceClient) IncreaseTemperature(ctx context.Context, in *hav1.ClimateRequest, _ ...grpc.CallOption) (*hav1.ClimateResponse, error) {
|
|
if f.increaseTemperatureFunc == nil {
|
|
return &hav1.ClimateResponse{}, nil
|
|
}
|
|
return f.increaseTemperatureFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeClimateServiceClient) DecreaseTemperature(ctx context.Context, in *hav1.ClimateRequest, _ ...grpc.CallOption) (*hav1.ClimateResponse, error) {
|
|
if f.decreaseTemperatureFunc == nil {
|
|
return &hav1.ClimateResponse{}, nil
|
|
}
|
|
return f.decreaseTemperatureFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeClimateServiceClient) SetTemperature(ctx context.Context, in *hav1.SetTemperatureRequest, _ ...grpc.CallOption) (*hav1.ClimateResponse, error) {
|
|
if f.setTemperatureFunc == nil {
|
|
return &hav1.ClimateResponse{}, nil
|
|
}
|
|
return f.setTemperatureFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeClimateServiceClient) SetHVACMode(ctx context.Context, in *hav1.SetHVACModeRequest, _ ...grpc.CallOption) (*hav1.ClimateResponse, error) {
|
|
if f.setHVACModeFunc == nil {
|
|
return &hav1.ClimateResponse{}, nil
|
|
}
|
|
return f.setHVACModeFunc(ctx, in)
|
|
}
|
|
|
|
func (f *fakeClimateServiceClient) ListClimates(ctx context.Context, in *hav1.ListClimatesRequest, _ ...grpc.CallOption) (*hav1.ListClimatesResponse, error) {
|
|
return &hav1.ListClimatesResponse{}, nil
|
|
}
|
|
|
|
func TestExecuteActionLight(t *testing.T) {
|
|
t.Run("turn_on forwards optional params", func(t *testing.T) {
|
|
var got *hav1.TurnOnRequest
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
turnOnFunc: func(ctx context.Context, in *hav1.TurnOnRequest) (*hav1.LightResponse, error) {
|
|
got = in
|
|
return &hav1.LightResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
err := c.ExecuteAction(context.Background(), "light.living_room", "turn_on", map[string]any{
|
|
"brightness_pct": "80",
|
|
"color_temp_kelvin": "2700",
|
|
"rgb_color": map[string]any{"r": "255", "g": "0", "b": "0"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetEntityId() != "light.living_room" {
|
|
t.Fatalf("EntityId = %q, want %q", got.GetEntityId(), "light.living_room")
|
|
}
|
|
if got.GetBrightnessPct() != 80 {
|
|
t.Fatalf("BrightnessPct = %v, want 80", got.GetBrightnessPct())
|
|
}
|
|
if got.GetColorTempKelvin() != 2700 {
|
|
t.Fatalf("ColorTempKelvin = %v, want 2700", got.GetColorTempKelvin())
|
|
}
|
|
if got.GetRgbColor().GetR() != 255 {
|
|
t.Fatalf("RgbColor.R = %v, want 255", got.GetRgbColor().GetR())
|
|
}
|
|
})
|
|
|
|
t.Run("turn_on with no params sets no optional fields", func(t *testing.T) {
|
|
var got *hav1.TurnOnRequest
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
turnOnFunc: func(ctx context.Context, in *hav1.TurnOnRequest) (*hav1.LightResponse, error) {
|
|
got = in
|
|
return &hav1.LightResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
if err := c.ExecuteAction(context.Background(), "light.living_room", "turn_on", nil); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.BrightnessPct != nil || got.ColorTempKelvin != nil || got.RgbColor != nil {
|
|
t.Fatalf("expected no optional fields set, got %#v", got)
|
|
}
|
|
})
|
|
|
|
t.Run("turn_off forwards transition", func(t *testing.T) {
|
|
var got *hav1.TurnOffRequest
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
turnOffFunc: func(ctx context.Context, in *hav1.TurnOffRequest) (*hav1.LightResponse, error) {
|
|
got = in
|
|
return &hav1.LightResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
if err := c.ExecuteAction(context.Background(), "light.living_room", "turn_off", map[string]any{"transition": "3"}); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetTransition() != 3 {
|
|
t.Fatalf("Transition = %v, want 3", got.GetTransition())
|
|
}
|
|
})
|
|
|
|
t.Run("toggle", func(t *testing.T) {
|
|
var got *hav1.ToggleRequest
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
toggleFunc: func(ctx context.Context, in *hav1.ToggleRequest) (*hav1.LightResponse, error) {
|
|
got = in
|
|
return &hav1.LightResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
if err := c.ExecuteAction(context.Background(), "light.living_room", "toggle", nil); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetEntityId() != "light.living_room" {
|
|
t.Fatalf("EntityId = %q, want %q", got.GetEntityId(), "light.living_room")
|
|
}
|
|
})
|
|
|
|
t.Run("set_brightness reuses TurnOn with only brightness set", func(t *testing.T) {
|
|
var got *hav1.TurnOnRequest
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
turnOnFunc: func(ctx context.Context, in *hav1.TurnOnRequest) (*hav1.LightResponse, error) {
|
|
got = in
|
|
return &hav1.LightResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
if err := c.ExecuteAction(context.Background(), "light.living_room", "set_brightness", map[string]any{"brightness_pct": "50"}); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetBrightnessPct() != 50 {
|
|
t.Fatalf("BrightnessPct = %v, want 50", got.GetBrightnessPct())
|
|
}
|
|
if got.ColorTempKelvin != nil || got.RgbColor != nil {
|
|
t.Fatalf("expected only brightness set, got %#v", got)
|
|
}
|
|
})
|
|
|
|
t.Run("set_brightness missing param errors without calling RPC", func(t *testing.T) {
|
|
called := false
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
turnOnFunc: func(ctx context.Context, in *hav1.TurnOnRequest) (*hav1.LightResponse, error) {
|
|
called = true
|
|
return &hav1.LightResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
err := c.ExecuteAction(context.Background(), "light.living_room", "set_brightness", nil)
|
|
if err == nil {
|
|
t.Fatal("ExecuteAction() error = nil, want error")
|
|
}
|
|
if called {
|
|
t.Fatal("TurnOn should not be called when the required param is missing")
|
|
}
|
|
})
|
|
|
|
t.Run("set_color_temp", func(t *testing.T) {
|
|
var got *hav1.TurnOnRequest
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
turnOnFunc: func(ctx context.Context, in *hav1.TurnOnRequest) (*hav1.LightResponse, error) {
|
|
got = in
|
|
return &hav1.LightResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
if err := c.ExecuteAction(context.Background(), "light.living_room", "set_color_temp", map[string]any{"color_temp_kelvin": "4000"}); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetColorTempKelvin() != 4000 {
|
|
t.Fatalf("ColorTempKelvin = %v, want 4000", got.GetColorTempKelvin())
|
|
}
|
|
})
|
|
|
|
t.Run("set_color", func(t *testing.T) {
|
|
var got *hav1.TurnOnRequest
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
turnOnFunc: func(ctx context.Context, in *hav1.TurnOnRequest) (*hav1.LightResponse, error) {
|
|
got = in
|
|
return &hav1.LightResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
err := c.ExecuteAction(context.Background(), "light.living_room", "set_color", map[string]any{
|
|
"rgb_color": map[string]any{"r": "10", "g": "20", "b": "30"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetRgbColor().GetR() != 10 || got.GetRgbColor().GetG() != 20 || got.GetRgbColor().GetB() != 30 {
|
|
t.Fatalf("RgbColor = %#v, want (10,20,30)", got.GetRgbColor())
|
|
}
|
|
})
|
|
|
|
t.Run("unsupported action", func(t *testing.T) {
|
|
c := &Client{lightClient: &fakeLightServiceClient{}}
|
|
if err := c.ExecuteAction(context.Background(), "light.living_room", "explode", nil); err == nil {
|
|
t.Fatal("ExecuteAction() error = nil, want error")
|
|
}
|
|
})
|
|
|
|
t.Run("propagates RPC error", func(t *testing.T) {
|
|
wantErr := errors.New("boom")
|
|
c := &Client{lightClient: &fakeLightServiceClient{
|
|
turnOnFunc: func(ctx context.Context, in *hav1.TurnOnRequest) (*hav1.LightResponse, error) {
|
|
return nil, wantErr
|
|
},
|
|
}}
|
|
err := c.ExecuteAction(context.Background(), "light.living_room", "turn_on", nil)
|
|
if !errors.Is(err, wantErr) {
|
|
t.Fatalf("ExecuteAction() error = %v, want %v", err, wantErr)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExecuteActionSwitch(t *testing.T) {
|
|
tests := []struct {
|
|
action string
|
|
}{{"turn_on"}, {"turn_off"}, {"toggle"}}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.action, func(t *testing.T) {
|
|
var gotOn, gotOff, gotToggle *hav1.SwitchRequest
|
|
c := &Client{switchClient: &fakeSwitchServiceClient{
|
|
turnOnFunc: func(ctx context.Context, in *hav1.SwitchRequest) (*hav1.SwitchResponse, error) {
|
|
gotOn = in
|
|
return &hav1.SwitchResponse{}, nil
|
|
},
|
|
turnOffFunc: func(ctx context.Context, in *hav1.SwitchRequest) (*hav1.SwitchResponse, error) {
|
|
gotOff = in
|
|
return &hav1.SwitchResponse{}, nil
|
|
},
|
|
toggleFunc: func(ctx context.Context, in *hav1.SwitchRequest) (*hav1.SwitchResponse, error) {
|
|
gotToggle = in
|
|
return &hav1.SwitchResponse{}, nil
|
|
},
|
|
}}
|
|
|
|
if err := c.ExecuteAction(context.Background(), "switch.fan", tt.action, nil); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
for _, got := range []*hav1.SwitchRequest{gotOn, gotOff, gotToggle} {
|
|
if got != nil && got.GetEntityId() != "switch.fan" {
|
|
t.Fatalf("EntityId = %q, want %q", got.GetEntityId(), "switch.fan")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
t.Run("unsupported action", func(t *testing.T) {
|
|
c := &Client{switchClient: &fakeSwitchServiceClient{}}
|
|
if err := c.ExecuteAction(context.Background(), "switch.fan", "explode", nil); err == nil {
|
|
t.Fatal("ExecuteAction() error = nil, want error")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExecuteActionClimate(t *testing.T) {
|
|
t.Run("set_hvac_mode", func(t *testing.T) {
|
|
var got *hav1.SetHVACModeRequest
|
|
c := &Client{climateClient: &fakeClimateServiceClient{
|
|
setHVACModeFunc: func(ctx context.Context, in *hav1.SetHVACModeRequest) (*hav1.ClimateResponse, error) {
|
|
got = in
|
|
return &hav1.ClimateResponse{}, nil
|
|
},
|
|
}}
|
|
if err := c.ExecuteAction(context.Background(), "climate.air_conditioner", "set_hvac_mode", map[string]any{"hvac_mode": "cool"}); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetHvacMode() != "cool" {
|
|
t.Fatalf("HvacMode = %q, want %q", got.GetHvacMode(), "cool")
|
|
}
|
|
})
|
|
|
|
t.Run("set_hvac_mode missing param errors", func(t *testing.T) {
|
|
c := &Client{climateClient: &fakeClimateServiceClient{}}
|
|
if err := c.ExecuteAction(context.Background(), "climate.air_conditioner", "set_hvac_mode", nil); err == nil {
|
|
t.Fatal("ExecuteAction() error = nil, want error")
|
|
}
|
|
})
|
|
|
|
t.Run("increase_temperature", func(t *testing.T) {
|
|
var got *hav1.ClimateRequest
|
|
c := &Client{climateClient: &fakeClimateServiceClient{
|
|
increaseTemperatureFunc: func(ctx context.Context, in *hav1.ClimateRequest) (*hav1.ClimateResponse, error) {
|
|
got = in
|
|
return &hav1.ClimateResponse{}, nil
|
|
},
|
|
}}
|
|
if err := c.ExecuteAction(context.Background(), "climate.air_conditioner", "increase_temperature", nil); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetEntityId() != "climate.air_conditioner" {
|
|
t.Fatalf("EntityId = %q, want %q", got.GetEntityId(), "climate.air_conditioner")
|
|
}
|
|
})
|
|
|
|
t.Run("decrease_temperature", func(t *testing.T) {
|
|
called := false
|
|
c := &Client{climateClient: &fakeClimateServiceClient{
|
|
decreaseTemperatureFunc: func(ctx context.Context, in *hav1.ClimateRequest) (*hav1.ClimateResponse, error) {
|
|
called = true
|
|
return &hav1.ClimateResponse{}, nil
|
|
},
|
|
}}
|
|
if err := c.ExecuteAction(context.Background(), "climate.air_conditioner", "decrease_temperature", nil); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if !called {
|
|
t.Fatal("DecreaseTemperature was not called")
|
|
}
|
|
})
|
|
|
|
t.Run("set_temperature forwards absolute target", func(t *testing.T) {
|
|
var got *hav1.SetTemperatureRequest
|
|
c := &Client{climateClient: &fakeClimateServiceClient{
|
|
setTemperatureFunc: func(ctx context.Context, in *hav1.SetTemperatureRequest) (*hav1.ClimateResponse, error) {
|
|
got = in
|
|
return &hav1.ClimateResponse{}, nil
|
|
},
|
|
}}
|
|
if err := c.ExecuteAction(context.Background(), "climate.air_conditioner", "set_temperature", map[string]any{"target_temperature": "23.5"}); err != nil {
|
|
t.Fatalf("ExecuteAction() error = %v", err)
|
|
}
|
|
if got.GetEntityId() != "climate.air_conditioner" || got.GetTargetTemperature() != 23.5 {
|
|
t.Fatalf("SetTemperatureRequest = %#v, want entity=climate.air_conditioner target=23.5", got)
|
|
}
|
|
})
|
|
|
|
t.Run("set_temperature missing param errors without calling RPC", func(t *testing.T) {
|
|
called := false
|
|
c := &Client{climateClient: &fakeClimateServiceClient{
|
|
setTemperatureFunc: func(ctx context.Context, in *hav1.SetTemperatureRequest) (*hav1.ClimateResponse, error) {
|
|
called = true
|
|
return &hav1.ClimateResponse{}, nil
|
|
},
|
|
}}
|
|
err := c.ExecuteAction(context.Background(), "climate.air_conditioner", "set_temperature", nil)
|
|
if err == nil {
|
|
t.Fatal("ExecuteAction() error = nil, want error")
|
|
}
|
|
if called {
|
|
t.Fatal("SetTemperature should not be called when the required param is missing")
|
|
}
|
|
})
|
|
|
|
t.Run("unsupported action", func(t *testing.T) {
|
|
c := &Client{climateClient: &fakeClimateServiceClient{}}
|
|
if err := c.ExecuteAction(context.Background(), "climate.air_conditioner", "explode", nil); err == nil {
|
|
t.Fatal("ExecuteAction() error = nil, want error")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExecuteActionDomainDispatch(t *testing.T) {
|
|
t.Run("unsupported domain", func(t *testing.T) {
|
|
c := &Client{}
|
|
if err := c.ExecuteAction(context.Background(), "sensor.temp", "turn_on", nil); err == nil {
|
|
t.Fatal("ExecuteAction() error = nil, want error")
|
|
}
|
|
})
|
|
|
|
t.Run("entity id with no domain prefix", func(t *testing.T) {
|
|
c := &Client{}
|
|
if err := c.ExecuteAction(context.Background(), "no-domain-here", "turn_on", nil); err == nil {
|
|
t.Fatal("ExecuteAction() error = nil, want error")
|
|
}
|
|
})
|
|
}
|