diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..00ea919
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,4 @@
+FROM postgres:latest
+ENV POSTGRES_USER=admin
+ENV POSTGRES_PASSWORD=AdminPassword123
+ENV POSTGRES_DB=cogitans
diff --git a/README.md b/README.md
index b594a11..0f9bc93 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,16 @@ TODO - _UX_
* файл должен содержать абсолютный путь до файла конфигурации yaml
* файл должен лежать рядом с main.go
-## 1. Запуск
+## 2. Поднятие баз данных через docker
+
+### Postgres
+`docker build -t cogitans .`
+`docker run -d --name -p 5433:5432 `
+
+### Redis
+`docker run -d --name -p 6379:6379 redis redis-server --requirepass `
+
+## 3. Запуск
* go run .
## 4. Деплой
* [Сайт](http://jantugan.ru)
diff --git a/cmd/2024_1_ResCogitans/main.go b/cmd/2024_1_ResCogitans/main.go
index fb7c24f..2394cfe 100644
--- a/cmd/2024_1_ResCogitans/main.go
+++ b/cmd/2024_1_ResCogitans/main.go
@@ -9,20 +9,6 @@ import (
_ "github.com/swaggo/http-swagger/example/go-chi/docs"
)
-// @title Swagger Example API
-// @version 1.0
-// @description This is a sample server seller server.
-// @termsOfService http://swagger.io/terms/
-
-// @contact.name API Support
-// @contact.url http://www.swagger.io/support
-// @contact.email support@swagger.io
-
-// @license.name Apache 2.0
-// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
-
-// @host localhost:8080
-// @BasePath /api/v1
func main() {
logger := logger.Logger()
cfg, err := config.LoadConfig()
diff --git a/config/local.yaml b/config/local.yaml
index 0663ade..10c02ff 100644
--- a/config/local.yaml
+++ b/config/local.yaml
@@ -1,5 +1,4 @@
env: "local"
-storage_path: "./storage/storage.db"
http_server:
address: "localhost:8080"
timeout: 4s
diff --git a/go.mod b/go.mod
index 09b009c..e445780 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,6 @@ module github.com/go-park-mail-ru/2024_1_ResCogitans
go 1.22.0
require (
- github.com/go-chi/chi v4.1.2+incompatible
github.com/go-chi/chi/v5 v5.0.12
github.com/go-redis/redis/v8 v8.11.5
github.com/gorilla/securecookie v1.1.2
@@ -32,6 +31,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/lib/pq v1.10.2 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/stretchr/objx v0.5.2 // indirect
github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/tools v0.20.0 // indirect
diff --git a/internal/config/config.go b/internal/config/config.go
index 04f7c19..2648f5f 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -11,7 +11,6 @@ import (
type Config struct {
Env string `yaml:"env" env:"ENV" env-required:"true"`
- StoragePath string `yaml:"storage_path" env-required:"true"`
HTTPServer `yaml:"http_server"`
Dsn `yaml:"dsn"`
Redis `yaml:"redis"`
diff --git a/internal/delivery/db/db.go b/internal/delivery/db/db.go
index d58e971..a5abbb1 100644
--- a/internal/delivery/db/db.go
+++ b/internal/delivery/db/db.go
@@ -11,7 +11,7 @@ import (
"github.com/jackc/pgx/v5/pgxpool"
)
-// GetPostgress gets connection to postgres database
+// GetPostgres gets connection to postgres database
func GetPostgres() (*pgxpool.Pool, error) {
log := logger.Logger()
diff --git a/internal/delivery/handlers/authorization/auth_handler_test.go b/internal/delivery/handlers/authorization/auth_handler_test.go
index d7b13e8..a5f9afb 100644
--- a/internal/delivery/handlers/authorization/auth_handler_test.go
+++ b/internal/delivery/handlers/authorization/auth_handler_test.go
@@ -1,76 +1,480 @@
package authorization_test
-// import (
-// "context"
-// "encoding/json"
-// "net/http"
-// "net/http/httptest"
-// "strings"
-// "testing"
-
-// "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
-// // "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/http-server/handlers/login"
-// "github.com/stretchr/testify/assert"
-// )
-
-// func TestAuthorize(t *testing.T) {
-// authHandler := login.Authorization{}
-
-// entities.CreateUser("san", "123")
-
-// testCases := []struct {
-// name string
-// inputJSON string
-// expectedStatus int
-// expectedError string
-// }{
-// {
-// name: "Successful authorization",
-// inputJSON: `{"username": "san", "password": "123"}`,
-// expectedStatus: http.StatusOK,
-// expectedError: "",
-// },
-// {
-// name: "Empty username",
-// inputJSON: `{"username": "", "password": "testpassword"}`,
-// expectedStatus: http.StatusUnauthorized,
-// expectedError: "Authorization failed",
-// },
-// {
-// name: "Empty password",
-// inputJSON: `{"username": "testuser", "password": ""}`,
-// expectedStatus: http.StatusUnauthorized,
-// expectedError: "Authorization failed",
-// },
-// {
-// name: "User not found",
-// inputJSON: `{"username": "nonexistentuser", "password": "testpassword"}`,
-// expectedStatus: http.StatusUnauthorized,
-// expectedError: "Authorization failed",
-// },
-// }
-
-// for _, tc := range testCases {
-// t.Run(tc.name, func(t *testing.T) {
-// req, err := http.NewRequest("POST", "/login", strings.NewReader(tc.inputJSON))
-// if err != nil {
-// t.Fatal(err)
-// }
-// req.Header.Set("Content-Type", "application/json")
-
-// var user entities.User
-// err = json.NewDecoder(req.Body).Decode(&user)
-// if err != nil {
-// t.Fatal(err)
-// }
-
-// rr := httptest.NewRecorder()
-// ctx := context.WithValue(req.Context(), "responseWriter", rr)
-// ctx = context.WithValue(ctx, "requestData", user)
-
-// response, err := authHandler.Authorize(ctx)
-
-// assert.Equal(t, tc.expectedStatus, response.Status, "handler returned wrong status code")
-// })
-// }
-// }
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/authorization"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/mocks"
+ httperrors "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/errors"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/httputils"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+)
+
+// Тесты для авторизации
+func TestAuthorizationHandler_Authorize(t *testing.T) {
+ mockSessionUseCase := new(mocks.MockSessionUseCase)
+ mockUserUseCase := new(mocks.MockUserUseCase)
+
+ handler := authorization.NewAuthorizationHandler(mockSessionUseCase, mockUserUseCase)
+
+ user := entities.User{Username: "san@boy.ru", Password: "ABC123abc123!"}
+ jsonUser, err := json.Marshal(user)
+ if err != nil {
+ assert.NoError(t, err)
+ }
+
+ // Создание запроса для добавления в контекст
+ req, err := http.NewRequest("POST", "/api/login", bytes.NewBuffer(jsonUser))
+ if err != nil {
+ assert.NoError(t, err)
+ }
+
+ // Создание ResponseRecorder для записи ответа
+ rr := httptest.NewRecorder()
+
+ t.Run("Request without request key", func(t *testing.T) {
+ userResponse, err := handler.Authorize(context.Background(), user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ assert.Equal(t, "failed getting request", err.Error())
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ // Добавление запроса в контекст
+ ctx := context.WithValue(req.Context(), httputils.HttpRequestKey, req)
+
+ t.Run("Request without response writer key", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("UserExists", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ assert.Equal(t, "failed getting response writer", err.Error())
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ // добавление ключа ответа в контекст
+ ctx = context.WithValue(ctx, httputils.ResponseWriterKey, rr)
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Successful authorization", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("UserExists", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+ mockSessionUseCase.On("CreateSession", ctx, rr, 1).Return(nil).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+ assert.NoError(t, err)
+ assert.Equal(t, entities.UserResponse{ID: 1, Username: "san@boy.ru"}, userResponse)
+ assert.Equal(t, http.StatusOK, rr.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Wrong username", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("UserExists", ctx, "san@boy.ru", "ABC123abc123!").Return(httperrors.HttpError{Code: http.StatusBadRequest, Message: "user not found"}).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.Error(t, err)
+ assert.IsType(t, httperrors.HttpError{}, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "user not found", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Incorrect username", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(httperrors.HttpError{Code: http.StatusBadRequest, Message: "email doesn't meet requirements"}).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.Error(t, err)
+ assert.IsType(t, httperrors.HttpError{}, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "email doesn't meet requirements", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Incorrect password", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(httperrors.HttpError{Code: http.StatusBadRequest, Message: "password doesn't meet requirements"}).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.Error(t, err)
+ assert.IsType(t, httperrors.HttpError{}, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "password doesn't meet requirements", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Failed getting user by username", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("UserExists", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{}, httperrors.HttpError{Code: http.StatusBadRequest, Message: "user not found"}).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.Error(t, err)
+ assert.IsType(t, httperrors.HttpError{}, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "user not found", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Failed creating session", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("UserExists", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+ mockSessionUseCase.On("CreateSession", ctx, rr, 1).Return(errors.New("unexpected error")).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.Error(t, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "unexpected error", httpError.Message)
+ assert.Equal(t, http.StatusInternalServerError, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Cookie not found", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, httperrors.HttpError{Code: http.StatusBadRequest, Message: "cookie not found"}).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("UserExists", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+ mockSessionUseCase.On("CreateSession", ctx, rr, 1).Return(nil).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.UserResponse{ID: 1, Username: "san@boy.ru"}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error decoding cookie", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, errors.New("error decoding cookie")).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("UserExists", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+ mockSessionUseCase.On("CreateSession", ctx, rr, 1).Return(nil).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.UserResponse{ID: 1, Username: "san@boy.ru"}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Unexpected error getting session", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, errors.New("unexpected error")).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.Error(t, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "unexpected error", httpError.Message)
+ assert.Equal(t, http.StatusInternalServerError, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("User is already authorised", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", mock.Anything, mock.Anything).Return(1, nil).Once()
+
+ userResponse, err := handler.Authorize(ctx, user)
+
+ assert.Error(t, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "user is already authorized", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+}
+
+// Тесты для выхода из аккаунта
+func TestAuthorizationHandler_LogOut(t *testing.T) {
+ mockSessionUseCase := new(mocks.MockSessionUseCase)
+ mockUserUseCase := new(mocks.MockUserUseCase)
+
+ handler := authorization.NewAuthorizationHandler(mockSessionUseCase, mockUserUseCase)
+
+ user := entities.User{}
+ jsonUser, err := json.Marshal(user)
+ if err != nil {
+ assert.NoError(t, err)
+ }
+
+ // Создание запроса
+ req, err := http.NewRequest("POST", "/api/logout", bytes.NewBuffer(jsonUser))
+ if err != nil {
+ assert.NoError(t, err)
+ }
+
+ // Создание ResponseRecorder для записи ответа
+ rr := httptest.NewRecorder()
+
+ t.Run("Request without request key", func(t *testing.T) {
+ userResponse, err := handler.LogOut(context.Background(), user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ assert.Equal(t, "failed getting request", err.Error())
+ })
+
+ // Добавление запроса в контекст
+ ctx := context.WithValue(req.Context(), httputils.HttpRequestKey, req)
+
+ t.Run("Request without response writer key", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+
+ userResponse, err := handler.LogOut(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ assert.Equal(t, "failed getting response writer", err.Error())
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ // добавление ключа ответа в контекст
+ ctx = context.WithValue(ctx, httputils.ResponseWriterKey, rr)
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Cookie not found", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, httperrors.HttpError{Code: http.StatusUnauthorized, Message: "cookie not found"}).Once()
+
+ userResponse, err := handler.LogOut(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "cookie not found", httpError.Message)
+ assert.Equal(t, http.StatusUnauthorized, httpError.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error clearing session", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(1, nil).Once()
+ mockSessionUseCase.On("ClearSession", ctx, rr, req).Return(errors.New("error clearing session")).Once()
+
+ userResponse, err := handler.LogOut(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "error clearing session", httpError.Message)
+ assert.Equal(t, http.StatusInternalServerError, httpError.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Success log out", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(1, nil).Once()
+ mockSessionUseCase.On("ClearSession", ctx, rr, req).Return(nil).Once()
+
+ userResponse, err := handler.LogOut(ctx, user)
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+}
+
+// Тесты для обновления пароля
+func TestAuthorizationHandler_UpdatePassword(t *testing.T) {
+ mockSessionUseCase := new(mocks.MockSessionUseCase)
+ mockUserUseCase := new(mocks.MockUserUseCase)
+
+ handler := authorization.NewAuthorizationHandler(mockSessionUseCase, mockUserUseCase)
+
+ user := entities.User{Username: "san@boys.ru", Password: "ABC123abc1234!"}
+ jsonUser, err := json.Marshal(user)
+ if err != nil {
+ assert.NoError(t, err)
+ }
+
+ req, err := http.NewRequest("POST", "/api/login", bytes.NewBuffer(jsonUser))
+ if err != nil {
+ assert.NoError(t, err)
+ }
+
+ t.Run("Request without request key", func(t *testing.T) {
+ userResponse, err := handler.UpdatePassword(context.Background(), user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ assert.Equal(t, "failed getting request", err.Error())
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ // Добавление запроса в контекст
+ ctx := context.WithValue(req.Context(), httputils.HttpRequestKey, req)
+
+ t.Run("Cookie nit found", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, httperrors.HttpError{Code: http.StatusBadRequest, Message: "cookie not found"}).Once()
+
+ userResponse, err := handler.UpdatePassword(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "cookie not found", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Incorrect username", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(1, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boys.ru", "ABC123abc1234!").Return(httperrors.HttpError{Code: http.StatusBadRequest, Message: "email doesn't meet requirements"}).Once()
+
+ userResponse, err := handler.UpdatePassword(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "email doesn't meet requirements", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error changing password", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(1, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boys.ru", "ABC123abc1234!").Return(nil).Once()
+ mockUserUseCase.On("ChangePassword", ctx, 1, "ABC123abc1234!").Return(entities.User{}, errors.New("failed changing password")).Once()
+
+ userResponse, err := handler.UpdatePassword(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "failed changing password", httpError.Message)
+ assert.Equal(t, http.StatusInternalServerError, httpError.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Success changing password", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(1, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boys.ru", "ABC123abc1234!").Return(nil).Once()
+ mockUserUseCase.On("ChangePassword", ctx, 1, "ABC123abc1234!").Return(entities.User{ID: 1, Username: "san@boys.ru"}, nil).Once()
+
+ userResponse, err := handler.UpdatePassword(ctx, user)
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.UserResponse{ID: 1, Username: "san@boys.ru"}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+}
diff --git a/internal/delivery/handlers/authorization/authorization_handler.go b/internal/delivery/handlers/authorization/authorization_handler.go
index e7150ab..5785a93 100644
--- a/internal/delivery/handlers/authorization/authorization_handler.go
+++ b/internal/delivery/handlers/authorization/authorization_handler.go
@@ -11,11 +11,11 @@ import (
)
type AuthorizationHandler struct {
- sessionUseCase *usecase.SessionUseCase
- userUseCase *usecase.UserUseCase
+ sessionUseCase usecase.SessionInterface
+ userUseCase usecase.UserUseCaseInterface
}
-func NewAuthorizationHandler(sessionUseCase *usecase.SessionUseCase, userUseCase *usecase.UserUseCase) *AuthorizationHandler {
+func NewAuthorizationHandler(sessionUseCase usecase.SessionInterface, userUseCase usecase.UserUseCaseInterface) *AuthorizationHandler {
return &AuthorizationHandler{
sessionUseCase: sessionUseCase,
userUseCase: userUseCase,
@@ -33,18 +33,14 @@ func (h *AuthorizationHandler) Authorize(ctx context.Context, requestData entiti
sessionID, err := h.sessionUseCase.GetSession(ctx, request)
if err != nil {
- if !httperrors.IsHttpError(err) {
- return entities.UserResponse{}, err
- }
-
httpError := httperrors.UnwrapHttpError(err)
- if httpError.Message != "Cookie not found" && httpError.Message != "Error decoding cookie" {
+ if httpError.Message != "cookie not found" && httpError.Message != "error decoding cookie" {
return entities.UserResponse{}, httpError
}
}
if sessionID != 0 {
- return entities.UserResponse{}, httperrors.NewHttpError(http.StatusBadRequest, "User is already authorized")
+ return entities.UserResponse{}, httperrors.NewHttpError(http.StatusBadRequest, "user is already authorized")
}
if err := h.userUseCase.UserDataVerification(username, password); err != nil {
diff --git a/internal/delivery/handlers/quiz/review_handler.go b/internal/delivery/handlers/quiz/review_handler.go
index 513ea97..2b6783b 100644
--- a/internal/delivery/handlers/quiz/review_handler.go
+++ b/internal/delivery/handlers/quiz/review_handler.go
@@ -11,14 +11,14 @@ import (
)
type QuizHandler struct {
- questionUseCase *usecase.QuestionUseCase
- commentUseCase *usecase.CommentUseCase
- journeyUseCase *usecase.JourneyUseCase
+ questionUseCase usecase.QuestionUseCaseInterface
+ commentUseCase usecase.CommentUseCaseInterface
+ journeyUseCase usecase.JourneyUseCaseInterface
}
-func NewQuizHandler(questionUseCase *usecase.QuestionUseCase,
- commentUseCase *usecase.CommentUseCase,
- journeyUseCase *usecase.JourneyUseCase) *QuizHandler {
+func NewQuizHandler(questionUseCase usecase.QuestionUseCaseInterface,
+ commentUseCase usecase.CommentUseCaseInterface,
+ journeyUseCase usecase.JourneyUseCaseInterface) *QuizHandler {
return &QuizHandler{
questionUseCase: questionUseCase,
commentUseCase: commentUseCase,
@@ -32,7 +32,7 @@ func (h *QuizHandler) CreateReview(ctx context.Context, requestData entities.Rev
return false, err
}
if userID == 0 {
- return false, httperrors.NewHttpError(http.StatusUnauthorized, "Permission denied")
+ return false, httperrors.NewHttpError(http.StatusUnauthorized, "permission denied")
}
err = h.questionUseCase.CreateReview(ctx, userID, requestData)
@@ -89,7 +89,7 @@ func (h *QuizHandler) SetStat(ctx context.Context, _ entities.Statistic) ([]enti
return []entities.Statistic{}, err
}
if userID == 0 {
- return []entities.Statistic{}, httperrors.NewHttpError(http.StatusUnauthorized, "Permission denied")
+ return []entities.Statistic{}, httperrors.NewHttpError(http.StatusUnauthorized, "permission denied")
}
stat, err := h.questionUseCase.SetStat(ctx, userID)
diff --git a/internal/delivery/handlers/quiz/review_handler_test.go b/internal/delivery/handlers/quiz/review_handler_test.go
new file mode 100644
index 0000000..c77a23e
--- /dev/null
+++ b/internal/delivery/handlers/quiz/review_handler_test.go
@@ -0,0 +1,273 @@
+package quiz_test
+
+import (
+ "context"
+ "net/http"
+ "testing"
+
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/quiz"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/mocks"
+ httperrors "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/errors"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestQuizHandler_CreateReview(t *testing.T) {
+ mockQuestionUseCase := new(mocks.QuestionMockUseCase)
+ mockCommentUseCase := new(mocks.CommentMockUseCase)
+ mockJourneyUseCase := new(mocks.JourneyMockUseCase)
+
+ handler := quiz.NewQuizHandler(mockQuestionUseCase, mockCommentUseCase, mockJourneyUseCase)
+
+ t.Run("Error getting user id from context", func(t *testing.T) {
+ response, err := handler.CreateReview(context.Background(), entities.Review{})
+
+ assert.Error(t, err)
+ assert.Equal(t, "failed getting user from context", err.Error())
+ assert.Equal(t, false, response)
+ })
+
+ wrongCtx := context.WithValue(context.Background(), "userID", 0)
+
+ t.Run("Unauthorized user", func(t *testing.T) {
+ response, err := handler.CreateReview(wrongCtx, entities.Review{})
+
+ assert.Error(t, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "permission denied", httpError.Message)
+ assert.Equal(t, http.StatusUnauthorized, httpError.Code)
+ assert.Equal(t, false, response)
+ })
+
+ ctx := context.WithValue(context.Background(), "userID", 1)
+
+ t.Run("Error creating review", func(t *testing.T) {
+ mockQuestionUseCase.On("CreateReview", ctx, 1, entities.Review{UserID: 1, Rating: 4, QuestionID: 4}).Return(errors.New("error creating review")).Once()
+ response, err := handler.CreateReview(ctx, entities.Review{UserID: 1, Rating: 4, QuestionID: 4})
+
+ assert.Error(t, err)
+ assert.Equal(t, "error creating review", err.Error())
+ assert.Equal(t, false, response)
+
+ mockQuestionUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Successfully create review", func(t *testing.T) {
+ mockQuestionUseCase.On("CreateReview", ctx, 1, entities.Review{UserID: 1, Rating: 4, QuestionID: 4}).Return(nil).Once()
+ response, err := handler.CreateReview(ctx, entities.Review{UserID: 1, Rating: 4, QuestionID: 4})
+
+ assert.NoError(t, err)
+ assert.Equal(t, true, response)
+ mockQuestionUseCase.AssertExpectations(t)
+ })
+}
+
+func TestQuizHandler_CheckData(t *testing.T) {
+ mockQuestionUseCase := new(mocks.QuestionMockUseCase)
+ mockCommentUseCase := new(mocks.CommentMockUseCase)
+ mockJourneyUseCase := new(mocks.JourneyMockUseCase)
+
+ handler := quiz.NewQuizHandler(mockQuestionUseCase, mockCommentUseCase, mockJourneyUseCase)
+
+ t.Run("Error getting user id from context", func(t *testing.T) {
+ response, err := handler.CheckData(context.Background(), entities.Review{})
+
+ assert.Error(t, err)
+ assert.Equal(t, "failed getting user from context", err.Error())
+ assert.Equal(t, entities.DataCheck{}, response)
+ })
+
+ wrongCtx := context.WithValue(context.Background(), "userID", 0)
+
+ t.Run("Unauthorized user", func(t *testing.T) {
+ response, err := handler.CheckData(wrongCtx, entities.Review{})
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.DataCheck{Flag: false}, response)
+ })
+
+ ctx := context.WithValue(context.Background(), "userID", 1)
+
+ t.Run("Error getting question", func(t *testing.T) {
+ mockQuestionUseCase.On("GetQuestions", ctx).Return([]entities.QuestionResponse{}, errors.New("error getting questions")).Once()
+ response, err := handler.CheckData(ctx, entities.Review{})
+
+ assert.Error(t, err)
+ assert.Equal(t, "error getting questions", err.Error())
+ assert.Equal(t, entities.DataCheck{}, response)
+ mockQuestionUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Review is already completed", func(t *testing.T) {
+ mockQuestionUseCase.On("GetQuestions", ctx).Return([]entities.QuestionResponse{}, nil).Once()
+ mockQuestionUseCase.On("CheckReview", ctx, 1).Return(true, nil).Once()
+ response, err := handler.CheckData(ctx, entities.Review{})
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.DataCheck{Flag: false}, response)
+ mockQuestionUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error checking review", func(t *testing.T) {
+ mockQuestionUseCase.On("GetQuestions", ctx).Return([]entities.QuestionResponse{}, nil).Once()
+ mockQuestionUseCase.On("CheckReview", ctx, 1).Return(false, errors.New("error checking review")).Once()
+ response, err := handler.CheckData(ctx, entities.Review{})
+
+ assert.Error(t, err)
+ assert.Equal(t, "error checking review", err.Error())
+ assert.Equal(t, entities.DataCheck{Flag: false}, response)
+ mockQuestionUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Journey was created", func(t *testing.T) {
+ mockQuestionUseCase.On("GetQuestions", ctx).Return([]entities.QuestionResponse{}, nil).Once()
+ mockQuestionUseCase.On("CheckReview", ctx, 1).Return(false, nil).Once()
+ mockJourneyUseCase.On("CheckJourney", ctx, 1).Return(true, nil).Once()
+ response, err := handler.CheckData(ctx, entities.Review{})
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.DataCheck{Questions: []entities.QuestionResponse{}, Flag: true}, response)
+
+ mockQuestionUseCase.AssertExpectations(t)
+ mockJourneyUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+ mockJourneyUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error checking journey", func(t *testing.T) {
+ mockQuestionUseCase.On("GetQuestions", ctx).Return([]entities.QuestionResponse{}, nil).Once()
+ mockQuestionUseCase.On("CheckReview", ctx, 1).Return(false, nil).Once()
+ mockJourneyUseCase.On("CheckJourney", ctx, 1).Return(false, errors.New("error checking journey")).Once()
+ response, err := handler.CheckData(ctx, entities.Review{})
+
+ assert.Error(t, err)
+ assert.Equal(t, "error checking journey", err.Error())
+ assert.Equal(t, entities.DataCheck{Flag: false}, response)
+
+ mockQuestionUseCase.AssertExpectations(t)
+ mockJourneyUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+ mockJourneyUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Comment was created", func(t *testing.T) {
+ mockQuestionUseCase.On("GetQuestions", ctx).Return([]entities.QuestionResponse{}, nil).Once()
+ mockQuestionUseCase.On("CheckReview", ctx, 1).Return(false, nil).Once()
+ mockJourneyUseCase.On("CheckJourney", ctx, 1).Return(false, nil).Once()
+ mockCommentUseCase.On("CheckCommentByUserID", ctx, 1).Return(true, nil).Once()
+ response, err := handler.CheckData(ctx, entities.Review{})
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.DataCheck{Questions: []entities.QuestionResponse{}, Flag: true}, response)
+
+ mockQuestionUseCase.AssertExpectations(t)
+ mockJourneyUseCase.AssertExpectations(t)
+ mockCommentUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+ mockJourneyUseCase.Mock.ExpectedCalls = nil
+ mockCommentUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error checking comments", func(t *testing.T) {
+ mockQuestionUseCase.On("GetQuestions", ctx).Return([]entities.QuestionResponse{}, nil).Once()
+ mockQuestionUseCase.On("CheckReview", ctx, 1).Return(false, nil).Once()
+ mockJourneyUseCase.On("CheckJourney", ctx, 1).Return(false, nil).Once()
+ mockCommentUseCase.On("CheckCommentByUserID", ctx, 1).Return(false, errors.New("error checking comments")).Once()
+ response, err := handler.CheckData(ctx, entities.Review{})
+
+ assert.Error(t, err)
+ assert.Equal(t, "error checking comments", err.Error())
+ assert.Equal(t, entities.DataCheck{Flag: false}, response)
+
+ mockQuestionUseCase.AssertExpectations(t)
+ mockJourneyUseCase.AssertExpectations(t)
+ mockCommentUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+ mockJourneyUseCase.Mock.ExpectedCalls = nil
+ mockCommentUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Not active user", func(t *testing.T) {
+ mockQuestionUseCase.On("GetQuestions", ctx).Return([]entities.QuestionResponse{}, nil).Once()
+ mockQuestionUseCase.On("CheckReview", ctx, 1).Return(false, nil).Once()
+ mockJourneyUseCase.On("CheckJourney", ctx, 1).Return(false, nil).Once()
+ mockCommentUseCase.On("CheckCommentByUserID", ctx, 1).Return(false, nil).Once()
+ response, err := handler.CheckData(ctx, entities.Review{})
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.DataCheck{Flag: false}, response)
+
+ mockQuestionUseCase.AssertExpectations(t)
+ mockJourneyUseCase.AssertExpectations(t)
+ mockCommentUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+ mockJourneyUseCase.Mock.ExpectedCalls = nil
+ mockCommentUseCase.Mock.ExpectedCalls = nil
+}
+
+func TestQuizHandler_SetStat(t *testing.T) {
+ mockQuestionUseCase := new(mocks.QuestionMockUseCase)
+ mockCommentUseCase := new(mocks.CommentMockUseCase)
+ mockJourneyUseCase := new(mocks.JourneyMockUseCase)
+
+ handler := quiz.NewQuizHandler(mockQuestionUseCase, mockCommentUseCase, mockJourneyUseCase)
+
+ t.Run("Error getting request from context", func(t *testing.T) {
+ response, err := handler.SetStat(context.Background(), entities.Statistic{})
+
+ assert.Error(t, err)
+ assert.Equal(t, "failed getting user from context", err.Error())
+ assert.Equal(t, []entities.Statistic{}, response)
+ })
+
+ wrongCtx := context.WithValue(context.Background(), "userID", 0)
+
+ t.Run("Unauthorized user", func(t *testing.T) {
+ response, err := handler.SetStat(wrongCtx, entities.Statistic{})
+
+ assert.Error(t, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "permission denied", httpError.Message)
+ assert.Equal(t, http.StatusUnauthorized, httpError.Code)
+ assert.Equal(t, []entities.Statistic{}, response)
+ })
+
+ ctx := context.WithValue(context.Background(), "userID", 1)
+
+ t.Run("Error setting stat", func(t *testing.T) {
+ mockQuestionUseCase.On("SetStat", ctx, 1).Return([]entities.Statistic{}, errors.New("error setting stat")).Once()
+ response, err := handler.SetStat(ctx, entities.Statistic{})
+
+ assert.Error(t, err)
+ assert.Equal(t, "error setting stat", err.Error())
+ assert.Equal(t, []entities.Statistic{}, response)
+
+ mockQuestionUseCase.AssertExpectations(t)
+ })
+
+ mockQuestionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Success setting stat", func(t *testing.T) {
+ mockQuestionUseCase.On("SetStat", ctx, 1).Return([]entities.Statistic{{}}, nil)
+ response, err := handler.SetStat(ctx, entities.Statistic{})
+
+ assert.NoError(t, err)
+ assert.Equal(t, []entities.Statistic{{}}, response)
+ mockQuestionUseCase.AssertExpectations(t)
+ })
+}
diff --git a/internal/delivery/handlers/registration/registration_handler.go b/internal/delivery/handlers/registration/registration_handler.go
index 07ff844..a8aad68 100644
--- a/internal/delivery/handlers/registration/registration_handler.go
+++ b/internal/delivery/handlers/registration/registration_handler.go
@@ -11,11 +11,11 @@ import (
)
type RegistrationHandler struct {
- sessionUseCase *usecase.SessionUseCase
- userUseCase *usecase.UserUseCase
+ sessionUseCase usecase.SessionInterface
+ userUseCase usecase.UserUseCaseInterface
}
-func NewRegistrationHandler(sessionUseCase *usecase.SessionUseCase, userUseCase *usecase.UserUseCase) *RegistrationHandler {
+func NewRegistrationHandler(sessionUseCase usecase.SessionInterface, userUseCase usecase.UserUseCaseInterface) *RegistrationHandler {
return &RegistrationHandler{
sessionUseCase: sessionUseCase,
userUseCase: userUseCase,
@@ -34,13 +34,13 @@ func (h *RegistrationHandler) SignUp(ctx context.Context, requestData entities.U
sessionID, err := h.sessionUseCase.GetSession(ctx, request)
if err != nil {
httpError := httperrors.UnwrapHttpError(err)
- if httpError.Message != "Session not found" && httpError.Message != "Cookie not found" && httpError.Message != "Error decoding cookie" {
+ if httpError.Message != "cookie not found" && httpError.Message != "error decoding cookie" {
return entities.UserResponse{}, httpError
}
}
if sessionID != 0 {
- return entities.UserResponse{}, httperrors.NewHttpError(http.StatusBadRequest, "User is already authorized")
+ return entities.UserResponse{}, httperrors.NewHttpError(http.StatusBadRequest, "user is already authorized")
}
taken, err := h.userUseCase.IsEmailTaken(ctx, username)
@@ -48,7 +48,7 @@ func (h *RegistrationHandler) SignUp(ctx context.Context, requestData entities.U
return entities.UserResponse{}, err
}
if taken {
- return entities.UserResponse{}, httperrors.NewHttpError(http.StatusBadRequest, "Username is taken")
+ return entities.UserResponse{}, httperrors.NewHttpError(http.StatusBadRequest, "username is taken")
}
if err := h.userUseCase.UserDataVerification(username, password); err != nil {
diff --git a/internal/delivery/handlers/registration/signup_handler_test.go b/internal/delivery/handlers/registration/signup_handler_test.go
index 628f664..bc1bfad 100644
--- a/internal/delivery/handlers/registration/signup_handler_test.go
+++ b/internal/delivery/handlers/registration/signup_handler_test.go
@@ -1,79 +1,254 @@
package registration_test
-// import (
-// "context"
-// "encoding/json"
-// "net/http"
-// "strings"
-// "testing"
-
-// "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
-// "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/http-server/handlers/registration"
-// "github.com/stretchr/testify/assert"
-// )
-
-// func TestSignUp(t *testing.T) {
-// regHandler := registration.Registration{}
-
-// testCases := []struct {
-// name string
-// inputJSON string
-// expectedStatus int
-// expectedError string
-// }{
-// {
-// name: "Successful registration",
-// inputJSON: `{"username": "testuser", "password": "testpassword"}`,
-// expectedStatus: http.StatusCreated,
-// expectedError: "",
-// },
-// {
-// name: "Empty username",
-// inputJSON: `{"username": "", "password": "testpassword"}`,
-// expectedStatus: http.StatusBadRequest,
-// expectedError: "username and password must not be empty",
-// },
-// {
-// name: "Empty password",
-// inputJSON: `{"username": "testuser", "password": ""}`,
-// expectedStatus: http.StatusBadRequest,
-// expectedError: "username and password must not be empty",
-// },
-// {
-// name: "User already exists",
-// inputJSON: `{"username": "testuser", "password": "testpassword"}`,
-// expectedStatus: http.StatusBadRequest,
-// expectedError: "username already exists",
-// },
-// }
-
-// for _, tc := range testCases {
-// t.Run(tc.name, func(t *testing.T) {
-
-// req, err := http.NewRequest("POST", "/signup", strings.NewReader(tc.inputJSON))
-// if err != nil {
-// t.Fatal(err)
-// }
-// req.Header.Set("Content-Type", "application/json")
-
-// var user entities.User
-// err = json.NewDecoder(req.Body).Decode(&user)
-// if err != nil {
-// t.Fatal(err)
-// }
-
-// ctx := context.WithValue(req.Context(), "requestData", user)
-
-// response, err := regHandler.SignUp(ctx)
-// if err != nil && tc.expectedError == "" {
-// t.Errorf("Ошибка при вызове SignUp: %v", err)
-// }
-
-// assert.Equal(t, tc.expectedStatus, response.Status, "handler returned wrong status code")
-
-// if tc.expectedError != "" {
-// assert.EqualError(t, err, tc.expectedError, "handler returned unexpected error message")
-// }
-// })
-// }
-// }
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/registration"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/mocks"
+ httperrors "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/errors"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/httputils"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestRegistrationHandler_SignUp(t *testing.T) {
+ mockSessionUseCase := new(mocks.MockSessionUseCase)
+ mockUserUseCase := new(mocks.MockUserUseCase)
+
+ handler := registration.NewRegistrationHandler(mockSessionUseCase, mockUserUseCase)
+
+ user := entities.User{Username: "san@boy.ru", Password: "ABC123abc123!"}
+ jsonUser, err := json.Marshal(user)
+ if err != nil {
+ assert.NoError(t, err)
+ }
+
+ // Создание запроса для добавления в контекст
+ req, err := http.NewRequest("POST", "/api/signup", bytes.NewBuffer(jsonUser))
+ if err != nil {
+ assert.NoError(t, err)
+ }
+
+ // Создание ResponseRecorder для записи ответа
+ rr := httptest.NewRecorder()
+
+ t.Run("Request without request key", func(t *testing.T) {
+ userResponse, err := handler.SignUp(context.Background(), user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ assert.Equal(t, "failed getting request", err.Error())
+ })
+
+ // Добавление запроса в контекст
+ ctx := context.WithValue(req.Context(), httputils.HttpRequestKey, req)
+
+ t.Run("Request without response writer key", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(false, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("CreateUser", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+ assert.Equal(t, "failed getting response writer", err.Error())
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ // добавление ключа ответа в контекст
+ ctx = context.WithValue(ctx, httputils.ResponseWriterKey, rr)
+
+ t.Run("Successful registration", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(false, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("CreateUser", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+ mockSessionUseCase.On("CreateSession", ctx, rr, 1).Return(nil).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+ assert.NoError(t, err)
+ assert.Equal(t, entities.UserResponse{ID: 1, Username: "san@boy.ru"}, userResponse)
+ assert.Equal(t, http.StatusOK, rr.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Cookie not found", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, httperrors.HttpError{Code: http.StatusBadRequest, Message: "cookie not found"}).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(false, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("CreateUser", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+ mockSessionUseCase.On("CreateSession", ctx, rr, 1).Return(nil).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+ assert.NoError(t, err)
+ assert.Equal(t, entities.UserResponse{ID: 1, Username: "san@boy.ru"}, userResponse)
+ assert.Equal(t, http.StatusOK, rr.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error decoding cookie", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, httperrors.HttpError{Code: http.StatusInternalServerError, Message: "error decoding cookie"}).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(false, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("CreateUser", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+ mockSessionUseCase.On("CreateSession", ctx, rr, 1).Return(nil).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+ assert.NoError(t, err)
+ assert.Equal(t, entities.UserResponse{ID: 1, Username: "san@boy.ru"}, userResponse)
+ assert.Equal(t, http.StatusOK, rr.Code)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error getting session", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, errors.New("unexpected error")).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+ assert.Error(t, err)
+ assert.Equal(t, "unexpected error", err.Error())
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Authorized user", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(1, nil).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+
+ assert.Error(t, err)
+ assert.Equal(t, "user is already authorized", err.Error())
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Email is taken", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(true, nil).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+
+ assert.Error(t, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "username is taken", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Wrong username", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(false, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(httperrors.HttpError{Code: http.StatusBadRequest, Message: "email doesn't meet requirements"}).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+ assert.Error(t, err)
+ httpError := httperrors.UnwrapHttpError(err)
+ assert.Equal(t, "email doesn't meet requirements", httpError.Message)
+ assert.Equal(t, http.StatusBadRequest, httpError.Code)
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error creating user", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(false, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("CreateUser", ctx, "san@boy.ru", "ABC123abc123!").Return(errors.New("unexpected error")).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+ assert.Error(t, err)
+ assert.Equal(t, "unexpected error", err.Error())
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error getting user by email", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(false, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("CreateUser", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{}, errors.New("unexpected error")).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+ assert.Error(t, err)
+ assert.Equal(t, "unexpected error", err.Error())
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+
+ mockUserUseCase.Mock.ExpectedCalls = nil
+ mockSessionUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error creating session", func(t *testing.T) {
+ mockSessionUseCase.On("GetSession", ctx, req).Return(0, nil).Once()
+ mockUserUseCase.On("IsEmailTaken", ctx, "san@boy.ru").Return(false, nil).Once()
+ mockUserUseCase.On("UserDataVerification", "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("CreateUser", ctx, "san@boy.ru", "ABC123abc123!").Return(nil).Once()
+ mockUserUseCase.On("GetUserByEmail", ctx, "san@boy.ru").Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil).Once()
+ mockSessionUseCase.On("CreateSession", ctx, rr, 1).Return(errors.New("unexpected error")).Once()
+
+ userResponse, err := handler.SignUp(ctx, user)
+ assert.Error(t, err)
+ assert.Equal(t, "unexpected error", err.Error())
+ assert.Equal(t, entities.UserResponse{}, userResponse)
+
+ mockSessionUseCase.AssertExpectations(t)
+ mockUserUseCase.AssertExpectations(t)
+ })
+}
diff --git a/internal/delivery/handlers/sight/sight_handler.go b/internal/delivery/handlers/sight/sight_handler.go
index 6c027d2..df01a62 100644
--- a/internal/delivery/handlers/sight/sight_handler.go
+++ b/internal/delivery/handlers/sight/sight_handler.go
@@ -7,13 +7,14 @@ import (
"github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
"github.com/go-park-mail-ru/2024_1_ResCogitans/internal/usecase"
"github.com/go-park-mail-ru/2024_1_ResCogitans/utils/httputils"
+ "github.com/pkg/errors"
)
type SightHandler struct {
- SightUseCase *usecase.SightUseCase
+ SightUseCase usecase.SightUseCaseInterface
}
-func NewSightsHandler(usecase *usecase.SightUseCase) *SightHandler {
+func NewSightsHandler(usecase usecase.SightUseCaseInterface) *SightHandler {
return &SightHandler{
SightUseCase: usecase,
}
@@ -31,7 +32,7 @@ func (h *SightHandler) GetSight(ctx context.Context, _ entities.Sight) (entities
pathParams := httputils.GetPathParamsFromCtx(ctx)
id, err := strconv.Atoi(pathParams["id"])
if err != nil {
- return entities.SightComments{}, err
+ return entities.SightComments{}, errors.Wrap(err, "error getting id from parameters")
}
sight, err := h.SightUseCase.GetSightByID(ctx, id)
if err != nil {
diff --git a/internal/delivery/handlers/sight/sight_handler_test.go b/internal/delivery/handlers/sight/sight_handler_test.go
index 0ba2bf1..5b1721b 100644
--- a/internal/delivery/handlers/sight/sight_handler_test.go
+++ b/internal/delivery/handlers/sight/sight_handler_test.go
@@ -4,76 +4,95 @@ import (
"context"
"testing"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/sight"
"github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
- "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/wrapper"
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/mocks"
+ "github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
-func TestGetSights(t *testing.T) {
- handler := &SightsHandler{}
+func TestSightHandler_GetSights(t *testing.T) {
+ mockSightUseCase := new(mocks.MockSightUseCase)
- ctx := context.Background()
+ handler := sight.NewSightsHandler(mockSightUseCase)
- resp, err := handler.GetSights(ctx, entities.Sight{})
- if err != nil {
- t.Fatalf("Failed to get sights: %v", err)
- }
+ t.Run("Successfully receiving a list of sites", func(t *testing.T) {
+ // TODO подставить в sights значения
+ mockSightUseCase.On("GetSightsList", context.Background()).Return([]entities.Sight{}, nil).Once()
- assert.NotEmpty(t, resp.Sight)
+ response, err := handler.GetSights(context.Background(), entities.Sight{})
- expectedFirstSight := entities.Sight{
- ID: 1,
- Rating: 2.1,
- Name: "У дяди Вани",
- Description: "Ресторан с видом на Сталинскую высотку.",
- CityID: 1,
- CountryID: 1,
- Path: "public/1.jpg",
- }
- assert.Equal(t, expectedFirstSight, resp.Sight[0])
+ assert.NoError(t, err)
+ assert.Equal(t, entities.Sights{Sight: []entities.Sight{}}, response)
+
+ mockSightUseCase.AssertExpectations(t)
+ })
+
+ mockSightUseCase.Mock.ExpectedCalls = nil
+
+ t.Run("Error getting sight", func(t *testing.T) {
+ mockSightUseCase.On("GetSightsList", context.Background()).Return([]entities.Sight{}, errors.New("unexpected error")).Once()
+ response, err := handler.GetSights(context.Background(), entities.Sight{})
+
+ assert.Error(t, err)
+ assert.Equal(t, entities.Sights{}, response)
+ assert.Equal(t, "unexpected error", err.Error())
+
+ mockSightUseCase.AssertExpectations(t)
+ })
}
-func TestGetSightsByID(t *testing.T) {
- comm := entities.Comments{}
- handler := &SightsHandler{}
-
- comm.Validate()
-
- ctx := context.Background()
- param := make(map[string]string)
- param["id"] = "1"
- ctx = wrapper.SetPathParamsToCtx(ctx, param)
-
- resp, err := handler.GetSightByID(ctx, entities.Sight{})
- if err != nil {
- t.Fatalf("Failed to get sights: %v", err)
- }
-
- assert.NotEmpty(t, resp.Sight)
-
- expectedSight := entities.Sight{
- ID: 1,
- Rating: 2.1,
- Name: "У дяди Вани",
- Description: "Ресторан с видом на Сталинскую высотку.",
- CityID: 1,
- CountryID: 1,
- City: "Москва",
- Country: "Россия",
- Path: "public/1.jpg",
- }
- assert.Equal(t, expectedSight, resp.Sight)
+func TestSightHandler_GetSight(t *testing.T) {
+ mockSightUseCase := new(mocks.MockSightUseCase)
+
+ handler := sight.NewSightsHandler(mockSightUseCase)
+
+ t.Run("Error getting path parameters", func(t *testing.T) {
+ response, err := handler.GetSight(context.Background(), entities.Sight{})
+ assert.Error(t, err)
+ assert.Equal(t, "error getting id from parameters: strconv.Atoi: parsing \"\": invalid syntax", err.Error())
+ assert.Equal(t, entities.SightComments{}, response)
+ })
+
+ // TODO создать запрос с параметром, где ключ - id, значение - 1
+ //req, err := http.NewRequest("GET", "/api/sight/1", nil)
+ //if err != nil {
+ // assert.NoError(t, err)
+ //}
+ //
+ //params := wrapper.GetPathParams(req)
+ //ctx := httputils.SetPathParamsToCtx(context.Background(), params)
+ //
+ //t.Run("Successfully get sight", func(t *testing.T) {
+ // mockSightUseCase""
+ //})
}
-func TestGetSightsByIDNotInt(t *testing.T) {
- handler := &SightsHandler{}
+func TestSightHandler_SearchSights(t *testing.T) {
+ mockSightUseCase := new(mocks.MockSightUseCase)
+
+ handler := sight.NewSightsHandler(mockSightUseCase)
+
+ t.Run("Successfully receiving a sight", func(t *testing.T) {
+ // TODO подставить в sights значения
+ mockSightUseCase.On("SearchSights", context.Background(), "лес").Return(entities.Sights{}, nil).Once()
+ response, err := handler.SearchSights(context.Background(), entities.Sight{Name: "лес"})
+
+ assert.NoError(t, err)
+ assert.Equal(t, entities.Sights{}, response)
+
+ mockSightUseCase.AssertExpectations(t)
+ })
+
+ mockSightUseCase.Mock.ExpectedCalls = nil
- ctx := context.Background()
- param := make(map[string]string)
- param["id"] = "id"
- ctx = wrapper.SetPathParamsToCtx(ctx, param)
+ t.Run("Error searching sight", func(t *testing.T) {
+ mockSightUseCase.On("SearchSights", context.Background(), "лес").Return(entities.Sights{}, errors.New("unexpected error")).Once()
+ response, err := handler.SearchSights(context.Background(), entities.Sight{Name: "лес"})
- _, err := handler.GetSightByID(ctx, entities.Sight{})
+ assert.Error(t, err)
+ assert.Equal(t, entities.Sights{}, response)
- assert.NotNil(t, err)
+ mockSightUseCase.AssertExpectations(t)
+ })
}
diff --git a/internal/mocks/comment_mock.go b/internal/mocks/comment_mock.go
new file mode 100644
index 0000000..23f4efe
--- /dev/null
+++ b/internal/mocks/comment_mock.go
@@ -0,0 +1,32 @@
+package mocks
+
+import (
+ "context"
+
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ "github.com/stretchr/testify/mock"
+)
+
+type CommentMockUseCase struct {
+ mock.Mock
+}
+
+func (m *CommentMockUseCase) CreateCommentBySightID(ctx context.Context, sightID int, comment entities.Comment) error {
+ args := m.Called(ctx, sightID, comment)
+ return args.Error(0)
+}
+
+func (m *CommentMockUseCase) EditCommentByCommentID(ctx context.Context, commentID int, comment entities.Comment) error {
+ args := m.Called(ctx, commentID, comment)
+ return args.Error(0)
+}
+
+func (m *CommentMockUseCase) DeleteCommentByCommentID(ctx context.Context, commentID int) error {
+ args := m.Called(ctx, commentID)
+ return args.Error(0)
+}
+
+func (m *CommentMockUseCase) CheckCommentByUserID(ctx context.Context, userID int) (bool, error) {
+ args := m.Called(ctx, userID)
+ return args.Bool(0), args.Error(1)
+}
diff --git a/internal/mocks/journey_mock.go b/internal/mocks/journey_mock.go
new file mode 100644
index 0000000..3e8d001
--- /dev/null
+++ b/internal/mocks/journey_mock.go
@@ -0,0 +1,57 @@
+package mocks
+
+import (
+ "context"
+
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ "github.com/stretchr/testify/mock"
+)
+
+type JourneyMockUseCase struct {
+ mock.Mock
+}
+
+func (m *JourneyMockUseCase) CreateJourney(ctx context.Context, journey entities.Journey) (entities.Journey, error) {
+ args := m.Called(ctx, journey)
+ return args.Get(0).(entities.Journey), args.Error(1)
+}
+
+func (m *JourneyMockUseCase) DeleteJourneyByID(ctx context.Context, journeyID int) error {
+ args := m.Called(ctx, journeyID)
+ return args.Error(0)
+}
+
+func (m *JourneyMockUseCase) GetJourneys(ctx context.Context, userID int) ([]entities.Journey, error) {
+ args := m.Called(ctx, userID)
+ return args.Get(0).([]entities.Journey), args.Error(1)
+}
+
+func (m *JourneyMockUseCase) AddJourneySight(ctx context.Context, journeyID int, ids []int) error {
+ args := m.Called(ctx, journeyID, ids)
+ return args.Error(0)
+}
+
+func (m *JourneyMockUseCase) EditJourney(ctx context.Context, journeyID int, name, description string) error {
+ args := m.Called(ctx, journeyID, name, description)
+ return args.Error(0)
+}
+
+func (m *JourneyMockUseCase) DeleteJourneySight(ctx context.Context, journeyID int, sight entities.JourneySight) error {
+ args := m.Called(ctx, journeyID, sight)
+ return args.Error(0)
+}
+
+func (m *JourneyMockUseCase) GetJourneySights(ctx context.Context, journeyID int) ([]entities.Sight, error) {
+ args := m.Called(ctx, journeyID)
+ return args.Get(0).([]entities.Sight), args.Error(1)
+}
+
+func (m *JourneyMockUseCase) GetJourney(ctx context.Context, journeyID int) (entities.Journey, error) {
+ args := m.Called(ctx, journeyID)
+ return args.Get(0).(entities.Journey), args.Error(1)
+}
+
+func (m *JourneyMockUseCase) CheckJourney(ctx context.Context, userID int) (bool, error) {
+ args := m.Called(ctx, userID)
+ return args.Bool(0), args.Error(1)
+}
diff --git a/internal/mocks/question_mock.go b/internal/mocks/question_mock.go
new file mode 100644
index 0000000..0e9c389
--- /dev/null
+++ b/internal/mocks/question_mock.go
@@ -0,0 +1,32 @@
+package mocks
+
+import (
+ "context"
+
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ "github.com/stretchr/testify/mock"
+)
+
+type QuestionMockUseCase struct {
+ mock.Mock
+}
+
+func (m *QuestionMockUseCase) CreateReview(ctx context.Context, userID int, review entities.Review) error {
+ args := m.Called(ctx, userID, review)
+ return args.Error(0)
+}
+
+func (m *QuestionMockUseCase) GetQuestions(ctx context.Context) ([]entities.QuestionResponse, error) {
+ args := m.Called(ctx)
+ return args.Get(0).([]entities.QuestionResponse), args.Error(1)
+}
+
+func (m *QuestionMockUseCase) CheckReview(ctx context.Context, userID int) (bool, error) {
+ args := m.Called(ctx, userID)
+ return args.Bool(0), args.Error(1)
+}
+
+func (m *QuestionMockUseCase) SetStat(ctx context.Context, userID int) ([]entities.Statistic, error) {
+ args := m.Called(ctx, userID)
+ return args.Get(0).([]entities.Statistic), args.Error(1)
+}
diff --git a/internal/mocks/session_mock.go b/internal/mocks/session_mock.go
new file mode 100644
index 0000000..0f2584f
--- /dev/null
+++ b/internal/mocks/session_mock.go
@@ -0,0 +1,27 @@
+package mocks
+
+import (
+ "context"
+ "net/http"
+
+ "github.com/stretchr/testify/mock"
+)
+
+type MockSessionUseCase struct {
+ mock.Mock
+}
+
+func (m *MockSessionUseCase) CreateSession(ctx context.Context, w http.ResponseWriter, userID int) error {
+ args := m.Called(ctx, w, userID)
+ return args.Error(0)
+}
+
+func (m *MockSessionUseCase) GetSession(ctx context.Context, r *http.Request) (int, error) {
+ args := m.Called(ctx, r)
+ return args.Int(0), args.Error(1)
+}
+
+func (m *MockSessionUseCase) ClearSession(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
+ args := m.Called(ctx, w, r)
+ return args.Error(0)
+}
diff --git a/internal/mocks/sight_mock.go b/internal/mocks/sight_mock.go
new file mode 100644
index 0000000..918c6d6
--- /dev/null
+++ b/internal/mocks/sight_mock.go
@@ -0,0 +1,37 @@
+package mocks
+
+import (
+ "context"
+
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ "github.com/stretchr/testify/mock"
+)
+
+type MockSightUseCase struct {
+ mock.Mock
+}
+
+func (m *MockSightUseCase) GetSightByID(ctx context.Context, sightID int) (entities.Sight, error) {
+ args := m.Called(ctx, sightID)
+ return args.Get(0).(entities.Sight), args.Error(1)
+}
+
+func (m *MockSightUseCase) GetCommentsBySightID(ctx context.Context, commentID int) ([]entities.Comment, error) {
+ args := m.Called(ctx, commentID)
+ return args.Get(0).([]entities.Comment), args.Error(1)
+}
+
+func (m *MockSightUseCase) GetCommentsByUserID(ctx context.Context, userID int) ([]entities.Comment, error) {
+ args := m.Called(ctx, userID)
+ return args.Get(0).([]entities.Comment), args.Error(1)
+}
+
+func (m *MockSightUseCase) GetSightsList(ctx context.Context) ([]entities.Sight, error) {
+ args := m.Called(ctx)
+ return args.Get(0).([]entities.Sight), args.Error(1)
+}
+
+func (m *MockSightUseCase) SearchSights(ctx context.Context, str string) (entities.Sights, error) {
+ args := m.Called(ctx, str)
+ return args.Get(0).(entities.Sights), args.Error(1)
+}
diff --git a/internal/mocks/user_mock.go b/internal/mocks/user_mock.go
new file mode 100644
index 0000000..9c068bf
--- /dev/null
+++ b/internal/mocks/user_mock.go
@@ -0,0 +1,52 @@
+package mocks
+
+import (
+ "context"
+
+ "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ "github.com/stretchr/testify/mock"
+)
+
+type MockUserUseCase struct {
+ mock.Mock
+}
+
+func (m *MockUserUseCase) CreateUser(ctx context.Context, email string, password string) error {
+ args := m.Called(ctx, email, password)
+ return args.Error(0)
+}
+
+func (m *MockUserUseCase) GetUserByEmail(ctx context.Context, email string) (entities.User, error) {
+ args := m.Called(ctx, email)
+ return args.Get(0).(entities.User), args.Error(1)
+}
+
+func (m *MockUserUseCase) GetUserByID(ctx context.Context, userID int) (entities.User, error) {
+ args := m.Called(ctx, userID)
+ return args.Get(0).(entities.User), args.Error(1)
+}
+
+func (m *MockUserUseCase) DeleteUser(ctx context.Context, userID int) error {
+ args := m.Called(ctx, userID)
+ return args.Error(0)
+}
+
+func (m *MockUserUseCase) UserDataVerification(email, password string) error {
+ args := m.Called(email, password)
+ return args.Error(0)
+}
+
+func (m *MockUserUseCase) ChangePassword(ctx context.Context, userID int, password string) (entities.User, error) {
+ args := m.Called(ctx, userID, password)
+ return args.Get(0).(entities.User), args.Error(1)
+}
+
+func (m *MockUserUseCase) UserExists(ctx context.Context, email, password string) error {
+ args := m.Called(ctx, email, password)
+ return args.Error(0)
+}
+
+func (m *MockUserUseCase) IsEmailTaken(ctx context.Context, email string) (bool, error) {
+ args := m.Called(ctx, email)
+ return args.Bool(0), args.Error(1)
+}
diff --git a/internal/storage/postgres/user/user_storage.go b/internal/storage/postgres/user/user_storage.go
index 8421a08..ca9adab 100644
--- a/internal/storage/postgres/user/user_storage.go
+++ b/internal/storage/postgres/user/user_storage.go
@@ -2,9 +2,13 @@ package user
import (
"context"
+ "net/http"
"github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities"
+ httperrors "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/errors"
+ "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
+ "github.com/pkg/errors"
)
// UserStorage struct
@@ -47,6 +51,9 @@ func (us *UserStorage) GetUserByEmail(ctx context.Context, email string) (entiti
var user entities.User
err := us.db.QueryRow(ctx, `SELECT id, email, passwrd, salt FROM user_data WHERE email = $1`, email).Scan(&user.ID, &user.Username, &user.Password, &user.Salt)
if err != nil {
+ if errors.Is(err, pgx.ErrNoRows) {
+ return entities.User{}, httperrors.NewHttpError(http.StatusBadRequest, "user not found")
+ }
return entities.User{}, err
}
return user, nil
diff --git a/internal/usecase/session_usecase.go b/internal/usecase/session_usecase.go
index 30cc62c..9b10d25 100644
--- a/internal/usecase/session_usecase.go
+++ b/internal/usecase/session_usecase.go
@@ -2,7 +2,6 @@ package usecase
import (
"context"
- "fmt"
"net/http"
"time"
@@ -59,7 +58,7 @@ func (a *SessionUseCase) GetSession(ctx context.Context, r *http.Request) (int,
cookie, err := r.Cookie(sessionId)
if err != nil {
if errors.Is(err, http.ErrNoCookie) {
- return 0, httperrors.NewHttpError(http.StatusUnauthorized, "Cookie not found")
+ return 0, httperrors.NewHttpError(http.StatusUnauthorized, "cookie not found")
}
return 0, err
}
@@ -68,7 +67,7 @@ func (a *SessionUseCase) GetSession(ctx context.Context, r *http.Request) (int,
if err = CookieHandler.Decode(sessionId, cookie.Value, &sessionID); err == nil {
return a.SessionStorage.GetSession(ctx, sessionID)
}
- return 0, fmt.Errorf("error decoding cookie: %w", err)
+ return 0, errors.New("error decoding cookie")
}
func (a *SessionUseCase) ClearSession(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
diff --git a/internal/usecase/user_usecase.go b/internal/usecase/user_usecase.go
index 1938304..5961d38 100644
--- a/internal/usecase/user_usecase.go
+++ b/internal/usecase/user_usecase.go
@@ -18,7 +18,7 @@ type UserUseCaseInterface interface {
GetUserByEmail(ctx context.Context, email string) (entities.User, error)
GetUserByID(ctx context.Context, userID int) (entities.User, error)
DeleteUser(ctx context.Context, userID int) error
- UserDataVerification(ctx context.Context, email, password string) error
+ UserDataVerification(email, password string) error
ChangePassword(ctx context.Context, userID int, password string) (entities.User, error)
UserExists(ctx context.Context, email, password string) error
IsEmailTaken(ctx context.Context, email string) (bool, error)
@@ -39,7 +39,7 @@ func (u *UserUseCase) CreateUser(ctx context.Context, email, password string) er
saltedPassword := password + salt
hashPassword, err := bcrypt.GenerateFromPassword([]byte(saltedPassword), bcrypt.DefaultCost)
if err != nil {
- return errors.New("Failed creating hash password")
+ return errors.New("failed creating hash password")
}
err = u.UserStorage.SaveUser(ctx, email, string(hashPassword), salt)
@@ -60,10 +60,10 @@ func (u *UserUseCase) DeleteUser(ctx context.Context, userID int) error {
func (u *UserUseCase) UserDataVerification(email, password string) error {
if !ValidateEmail(email) {
- return httperrors.NewHttpError(http.StatusBadRequest, "Email doesn't meet requirements")
+ return httperrors.NewHttpError(http.StatusBadRequest, "email doesn't meet requirements")
}
if !ValidatePassword(password) {
- return httperrors.NewHttpError(http.StatusBadRequest, "Password doesn't meet requirements")
+ return httperrors.NewHttpError(http.StatusBadRequest, "password doesn't meet requirements")
}
return nil
diff --git a/router/router.go b/router/router.go
index fc4be19..b58255a 100644
--- a/router/router.go
+++ b/router/router.go
@@ -3,8 +3,8 @@ package router
import (
"net/http"
- "github.com/go-chi/chi/middleware"
"github.com/go-chi/chi/v5"
+ "github.com/go-chi/chi/v5/middleware"
"github.com/go-park-mail-ru/2024_1_ResCogitans/internal/config"
"github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/authorization"
user "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/avatar"
diff --git a/utils/httputils/httputils.go b/utils/httputils/httputils.go
index 494de4e..d8d3f63 100644
--- a/utils/httputils/httputils.go
+++ b/utils/httputils/httputils.go
@@ -20,7 +20,7 @@ func SetRequestToCtx(ctx context.Context, r *http.Request) context.Context {
func GetRequestFromCtx(ctx context.Context) (*http.Request, error) {
r, ok := ctx.Value(HttpRequestKey).(*http.Request)
if !ok {
- return nil, errors.New("Failed getting request")
+ return nil, errors.New("failed getting request")
}
return r, nil
}
@@ -44,7 +44,7 @@ func SetResponseWriterToCtx(ctx context.Context, w http.ResponseWriter) context.
func GetResponseWriterFromCtx(ctx context.Context) (http.ResponseWriter, error) {
w, ok := ctx.Value(ResponseWriterKey).(http.ResponseWriter)
if !ok {
- return nil, errors.New("Failed getting response writer")
+ return nil, errors.New("failed getting response writer")
}
return w, nil
}
@@ -53,7 +53,7 @@ func GetUserFromCtx(ctx context.Context) (int, error) {
user := ctx.Value("userID")
userID, ok := user.(int)
if !ok {
- return 0, errors.New("Failed getting user from context")
+ return 0, errors.New("failed getting user from context")
}
return userID, nil
}