package web_test import ( "bytes" "encoding/json" "io" "net/http" "net/http/httptest" "testing" "time" "code.severnaya.net/kordophone-mock/v2/model" "code.severnaya.net/kordophone-mock/v2/server" "code.severnaya.net/kordophone-mock/v2/web" ) func TestVersion(t *testing.T) { s := httptest.NewServer(web.NewMockHTTPServer(web.MockHTTPServerConfiguration{})) resp, err := http.Get(s.URL + "/version") if err != nil { t.Fatalf("TestVersion error: %s", err) } body, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("Error decoding body: %s", body) } if string(body) != server.VERSION { t.Fatalf("Unexpected return value: %s (expected %s)", body, "1.0") } } func TestStatus(t *testing.T) { s := httptest.NewServer(web.NewMockHTTPServer(web.MockHTTPServerConfiguration{})) resp, err := http.Get(s.URL + "/status") if err != nil { t.Fatalf("TestStatus error: %s", err) } body, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("Error decoding body: %s", body) } if string(body) != "OK" { t.Fatalf("Unexpected return value: %s (expected %s)", body, "OK") } } func TestConversations(t *testing.T) { server := web.NewMockHTTPServer(web.MockHTTPServerConfiguration{}) httpServer := httptest.NewServer(server) conversation := model.Conversation{ Date: time.Now(), Participants: []string{"Alice", "Bob"}, UnreadCount: 1, LastMessagePreview: "Hello world", Guid: "1234567890", } server.Server.AddConversation(conversation) resp, err := http.Get(httpServer.URL + "/conversations") if err != nil { t.Fatalf("TestConversations error: %s", err) } body, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("Error decoding body: %s", body) } var convos []model.Conversation err = json.Unmarshal(body, &convos) if err != nil { t.Fatalf("Error unmarshalling JSON: %s", err) } if len(convos) != 1 { t.Fatalf("Unexpected number of conversations: %d (expected %d)", len(convos), 1) } if convos[0].Guid != conversation.Guid { t.Fatalf("Unexpected conversation GUID: %s (expected %s)", convos[0].Guid, conversation.Guid) } if convos[0].LastMessagePreview != conversation.LastMessagePreview { t.Fatalf("Unexpected conversation LastMessagePreview: %s (expected %s)", convos[0].LastMessagePreview, conversation.LastMessagePreview) } if convos[0].UnreadCount != conversation.UnreadCount { t.Fatalf("Unexpected conversation UnreadCount: %d (expected %d)", convos[0].UnreadCount, conversation.UnreadCount) } for i, p := range convos[0].Participants { if p != conversation.Participants[i] { t.Fatalf("Unexpected conversation Participants: %s (expected %s)", p, conversation.Participants[i]) } } if !convos[0].Date.Equal(conversation.Date) { t.Fatalf("Unexpected conversation Date: %s (expected %s)", convos[0].Date, conversation.Date) } } func TestAuthentication(t *testing.T) { s := web.NewMockHTTPServer(web.MockHTTPServerConfiguration{AuthEnabled: true}) httpServer := httptest.NewServer(s) // First, try authenticated request and make sure it fails resp, err := http.Get(httpServer.URL + "/status") if err != nil { t.Fatalf("TestAuthentication status error: %s", err) } if resp.StatusCode != http.StatusUnauthorized { t.Fatalf("Unexpected status code: %d (expected %d)", resp.StatusCode, http.StatusUnauthorized) } tryAuthenticate := func(username string, password string) *http.Response { authRequest := web.AuthenticationRequest{ Username: username, Password: password, } authRequestJSON, err := json.Marshal(authRequest) if err != nil { t.Fatalf("Error marshalling JSON: %s", err) } resp, err := http.Post(httpServer.URL+"/authenticate", "application/json", io.NopCloser(bytes.NewReader(authRequestJSON))) if err != nil { t.Fatalf("TestAuthentication error: %s", err) } return resp } // Send authentication request with bad credentials resp = tryAuthenticate("bad", "credentials") if resp.StatusCode == http.StatusOK { t.Fatalf("Unexpected status code: %d (expected %d)", resp.StatusCode, http.StatusUnauthorized) } // Now try good credentials resp = tryAuthenticate(server.AUTH_USERNAME, server.AUTH_PASSWORD) if resp.StatusCode != http.StatusOK { t.Fatalf("Unexpected status code: %d (expected %d)", resp.StatusCode, http.StatusOK) } // Decode the token from the body. body, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("Error decoding body: %s", body) } var authToken model.AuthToken err = json.Unmarshal(body, &authToken) if err != nil { t.Fatalf("Error unmarshalling JSON: %s, body: %s", err, body) } if authToken.SignedToken == "" { t.Fatalf("Unexpected empty signed token") } // Send a request with the signed token req, err := http.NewRequest(http.MethodGet, httpServer.URL+"/status", nil) if err != nil { t.Fatalf("Error creating request: %s", err) } req.Header.Set("Authorization", "Bearer "+authToken.SignedToken) resp, err = http.DefaultClient.Do(req) if err != nil { t.Fatalf("Error sending request: %s", err) } if resp.StatusCode != http.StatusOK { t.Fatalf("Unexpected status code: %d (expected %d)", resp.StatusCode, http.StatusUnauthorized) } body, err = io.ReadAll(resp.Body) if err != nil { t.Fatalf("Error decoding body: %s", body) } if string(body) != "OK" { t.Fatalf("Unexpected body: %s (expected %s)", body, "OK") } }