chrly/internal/http/profiles_test.go

172 lines
4.6 KiB
Go

package http
import (
"bytes"
"context"
"errors"
"io"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
"ely.by/chrly/internal/db"
"ely.by/chrly/internal/profiles"
)
type ProfilesManagerMock struct {
mock.Mock
}
func (m *ProfilesManagerMock) PersistProfile(ctx context.Context, profile *db.Profile) error {
return m.Called(ctx, profile).Error(0)
}
func (m *ProfilesManagerMock) RemoveProfileByUuid(ctx context.Context, uuid string) error {
return m.Called(ctx, uuid).Error(0)
}
type ProfilesTestSuite struct {
suite.Suite
App *ProfilesApi
ProfilesManager *ProfilesManagerMock
}
func (t *ProfilesTestSuite) SetupSubTest() {
t.ProfilesManager = &ProfilesManagerMock{}
t.App, _ = NewProfilesApi(t.ProfilesManager)
}
func (t *ProfilesTestSuite) TearDownSubTest() {
t.ProfilesManager.AssertExpectations(t.T())
}
func (t *ProfilesTestSuite) TestPostProfile() {
t.Run("successfully post profile", func() {
t.ProfilesManager.On("PersistProfile", mock.Anything, &db.Profile{
Uuid: "0f657aa8-bfbe-415d-b700-5750090d3af3",
Username: "mock_username",
SkinUrl: "https://example.com/skin.png",
SkinModel: "slim",
CapeUrl: "https://example.com/cape.png",
MojangTextures: "bW9jawo=",
MojangSignature: "bW9jawo=",
}).Once().Return(nil)
req := httptest.NewRequest("POST", "http://chrly/", bytes.NewBufferString(url.Values{
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
"username": {"mock_username"},
"skinUrl": {"https://example.com/skin.png"},
"skinModel": {"slim"},
"capeUrl": {"https://example.com/cape.png"},
"mojangTextures": {"bW9jawo="},
"mojangSignature": {"bW9jawo="},
}.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
w := httptest.NewRecorder()
t.App.Handler().ServeHTTP(w, req)
result := w.Result()
t.Equal(http.StatusCreated, result.StatusCode)
body, _ := io.ReadAll(result.Body)
t.Empty(body)
})
t.Run("handle malformed body", func() {
req := httptest.NewRequest("POST", "http://chrly/", strings.NewReader("invalid;=url?encoded_string"))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
w := httptest.NewRecorder()
t.App.Handler().ServeHTTP(w, req)
result := w.Result()
t.Equal(http.StatusBadRequest, result.StatusCode)
body, _ := io.ReadAll(result.Body)
t.JSONEq(`{
"errors": {
"body": [
"The body of the request must be a valid url-encoded string"
]
}
}`, string(body))
})
t.Run("receive validation errors", func() {
t.ProfilesManager.On("PersistProfile", mock.Anything, mock.Anything).Once().Return(&profiles.ValidationError{
Errors: map[string][]string{
"Username": {"error1", "error2"},
},
})
req := httptest.NewRequest("POST", "http://chrly/", strings.NewReader(""))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
w := httptest.NewRecorder()
t.App.Handler().ServeHTTP(w, req)
result := w.Result()
t.Equal(http.StatusBadRequest, result.StatusCode)
body, _ := io.ReadAll(result.Body)
t.JSONEq(`{
"errors": {
"username": [
"error1",
"error2"
]
}
}`, string(body))
})
t.Run("receive other error", func() {
t.ProfilesManager.On("PersistProfile", mock.Anything, mock.Anything).Once().Return(errors.New("mock error"))
req := httptest.NewRequest("POST", "http://chrly/", strings.NewReader(""))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
w := httptest.NewRecorder()
t.App.Handler().ServeHTTP(w, req)
result := w.Result()
t.Equal(http.StatusInternalServerError, result.StatusCode)
})
}
func (t *ProfilesTestSuite) TestDeleteProfileByUuid() {
t.Run("successfully delete", func() {
t.ProfilesManager.On("RemoveProfileByUuid", mock.Anything, "0f657aa8-bfbe-415d-b700-5750090d3af3").Once().Return(nil)
req := httptest.NewRequest("DELETE", "http://chrly/0f657aa8-bfbe-415d-b700-5750090d3af3", nil)
w := httptest.NewRecorder()
t.App.Handler().ServeHTTP(w, req)
resp := w.Result()
t.Equal(http.StatusNoContent, resp.StatusCode)
body, _ := io.ReadAll(resp.Body)
t.Empty(body)
})
t.Run("error from manager", func() {
t.ProfilesManager.On("RemoveProfileByUuid", mock.Anything, mock.Anything).Return(errors.New("mock error"))
req := httptest.NewRequest("DELETE", "http://chrly/0f657aa8-bfbe-415d-b700-5750090d3af3", nil)
w := httptest.NewRecorder()
t.App.Handler().ServeHTTP(w, req)
resp := w.Result()
t.Equal(http.StatusInternalServerError, resp.StatusCode)
})
}
func TestProfilesApi(t *testing.T) {
suite.Run(t, new(ProfilesTestSuite))
}