diff --git a/.gitignore b/.gitignore index c39d755..4bd78c5 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,6 @@ __pycache__/ .pytest_cache/ config.yaml bin/ -*.db \ No newline at end of file +*.db + +cover.html \ No newline at end of file diff --git a/src/cmd/serve.go b/src/cmd/serve.go index e0edcd7..e06cbd0 100644 --- a/src/cmd/serve.go +++ b/src/cmd/serve.go @@ -103,8 +103,7 @@ func serve(cmd *cobra.Command, args []string) { router.HandleFunc("/poo/latest", pooRecorder.HandleNotifyLatestPoo).Methods("GET") router.HandleFunc("/poo/record", pooRecorder.HandleRecordPoo).Methods("POST") - - router.HandleFunc("/homeassistant/publish", homeassistant.DefaultHandler.HandleHaMessage).Methods("POST") + router.HandleFunc("/homeassistant/publish", homeassistant.HandleHaMessage).Methods("POST") router.HandleFunc("/location/record", locationRecorder.HandleRecordLocation).Methods("POST") diff --git a/src/components/homeassistant/homeassistant.go b/src/components/homeassistant/homeassistant.go index a031dc7..4a68376 100644 --- a/src/components/homeassistant/homeassistant.go +++ b/src/components/homeassistant/homeassistant.go @@ -23,19 +23,7 @@ type actionTask struct { DueHour int `json:"due_hour"` } -type HaMessageHandler struct { - PooRecorderHandler func(message haMessage) - LocationRecorderHandler func(message haMessage) - TicktickHandler func(message haMessage) -} - -var DefaultHandler = HaMessageHandler{ - PooRecorderHandler: handlePooRecorderMsg, - LocationRecorderHandler: handleLocationRecorderMsg, - TicktickHandler: handleTicktickMsg, -} - -func (handler HaMessageHandler) HandleHaMessage(w http.ResponseWriter, r *http.Request) { +func HandleHaMessage(w http.ResponseWriter, r *http.Request) { var message haMessage decoder := json.NewDecoder(r.Body) decoder.DisallowUnknownFields() @@ -48,11 +36,14 @@ func (handler HaMessageHandler) HandleHaMessage(w http.ResponseWriter, r *http.R switch message.Target { case "poo_recorder": - handler.PooRecorderHandler(message) + handlePooRecorderMsg(message) case "location_recorder": - handler.LocationRecorderHandler(message) + handleLocationRecorderMsg(message) case "ticktick": - handler.TicktickHandler(message) + handleTicktickMsg(message) + default: + slog.Warn(fmt.Sprintln("HandleHaMessage Unknown target", message.Target)) + http.Error(w, "Unknown target", http.StatusBadRequest) } } @@ -91,7 +82,7 @@ func handleTicktickMsg(message haMessage) { } } -func handleGetLatestPoo() { +func handleGetLatestPoo() bool { client := &http.Client{ Timeout: time.Second * 1, } @@ -99,7 +90,10 @@ func handleGetLatestPoo() { _, err := client.Get("http://localhost:" + port + "/poo/latest") if err != nil { slog.Warn(fmt.Sprintln("handleGetLatestPoo Error sending request to poo recorder", err)) + return false } + + return true } func createActionTask(message haMessage) { diff --git a/src/components/homeassistant/homeassistant_test.go b/src/components/homeassistant/homeassistant_test.go index 459c56c..fcb3750 100644 --- a/src/components/homeassistant/homeassistant_test.go +++ b/src/components/homeassistant/homeassistant_test.go @@ -1,65 +1,46 @@ package homeassistant import ( - "fmt" - "math/rand/v2" + "bytes" + "log/slog" "net/http" "net/http/httptest" "strings" "testing" - "github.com/stretchr/testify/mock" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" ) -type MockedHaHandler struct { - mock.Mock +var ( + loggerText = new(bytes.Buffer) +) + +func LoggerSetupTeardown(t *testing.T) func() { + logger := slog.New(slog.NewTextHandler(loggerText, nil)) + defaultLogger := slog.Default() + slog.SetDefault(logger) + + return func() { + slog.SetDefault(defaultLogger) + loggerText.Reset() + } } -func (m *MockedHaHandler) handlePooRecorderMsg(message haMessage) { - m.Called(message) -} - -func (m *MockedHaHandler) handleLocationRecorderMsg(message haMessage) { - m.Called(message) -} - -func (m *MockedHaHandler) handleTicktickMsg(message haMessage) { - m.Called(message) -} - -func TestHandleHaMessagePooRecorder(t *testing.T) { +func TestHandlePooRecorderMsgGetLatest(t *testing.T) { + teardown := LoggerSetupTeardown(t) + defer teardown() requestBody := `{"target": "poo_recorder", "action": "get_latest", "content": ""}` req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(requestBody)) w := httptest.NewRecorder() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/poo/latest", r.URL.Path) + })) + defer server.Close() + port := strings.Split(server.URL, ":")[2] + viper.Set("port", port) - testObj := new(MockedHaHandler) - mockedHandler := HaMessageHandler{ - PooRecorderHandler: testObj.handlePooRecorderMsg, - LocationRecorderHandler: testObj.handleLocationRecorderMsg, - TicktickHandler: testObj.handleTicktickMsg, - } - testObj.On("handlePooRecorderMsg", haMessage{Target: "poo_recorder", Action: "get_latest"}).Return() - mockedHandler.HandleHaMessage(w, req) - testObj.AssertCalled(t, "handlePooRecorderMsg", haMessage{Target: "poo_recorder", Action: "get_latest"}) -} - -func TestHandleHaMessageLocationRecorder(t *testing.T) { - expectedLatitude := rand.Float64() * 359 - expectedLongitude := rand.Float64() * 359 - expectedAltitude := rand.Float64() * 10000 - requestBody := fmt.Sprintf(`{"target": "location_recorder", "action": "record", - "content": "{'Person': 'Tom', 'latitude': %f, 'longitude': %f, 'altitude': %f}"}`, expectedLatitude, expectedLongitude, expectedAltitude) - req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(requestBody)) - w := httptest.NewRecorder() - testobj := new(MockedHaHandler) - mockedHandler := HaMessageHandler{ - PooRecorderHandler: testobj.handlePooRecorderMsg, - LocationRecorderHandler: testobj.handleLocationRecorderMsg, - TicktickHandler: testobj.handleTicktickMsg, - } - testobj.On("handleLocationRecorderMsg", haMessage{Target: "location_recorder", Action: "record", - Content: fmt.Sprintf("{'Person': 'Tom', 'latitude': %f, 'longitude': %f, 'altitude': %f}", expectedLatitude, expectedLongitude, expectedAltitude)}).Return() - mockedHandler.HandleHaMessage(w, req) - testobj.AssertCalled(t, "handleLocationRecorderMsg", haMessage{Target: "location_recorder", Action: "record", - Content: fmt.Sprintf("{'Person': 'Tom', 'latitude': %f, 'longitude': %f, 'altitude': %f}", expectedLatitude, expectedLongitude, expectedAltitude)}) + HandleHaMessage(w, req) + assert.Equal(t, http.StatusOK, w.Code) + assert.Empty(t, loggerText.String()) }