diff --git a/example/config.yaml b/example/config.yaml new file mode 100644 index 0000000..5c72f02 --- /dev/null +++ b/example/config.yaml @@ -0,0 +1,7 @@ +hass: + address: 192.168.0.204 + port: 8123 + zone: zone.home + +entities: + light_entity_id: light.office_desk_lamp diff --git a/example/example.go b/example/example.go index 8d3dc05..fa5dc74 100644 --- a/example/example.go +++ b/example/example.go @@ -1,4 +1,4 @@ -package main +package example import ( "encoding/json" @@ -15,7 +15,6 @@ func main() { HAAuthToken: os.Getenv("HA_AUTH_TOKEN"), HomeZoneEntityId: "zone.home", }) - if err != nil { log.Fatalln("Error connecting to HASS:", err) } @@ -51,7 +50,6 @@ func main() { app.RegisterEventListeners(zwaveEventListener) app.Start() - } func pantryLights(service *ga.Service, state ga.State, sensor ga.EntityData) { diff --git a/example/example_live_test.go b/example/example_live_test.go new file mode 100644 index 0000000..e88611b --- /dev/null +++ b/example/example_live_test.go @@ -0,0 +1,113 @@ +package example + +import ( + "log/slog" + "os" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "gopkg.in/yaml.v3" + ga "saml.dev/gome-assistant" +) + +type ( + MySuite struct { + suite.Suite + app *ga.App + config *Config + suiteCtx map[string]any + } + + Config struct { + Hass struct { + HAAuthToken string `yaml:"token"` + IpAddress string `yaml:"address"` + Port string `yaml:"port"` + HomeZoneEntityId string `yaml:"zone"` + } + Entities struct { + LightEntityId string `yaml:"light_entity_id"` + } + } +) + +func (s *MySuite) SetupSuite() { + s.suiteCtx = make(map[string]any) + + configFile, err := os.ReadFile("./config.yaml") + if err != nil { + slog.Error("Error reading config file", err) + } + s.config = &Config{} + // either env var or config file can be used to set HA auth. token + s.config.Hass.HAAuthToken = os.Getenv("HA_AUTH_TOKEN") + if err := yaml.Unmarshal(configFile, s.config); err != nil { + slog.Error("Error unmarshalling config file:", err) + } + + s.app, err = ga.NewApp(ga.NewAppRequest{ + HAAuthToken: s.config.Hass.HAAuthToken, + IpAddress: s.config.Hass.IpAddress, + HomeZoneEntityId: s.config.Hass.HomeZoneEntityId, + }) + if err != nil { + slog.Error("Failed to createw new app:", err) + s.T().FailNow() + } + + entityId := s.config.Entities.LightEntityId + if entityId != "" { + s.suiteCtx["entityCallbackInvoked"] = false + etl := ga.NewEntityListener().EntityIds(entityId).Call(s.entityCallback).Build() + s.app.RegisterEntityListeners(etl) + go s.app.Start() + } +} + +func (s *MySuite) TearDownSuite() { + if s.app != nil { + s.app.Cleanup() + s.app = nil + } +} + +// Basic test of light toggle service and entity listener +func (s *MySuite) TestLightService() { + entityId := s.config.Entities.LightEntityId + + if entityId != "" { + initState := getEntityState(s, entityId) + s.app.GetService().Light.Toggle(entityId) + + assert.EventuallyWithT(s.T(), func(c *assert.CollectT) { + newState := getEntityState(s, entityId) + assert.NotEqual(c, initState, newState) + assert.True(c, s.suiteCtx["entityCallbackInvoked"].(bool)) + }, 10*time.Second, 1*time.Second, "State of light entity did not change or callback was not invoked") + } else { + s.T().Skip("No light entity id provided") + } +} + +// Test if event has been captured after light entity state changed +func (s *MySuite) entityCallback(se *ga.Service, st ga.State, e ga.EntityData) { + slog.Info("Entity callback called.", "entity id:", e.TriggerEntityId, "from state:", e.FromState, "to state:", e.ToState) + s.suiteCtx["entityCallbackInvoked"] = true +} + +func getEntityState(s *MySuite, entityId string) string { + state, err := s.app.GetState().Get(entityId) + if err != nil { + slog.Error("Error getting entity state:", err) + s.T().FailNow() + } + slog.Info("State of entity:", "state", state.State) + return state.State +} + +// Run the test suite +func TestMySuite(t *testing.T) { + suite.Run(t, new(MySuite)) +} diff --git a/example/go.mod b/example/go.mod new file mode 100644 index 0000000..95813bf --- /dev/null +++ b/example/go.mod @@ -0,0 +1,23 @@ +module example + +go 1.21.0 + +require ( + github.com/stretchr/testify v1.8.4 + gopkg.in/yaml.v3 v3.0.1 + saml.dev/gome-assistant v0.2.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gobuffalo/envy v1.10.2 // indirect + github.com/gobuffalo/packd v1.0.2 // indirect + github.com/gobuffalo/packr v1.30.1 // indirect + github.com/golang-module/carbon v1.7.3 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/nathan-osman/go-sunrise v1.1.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + golang.org/x/mod v0.9.0 // indirect +)