From f6979868e5c45703f766410fa5f43b9e0bb3e4e2 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 19 Sep 2024 17:19:09 +0300 Subject: [PATCH] added at_session_handler tests --- internal/http/at_session_handler_test.go | 232 +++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 internal/http/at_session_handler_test.go diff --git a/internal/http/at_session_handler_test.go b/internal/http/at_session_handler_test.go new file mode 100644 index 0000000..c99cee7 --- /dev/null +++ b/internal/http/at_session_handler_test.go @@ -0,0 +1,232 @@ +package http + +import ( + "context" + "errors" + "io" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + + "git.defalsify.org/vise.git/engine" + "git.grassecon.net/urdt/ussd/internal/handlers" + "git.grassecon.net/urdt/ussd/internal/mocks/httpmocks" +) + +func TestNewATSessionHandler(t *testing.T) { + mockHandler := &httpmocks.MockRequestHandler{} + ash := NewATSessionHandler(mockHandler) + + if ash == nil { + t.Fatal("NewATSessionHandler returned nil") + } + + if ash.SessionHandler == nil { + t.Fatal("SessionHandler is nil") + } +} + +func TestATSessionHandler_ServeHTTP(t *testing.T) { + tests := []struct { + name string + setupMocks func(*httpmocks.MockRequestHandler, *httpmocks.MockRequestParser, *httpmocks.MockEngine) + formData url.Values + expectedStatus int + expectedBody string + }{ + { + name: "Successful request", + setupMocks: func(mh *httpmocks.MockRequestHandler, mrp *httpmocks.MockRequestParser, me *httpmocks.MockEngine) { + mrp.GetSessionIdFunc = func(rq any) (string, error) { + req := rq.(*http.Request) + return req.FormValue("phoneNumber"), nil + } + mrp.GetInputFunc = func(rq any) ([]byte, error) { + req := rq.(*http.Request) + text := req.FormValue("text") + parts := strings.Split(text, "*") + return []byte(parts[len(parts)-1]), nil + } + mh.ProcessFunc = func(rqs handlers.RequestSession) (handlers.RequestSession, error) { + rqs.Continue = true + rqs.Engine = me + return rqs, nil + } + mh.GetConfigFunc = func() engine.Config { return engine.Config{} } + mh.GetRequestParserFunc = func() handlers.RequestParser { return mrp } + mh.OutputFunc = func(rs handlers.RequestSession) (handlers.RequestSession, error) { return rs, nil } + mh.ResetFunc = func(rs handlers.RequestSession) (handlers.RequestSession, error) { return rs, nil } + me.WriteResultFunc = func(context.Context, io.Writer) (int, error) { return 0, nil } + }, + formData: url.Values{ + "phoneNumber": []string{"+1234567890"}, + "text": []string{"1*2*3"}, + }, + expectedStatus: http.StatusOK, + expectedBody: "CON ", + }, + { + name: "GetSessionId error", + setupMocks: func(mh *httpmocks.MockRequestHandler, mrp *httpmocks.MockRequestParser, me *httpmocks.MockEngine) { + mrp.GetSessionIdFunc = func(rq any) (string, error) { + return "", errors.New("no phone number found") + } + mh.GetConfigFunc = func() engine.Config { return engine.Config{} } + mh.GetRequestParserFunc = func() handlers.RequestParser { return mrp } + }, + formData: url.Values{ + "text": []string{"1*2*3"}, + }, + expectedStatus: http.StatusBadRequest, + expectedBody: "", + }, + { + name: "GetInput error", + setupMocks: func(mh *httpmocks.MockRequestHandler, mrp *httpmocks.MockRequestParser, me *httpmocks.MockEngine) { + mrp.GetSessionIdFunc = func(rq any) (string, error) { + req := rq.(*http.Request) + return req.FormValue("phoneNumber"), nil + } + mrp.GetInputFunc = func(rq any) ([]byte, error) { + return nil, errors.New("no input found") + } + mh.GetConfigFunc = func() engine.Config { return engine.Config{} } + mh.GetRequestParserFunc = func() handlers.RequestParser { return mrp } + }, + formData: url.Values{ + "phoneNumber": []string{"+1234567890"}, + }, + expectedStatus: http.StatusBadRequest, + expectedBody: "", + }, + { + name: "Process error", + setupMocks: func(mh *httpmocks.MockRequestHandler, mrp *httpmocks.MockRequestParser, me *httpmocks.MockEngine) { + mrp.GetSessionIdFunc = func(rq any) (string, error) { + req := rq.(*http.Request) + return req.FormValue("phoneNumber"), nil + } + mrp.GetInputFunc = func(rq any) ([]byte, error) { + req := rq.(*http.Request) + text := req.FormValue("text") + parts := strings.Split(text, "*") + return []byte(parts[len(parts)-1]), nil + } + mh.ProcessFunc = func(rqs handlers.RequestSession) (handlers.RequestSession, error) { + return rqs, handlers.ErrStorage + } + mh.GetConfigFunc = func() engine.Config { return engine.Config{} } + mh.GetRequestParserFunc = func() handlers.RequestParser { return mrp } + }, + formData: url.Values{ + "phoneNumber": []string{"+1234567890"}, + "text": []string{"1*2*3"}, + }, + expectedStatus: http.StatusInternalServerError, + expectedBody: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockHandler := &httpmocks.MockRequestHandler{} + mockRequestParser := &httpmocks.MockRequestParser{} + mockEngine := &httpmocks.MockEngine{} + tt.setupMocks(mockHandler, mockRequestParser, mockEngine) + + ash := NewATSessionHandler(mockHandler) + + req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(tt.formData.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + w := httptest.NewRecorder() + + ash.ServeHTTP(w, req) + + if w.Code != tt.expectedStatus { + t.Errorf("Expected status %d, got %d", tt.expectedStatus, w.Code) + } + + if tt.expectedBody != "" && w.Body.String() != tt.expectedBody { + t.Errorf("Expected body %q, got %q", tt.expectedBody, w.Body.String()) + } + }) + } +} + +func TestATSessionHandler_Output(t *testing.T) { + tests := []struct { + name string + input handlers.RequestSession + expectedPrefix string + expectedError bool + }{ + { + name: "Continue true", + input: handlers.RequestSession{ + Continue: true, + Engine: &httpmocks.MockEngine{ + WriteResultFunc: func(context.Context, io.Writer) (int, error) { + return 0, nil + }, + }, + Writer: &httpmocks.MockWriter{}, + }, + expectedPrefix: "CON ", + expectedError: false, + }, + { + name: "Continue false", + input: handlers.RequestSession{ + Continue: false, + Engine: &httpmocks.MockEngine{ + WriteResultFunc: func(context.Context, io.Writer) (int, error) { + return 0, nil + }, + }, + Writer: &httpmocks.MockWriter{}, + }, + expectedPrefix: "END ", + expectedError: false, + }, + { + name: "WriteResult error", + input: handlers.RequestSession{ + Continue: true, + Engine: &httpmocks.MockEngine{ + WriteResultFunc: func(context.Context, io.Writer) (int, error) { + return 0, errors.New("write error") + }, + }, + Writer: &httpmocks.MockWriter{}, + }, + expectedPrefix: "CON ", + expectedError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ash := &ATSessionHandler{} + _, err := ash.Output(tt.input) + + if tt.expectedError && err == nil { + t.Error("Expected an error, but got nil") + } + + if !tt.expectedError && err != nil { + t.Errorf("Unexpected error: %v", err) + } + + mw := tt.input.Writer.(*httpmocks.MockWriter) + if !mw.WriteStringCalled { + t.Error("WriteString was not called") + } + + if mw.WrittenString != tt.expectedPrefix { + t.Errorf("Expected prefix %q, got %q", tt.expectedPrefix, mw.WrittenString) + } + }) + } +}