docs: add integration test run instructions to README.md
- Added section 8 'Тестирование' with run instructions, structure, features, and diagnostics - Also includes test file route path adjustments and import reordering
This commit is contained in:
@@ -1344,4 +1344,64 @@ Refresh token хранится в **HttpOnly cookie**.
|
|||||||
"field password is invalid: min"
|
"field password is invalid: min"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Тестирование
|
||||||
|
|
||||||
|
### 8.1 Запуск интеграционных тестов
|
||||||
|
|
||||||
|
Интеграционные тесты используют in-memory SQLite и mock-репозитории. Запуск:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd main_dc/yalarba/api_yal
|
||||||
|
CGO_ENABLED=1 go test ./tests/integration/... -v -count=1
|
||||||
|
```
|
||||||
|
|
||||||
|
**Требования:**
|
||||||
|
- Go 1.21+
|
||||||
|
- `CGO_ENABLED=1` (используется `mattn/go-sqlite3`)
|
||||||
|
- Зависимости устанавливаются автоматически через `go mod download`
|
||||||
|
|
||||||
|
### 8.2 Структура тестов
|
||||||
|
|
||||||
|
```
|
||||||
|
tests/
|
||||||
|
├── integration/
|
||||||
|
│ ├── account_test.go # Тесты аккаунтов (профиль, обновление, удаление)
|
||||||
|
│ ├── appeal_test.go # Тесты обращений (CRUD, мои обращения)
|
||||||
|
│ ├── auth_test.go # Тесты аутентификации (регистрация, логин, refresh, logout, сброс пароля)
|
||||||
|
│ ├── comment_test.go # Тесты комментариев (CRUD, список, статистика)
|
||||||
|
│ ├── feedback_test.go # Тесты отзывов (CRUD, список, поиск, статистика)
|
||||||
|
│ ├── object_test.go # Тесты объектов (CRUD, поиск, nearby)
|
||||||
|
│ └── rating_test.go # Тесты рейтингов (голосование, статистика)
|
||||||
|
└── testutils/
|
||||||
|
├── fixtures.go # DTO и хелперы создания тестовых данных
|
||||||
|
├── mock_appeal_repository.go # Mock-репозиторий обращений (map-based)
|
||||||
|
├── mock_object_repository.go # Mock-репозиторий объектов (map-based)
|
||||||
|
├── setup.go # TestConfig, TestUser, HTTP-клиент
|
||||||
|
└── test_server.go # Chi-роутер, in-memory SQLite, middleware
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.3 Особенности
|
||||||
|
|
||||||
|
- **Общий сервер**: Все тесты в одном запуске используют один экземпляр `TestServer` (синглтон через `sync.Once`).
|
||||||
|
- **In-memory БД**: SQLite `file::memory:?cache=shared`, данные не сохраняются между запусками.
|
||||||
|
- **Mock-репозитории**: `ObjectRepository` и `AppealRepository` заменены на map-based реализации (избегают Haversine и jsonb-зависимостей).
|
||||||
|
- **Автоочистка**: Тестовые пользователи удаляются после каждого теста через `CleanupTestUser`.
|
||||||
|
- **Bearer-токены**: JWT токен создаётся при регистрации и передаётся в `Authorization` заголовке.
|
||||||
|
|
||||||
|
### 8.4 Диагностика
|
||||||
|
|
||||||
|
Для просмотра HTTP-логов сервера:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CGO_ENABLED=1 go test ./tests/integration/... -v -count=1 2>&1 | grep "\[ValitovGazizPC"
|
||||||
|
```
|
||||||
|
|
||||||
|
Фильтрация по конкретному тесту:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CGO_ENABLED=1 go test ./tests/integration/... -v -count=1 -run "TestAuthFlow/PasswordReset"
|
||||||
```
|
```
|
||||||
@@ -1,21 +1,18 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"api_yal/tests/testutils"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
"api_yal/tests/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAccountEndpoints тестирует все эндпоинты управления аккаунтом пользователя
|
|
||||||
// Включает получение профиля, обновление данных, смену пароля и удаление аккаунта
|
|
||||||
func TestAccountEndpoints(t *testing.T) {
|
func TestAccountEndpoints(t *testing.T) {
|
||||||
config := testutils.NewTestConfig()
|
config := testutils.NewTestConfig()
|
||||||
|
|
||||||
// GetProfile тестирует получение профиля авторизованного пользователя
|
|
||||||
t.Run("GetProfile", func(t *testing.T) {
|
t.Run("GetProfile", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/account/profile", nil, user.Token)
|
resp, err := config.Request("GET", "/profile", nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get profile: %v", err)
|
t.Fatalf("Failed to get profile: %v", err)
|
||||||
}
|
}
|
||||||
@@ -30,7 +27,6 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем наличие всех обязательных полей в ответе
|
|
||||||
expectedFields := []string{"id", "email", "full_name", "first_name", "last_name", "role", "stats"}
|
expectedFields := []string{"id", "email", "full_name", "first_name", "last_name", "role", "stats"}
|
||||||
for _, field := range expectedFields {
|
for _, field := range expectedFields {
|
||||||
if _, ok := profile[field]; !ok {
|
if _, ok := profile[field]; !ok {
|
||||||
@@ -39,12 +35,11 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// GetOwnAccount тестирует получение данных собственного аккаунта
|
|
||||||
t.Run("GetOwnAccount", func(t *testing.T) {
|
t.Run("GetOwnAccount", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/account", nil, user.Token)
|
resp, err := config.Request("GET", "/me", nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get account: %v", err)
|
t.Fatalf("Failed to get account: %v", err)
|
||||||
}
|
}
|
||||||
@@ -55,7 +50,6 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// UpdateAccount тестирует обновление данных аккаунта (телефон, город)
|
|
||||||
t.Run("UpdateAccount", func(t *testing.T) {
|
t.Run("UpdateAccount", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
@@ -65,7 +59,7 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
"city": "Moscow",
|
"city": "Moscow",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := config.Request("PUT", "/account", updateData, user.Token)
|
resp, err := config.Request("PUT", "/me", updateData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to update account: %v", err)
|
t.Fatalf("Failed to update account: %v", err)
|
||||||
}
|
}
|
||||||
@@ -80,19 +74,17 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, что номер телефона обновился корректно
|
|
||||||
if phone, ok := updatedAccount["phone"].(string); !ok || phone != "+79998887766" {
|
if phone, ok := updatedAccount["phone"].(string); !ok || phone != "+79998887766" {
|
||||||
t.Error("Phone number not updated correctly")
|
t.Error("Phone number not updated correctly")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// ChangePassword тестирует успешную смену пароля
|
|
||||||
t.Run("ChangePassword", func(t *testing.T) {
|
t.Run("ChangePassword", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
newPassword := "newpass123"
|
newPassword := "newpass123"
|
||||||
resp, err := config.Request("POST", "/account/change-password", map[string]interface{}{
|
resp, err := config.Request("POST", "/change-password", map[string]interface{}{
|
||||||
"current_password": user.Password,
|
"current_password": user.Password,
|
||||||
"new_password": newPassword,
|
"new_password": newPassword,
|
||||||
}, user.Token)
|
}, user.Token)
|
||||||
@@ -105,7 +97,6 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, что можно войти с новым паролем
|
|
||||||
newToken, err := config.GetAuthToken(user.Email, newPassword)
|
newToken, err := config.GetAuthToken(user.Email, newPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to login with new password: %v", err)
|
t.Errorf("Failed to login with new password: %v", err)
|
||||||
@@ -115,12 +106,11 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// ChangePasswordWrongCurrent тестирует смену пароля с неверным текущим паролем
|
|
||||||
t.Run("ChangePasswordWrongCurrent", func(t *testing.T) {
|
t.Run("ChangePasswordWrongCurrent", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
resp, err := config.Request("POST", "/account/change-password", map[string]interface{}{
|
resp, err := config.Request("POST", "/change-password", map[string]interface{}{
|
||||||
"current_password": "wrongpassword",
|
"current_password": "wrongpassword",
|
||||||
"new_password": "newpass123",
|
"new_password": "newpass123",
|
||||||
}, user.Token)
|
}, user.Token)
|
||||||
@@ -129,17 +119,15 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// Ожидаем ошибку 400 или 401 при неверном текущем пароле
|
|
||||||
if resp.StatusCode != 400 && resp.StatusCode != 401 {
|
if resp.StatusCode != 400 && resp.StatusCode != 401 {
|
||||||
t.Errorf("Expected status 400 or 401, got %d", resp.StatusCode)
|
t.Errorf("Expected status 400 or 401, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// DeleteAccount тестирует удаление аккаунта
|
|
||||||
t.Run("DeleteAccount", func(t *testing.T) {
|
t.Run("DeleteAccount", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
|
|
||||||
resp, err := config.Request("DELETE", "/account", nil, user.Token)
|
resp, err := config.Request("DELETE", "/me", nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to delete account: %v", err)
|
t.Fatalf("Failed to delete account: %v", err)
|
||||||
}
|
}
|
||||||
@@ -149,16 +137,14 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, что больше нельзя войти после удаления аккаунта
|
|
||||||
_, err = config.GetAuthToken(user.Email, user.Password)
|
_, err = config.GetAuthToken(user.Email, user.Password)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Should not be able to login after account deletion")
|
t.Error("Should not be able to login after account deletion")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// UnauthorizedAccess тестирует доступ к защищенным эндпоинтам без токена
|
|
||||||
t.Run("UnauthorizedAccess", func(t *testing.T) {
|
t.Run("UnauthorizedAccess", func(t *testing.T) {
|
||||||
resp, err := config.Request("GET", "/account/profile", nil, "")
|
resp, err := config.Request("GET", "/profile", nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to make request: %v", err)
|
t.Fatalf("Failed to make request: %v", err)
|
||||||
}
|
}
|
||||||
@@ -168,4 +154,4 @@ func TestAccountEndpoints(t *testing.T) {
|
|||||||
t.Errorf("Expected status 401, got %d", resp.StatusCode)
|
t.Errorf("Expected status 401, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,202 +1,188 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"fmt"
|
||||||
"api_yal/tests/testutils"
|
"testing"
|
||||||
|
"api_yal/tests/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAppealEndpoints тестирует все эндпоинты для работы с обращениями пользователей
|
|
||||||
// Включает создание, получение, обновление, удаление обращений и получение списка своих обращений
|
|
||||||
func TestAppealEndpoints(t *testing.T) {
|
func TestAppealEndpoints(t *testing.T) {
|
||||||
config := testutils.NewTestConfig()
|
config := testutils.NewTestConfig()
|
||||||
|
|
||||||
// CreateAppeal тестирует создание нового обращения
|
t.Run("CreateAppeal", func(t *testing.T) {
|
||||||
t.Run("CreateAppeal", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
appealData := map[string]interface{}{
|
appealData := map[string]interface{}{
|
||||||
"type": "complaint",
|
"type": "complaint",
|
||||||
"title": "Test Appeal",
|
"title": "Test Appeal",
|
||||||
"message": "This is a test appeal message for testing purposes",
|
"message": "This is a test appeal message for testing purposes",
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"contact_name": "Test User",
|
"contact_name": "Test User",
|
||||||
"contact_email": user.Email,
|
"contact_email": user.Email,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := config.Request("POST", "/appeals", appealData, user.Token)
|
resp, err := config.Request("POST", "/appeals", appealData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create appeal: %v", err)
|
t.Fatalf("Failed to create appeal: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// Ожидаем статус 201 Created
|
if resp.StatusCode != 201 {
|
||||||
if resp.StatusCode != 201 {
|
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
||||||
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var createdAppeal map[string]interface{}
|
var createdAppeal map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdAppeal); err != nil {
|
if err := config.ParseResponse(resp, &createdAppeal); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, что ID обращения присутствует в ответе
|
if _, ok := createdAppeal["id"]; !ok {
|
||||||
if _, ok := createdAppeal["id"]; !ok {
|
t.Error("Appeal ID not found")
|
||||||
t.Error("Appeal ID not found")
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
// GetAppealByID тестирует получение обращения по ID
|
t.Run("GetAppealByID", func(t *testing.T) {
|
||||||
t.Run("GetAppealByID", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
// Создаем обращение
|
appealData := map[string]interface{}{
|
||||||
appealData := map[string]interface{}{
|
"type": "question",
|
||||||
"type": "question",
|
"title": "Test Question",
|
||||||
"title": "Test Question",
|
"message": "This is a test question",
|
||||||
"message": "This is a test question",
|
"contact_email": user.Email,
|
||||||
"contact_email": user.Email,
|
}
|
||||||
}
|
resp, err := config.Request("POST", "/appeals", appealData, user.Token)
|
||||||
resp, err := config.Request("POST", "/appeals", appealData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create appeal: %v", err)
|
||||||
t.Fatalf("Failed to create appeal: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var createdAppeal map[string]interface{}
|
var createdAppeal map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdAppeal); err != nil {
|
if err := config.ParseResponse(resp, &createdAppeal); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
appealID := createdAppeal["id"].(float64)
|
appealID := createdAppeal["id"].(float64)
|
||||||
|
|
||||||
getResp, err := config.Request("GET", "/appeals/"+string(rune(appealID)), nil, user.Token)
|
getResp, err := config.Request("GET", "/appeals/"+fmt.Sprintf("%.0f", appealID), nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get appeal: %v", err)
|
t.Fatalf("Failed to get appeal: %v", err)
|
||||||
}
|
}
|
||||||
defer getResp.Body.Close()
|
defer getResp.Body.Close()
|
||||||
|
|
||||||
if getResp.StatusCode != 200 {
|
if getResp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", getResp.StatusCode)
|
t.Errorf("Expected status 200, got %d", getResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// UpdateAppeal тестирует обновление существующего обращения
|
t.Run("UpdateAppeal", func(t *testing.T) {
|
||||||
t.Run("UpdateAppeal", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
// Создаем обращение
|
appealData := map[string]interface{}{
|
||||||
appealData := map[string]interface{}{
|
"type": "suggestion",
|
||||||
"type": "suggestion",
|
"title": "Original Title",
|
||||||
"title": "Original Title",
|
"message": "Original message for testing",
|
||||||
"message": "Original message for testing",
|
"contact_email": user.Email,
|
||||||
"contact_email": user.Email,
|
}
|
||||||
}
|
resp, err := config.Request("POST", "/appeals", appealData, user.Token)
|
||||||
resp, err := config.Request("POST", "/appeals", appealData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create appeal: %v", err)
|
||||||
t.Fatalf("Failed to create appeal: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var createdAppeal map[string]interface{}
|
var createdAppeal map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdAppeal); err != nil {
|
if err := config.ParseResponse(resp, &createdAppeal); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
appealID := createdAppeal["id"].(float64)
|
appealID := createdAppeal["id"].(float64)
|
||||||
|
|
||||||
updateData := map[string]interface{}{
|
updateData := map[string]interface{}{
|
||||||
"title": "Updated Title",
|
"title": "Updated Title",
|
||||||
"message": "Updated message content",
|
"message": "Updated message content",
|
||||||
"priority": "critical",
|
"priority": "critical",
|
||||||
}
|
}
|
||||||
|
|
||||||
updateResp, err := config.Request("PUT", "/appeals/"+string(rune(appealID)), updateData, user.Token)
|
updateResp, err := config.Request("PUT", "/appeals/"+fmt.Sprintf("%.0f", appealID), updateData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to update appeal: %v", err)
|
t.Fatalf("Failed to update appeal: %v", err)
|
||||||
}
|
}
|
||||||
defer updateResp.Body.Close()
|
defer updateResp.Body.Close()
|
||||||
|
|
||||||
if updateResp.StatusCode != 200 {
|
if updateResp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", updateResp.StatusCode)
|
t.Errorf("Expected status 200, got %d", updateResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// MyAppeals тестирует получение списка обращений текущего пользователя
|
t.Run("MyAppeals", func(t *testing.T) {
|
||||||
t.Run("MyAppeals", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
// Создаем несколько обращений
|
for i := 0; i < 3; i++ {
|
||||||
for i := 0; i < 3; i++ {
|
appealData := map[string]interface{}{
|
||||||
appealData := map[string]interface{}{
|
"type": "other",
|
||||||
"type": "other",
|
"title": "Test Appeal",
|
||||||
"title": "Test Appeal",
|
"message": "Test message content",
|
||||||
"message": "Test message content",
|
}
|
||||||
}
|
_, err := config.Request("POST", "/appeals", appealData, user.Token)
|
||||||
_, err := config.Request("POST", "/appeals", appealData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create appeal: %v", err)
|
||||||
t.Fatalf("Failed to create appeal: %v", err)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/appeals/me", nil, user.Token)
|
resp, err := config.Request("GET", "/appeals/me", nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get my appeals: %v", err)
|
t.Fatalf("Failed to get my appeals: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// DeleteAppeal тестирует удаление обращения
|
t.Run("DeleteAppeal", func(t *testing.T) {
|
||||||
t.Run("DeleteAppeal", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
// Создаем обращение
|
appealData := map[string]interface{}{
|
||||||
appealData := map[string]interface{}{
|
"type": "question",
|
||||||
"type": "question",
|
"title": "To Delete",
|
||||||
"title": "To Delete",
|
"message": "This appeal will be deleted",
|
||||||
"message": "This appeal will be deleted",
|
}
|
||||||
}
|
resp, err := config.Request("POST", "/appeals", appealData, user.Token)
|
||||||
resp, err := config.Request("POST", "/appeals", appealData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create appeal: %v", err)
|
||||||
t.Fatalf("Failed to create appeal: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var createdAppeal map[string]interface{}
|
var createdAppeal map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdAppeal); err != nil {
|
if err := config.ParseResponse(resp, &createdAppeal); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
appealID := createdAppeal["id"].(float64)
|
appealID := createdAppeal["id"].(float64)
|
||||||
|
|
||||||
deleteResp, err := config.Request("DELETE", "/appeals/"+string(rune(appealID)), nil, user.Token)
|
deleteResp, err := config.Request("DELETE", "/appeals/"+fmt.Sprintf("%.0f", appealID), nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to delete appeal: %v", err)
|
t.Fatalf("Failed to delete appeal: %v", err)
|
||||||
}
|
}
|
||||||
defer deleteResp.Body.Close()
|
defer deleteResp.Body.Close()
|
||||||
|
|
||||||
// Ожидаем статус 204 No Content при успешном удалении
|
if deleteResp.StatusCode != 204 {
|
||||||
if deleteResp.StatusCode != 204 {
|
t.Errorf("Expected status 204, got %d", deleteResp.StatusCode)
|
||||||
t.Errorf("Expected status 204, got %d", deleteResp.StatusCode)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Проверяем, что обращение удалено - должно вернуть 404
|
getResp, err := config.Request("GET", "/appeals/"+fmt.Sprintf("%.0f", appealID), nil, user.Token)
|
||||||
getResp, err := config.Request("GET", "/appeals/"+string(rune(appealID)), nil, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to get appeal: %v", err)
|
||||||
t.Fatalf("Failed to get appeal: %v", err)
|
}
|
||||||
}
|
defer getResp.Body.Close()
|
||||||
defer getResp.Body.Close()
|
|
||||||
|
|
||||||
if getResp.StatusCode != 404 {
|
if getResp.StatusCode != 404 {
|
||||||
t.Errorf("Expected status 404 for deleted appeal, got %d", getResp.StatusCode)
|
t.Errorf("Expected status 404 for deleted appeal, got %d", getResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,228 +1,218 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"api_yal/tests/testutils"
|
"api_yal/tests/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAuthFlow тестирует полный поток аутентификации пользователя
|
|
||||||
// Включает регистрацию, логин, обновление токена, выход, сброс пароля и мобильную авторизацию
|
|
||||||
func TestAuthFlow(t *testing.T) {
|
func TestAuthFlow(t *testing.T) {
|
||||||
config := testutils.NewTestConfig()
|
config := testutils.NewTestConfig()
|
||||||
|
|
||||||
// Register тестирует регистрацию нового пользователя
|
|
||||||
t.Run("Register", func(t *testing.T) {
|
|
||||||
testData := map[string]interface{}{
|
|
||||||
"email": "testflow@example.com",
|
|
||||||
"password": "test123456",
|
|
||||||
"first_name": "Flow",
|
|
||||||
"last_name": "Test",
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := config.Request("POST", "/auth/register", testData, "")
|
t.Run("Register", func(t *testing.T) {
|
||||||
if err != nil {
|
testData := map[string]interface{}{
|
||||||
t.Fatalf("Failed to register: %v", err)
|
"email": "testflow@example.com",
|
||||||
}
|
"password": "test123456",
|
||||||
defer resp.Body.Close()
|
"first_name": "Flow",
|
||||||
|
"last_name": "Test",
|
||||||
|
}
|
||||||
|
|
||||||
// Ожидаем статус 201 Created при успешной регистрации
|
resp, err := config.Request("POST", "/auth/register", testData, "")
|
||||||
if resp.StatusCode != 201 {
|
if err != nil {
|
||||||
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
t.Fatalf("Failed to register: %v", err)
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var result map[string]interface{}
|
if resp.StatusCode != 201 {
|
||||||
if err := config.ParseResponse(resp, &result); err != nil {
|
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Проверяем наличие токена и данных пользователя в ответе
|
var result map[string]interface{}
|
||||||
if _, ok := result["token"]; !ok {
|
if err := config.ParseResponse(resp, &result); err != nil {
|
||||||
t.Error("Token not found in response")
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := result["user"]; !ok {
|
if _, ok := result["token"]; !ok {
|
||||||
t.Error("User data not found in response")
|
t.Error("Token not found in response")
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
// Login тестирует вход существующего пользователя
|
if _, ok := result["user"]; !ok {
|
||||||
t.Run("Login", func(t *testing.T) {
|
t.Error("User data not found in response")
|
||||||
// Сначала создаем пользователя
|
}
|
||||||
user := config.CreateTestUser(t)
|
})
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
// Тестируем логин
|
t.Run("Login", func(t *testing.T) {
|
||||||
resp, err := config.Request("POST", "/auth/login", map[string]interface{}{
|
user := config.CreateTestUser(t)
|
||||||
"email": user.Email,
|
defer config.CleanupTestUser(t, user)
|
||||||
"password": user.Password,
|
|
||||||
}, "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to login: %v", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
resp, err := config.Request("POST", "/auth/login", map[string]interface{}{
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
"email": user.Email,
|
||||||
}
|
"password": user.Password,
|
||||||
|
}, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to login: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var result map[string]interface{}
|
if resp.StatusCode != 200 {
|
||||||
if err := config.ParseResponse(resp, &result); err != nil {
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := result["token"]; !ok {
|
var result map[string]interface{}
|
||||||
t.Error("Token not found in response")
|
if err := config.ParseResponse(resp, &result); err != nil {
|
||||||
}
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Проверяем, что refresh token установлен в cookie
|
if _, ok := result["token"]; !ok {
|
||||||
cookies := resp.Cookies()
|
t.Error("Token not found in response")
|
||||||
foundRefreshToken := false
|
}
|
||||||
for _, cookie := range cookies {
|
|
||||||
if cookie.Name == "refresh_token" {
|
|
||||||
foundRefreshToken = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !foundRefreshToken {
|
|
||||||
t.Error("Refresh token cookie not set")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// RefreshToken тестирует обновление access токена через refresh token
|
cookies := resp.Cookies()
|
||||||
t.Run("RefreshToken", func(t *testing.T) {
|
foundRefreshToken := false
|
||||||
user := config.CreateTestUser(t)
|
for _, cookie := range cookies {
|
||||||
defer config.CleanupTestUser(t, user)
|
if cookie.Name == "refresh_token" {
|
||||||
|
foundRefreshToken = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !foundRefreshToken {
|
||||||
|
t.Error("Refresh token cookie not set")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Логинимся для получения refresh token в cookie
|
t.Run("RefreshToken", func(t *testing.T) {
|
||||||
_, err := config.Request("POST", "/auth/login", map[string]interface{}{
|
user := config.CreateTestUser(t)
|
||||||
"email": user.Email,
|
defer config.CleanupTestUser(t, user)
|
||||||
"password": user.Password,
|
|
||||||
}, "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to login: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обновляем токен
|
loginResp, err := config.Request("POST", "/auth/login", map[string]interface{}{
|
||||||
resp, err := config.Request("POST", "/auth/refresh", nil, "")
|
"email": user.Email,
|
||||||
if err != nil {
|
"password": user.Password,
|
||||||
t.Fatalf("Failed to refresh token: %v", err)
|
}, "")
|
||||||
}
|
if err != nil {
|
||||||
defer resp.Body.Close()
|
t.Fatalf("Failed to login: %v", err)
|
||||||
|
}
|
||||||
|
loginResp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
var refreshToken string
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
for _, cookie := range loginResp.Cookies() {
|
||||||
}
|
if cookie.Name == "refresh_token" {
|
||||||
})
|
refreshToken = cookie.Value
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Logout тестирует выход пользователя из системы
|
resp, err := config.Request("POST", "/auth/refresh", map[string]interface{}{
|
||||||
t.Run("Logout", func(t *testing.T) {
|
"refresh_token": refreshToken,
|
||||||
user := config.CreateTestUser(t)
|
}, "")
|
||||||
defer config.CleanupTestUser(t, user)
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to refresh token: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
resp, err := config.Request("POST", "/auth/logout", nil, user.Token)
|
if resp.StatusCode != 200 {
|
||||||
if err != nil {
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
t.Fatalf("Failed to logout: %v", err)
|
}
|
||||||
}
|
})
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
t.Run("Logout", func(t *testing.T) {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
user := config.CreateTestUser(t)
|
||||||
}
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
var result map[string]interface{}
|
resp, err := config.Request("POST", "/auth/logout", nil, user.Token)
|
||||||
if err := config.ParseResponse(resp, &result); err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to logout: %v", err)
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// Проверяем сообщение о успешном выходе
|
if resp.StatusCode != 200 {
|
||||||
if msg, ok := result["message"]; !ok || msg != "Successfully logged out" {
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
t.Error("Logout message not as expected")
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// PasswordReset тестирует полный поток сброса пароля
|
var result map[string]interface{}
|
||||||
t.Run("PasswordReset", func(t *testing.T) {
|
if err := config.ParseResponse(resp, &result); err != nil {
|
||||||
user := config.CreateTestUser(t)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
defer config.CleanupTestUser(t, user)
|
}
|
||||||
|
|
||||||
// Запрос сброса пароля
|
if msg, ok := result["message"].(string); !ok || msg != "Successfully logged out" {
|
||||||
resp, err := config.Request("POST", "/auth/password-reset/request", map[string]interface{}{
|
t.Error("Logout message not as expected")
|
||||||
"email": user.Email,
|
}
|
||||||
}, "")
|
})
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to request password reset: %v", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
t.Run("PasswordReset", func(t *testing.T) {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
user := config.CreateTestUser(t)
|
||||||
}
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
var result map[string]interface{}
|
resp, err := config.Request("POST", "/auth/reset-password", map[string]interface{}{
|
||||||
if err := config.ParseResponse(resp, &result); err != nil {
|
"email": user.Email,
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
}, "")
|
||||||
}
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to request password reset: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// Получаем токен сброса из ответа (в реальном API он приходит на email)
|
if resp.StatusCode != 200 {
|
||||||
resetToken, ok := result["token"].(string)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
if !ok {
|
}
|
||||||
t.Fatal("Reset token not found in response")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Подтверждение сброса пароля с новым паролем
|
var result map[string]interface{}
|
||||||
newPassword := "newpassword789"
|
if err := config.ParseResponse(resp, &result); err != nil {
|
||||||
resp, err = config.Request("POST", "/auth/password-reset/confirm", map[string]interface{}{
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
"token": resetToken,
|
}
|
||||||
"new_password": newPassword,
|
|
||||||
}, "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to confirm password reset: %v", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
resetToken, ok := result["token"].(string)
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
if !ok {
|
||||||
}
|
t.Fatal("Reset token not found in response")
|
||||||
|
}
|
||||||
|
|
||||||
// Проверяем, что можно войти с новым паролем
|
newPassword := "newpassword789"
|
||||||
newToken, err := config.GetAuthToken(user.Email, newPassword)
|
resp, err = config.Request("POST", "/auth/reset-password/confirm", map[string]interface{}{
|
||||||
if err != nil {
|
"token": resetToken,
|
||||||
t.Errorf("Failed to login with new password: %v", err)
|
"new_password": newPassword,
|
||||||
}
|
}, "")
|
||||||
if newToken == "" {
|
if err != nil {
|
||||||
t.Error("Failed to get token with new password")
|
t.Fatalf("Failed to confirm password reset: %v", err)
|
||||||
}
|
}
|
||||||
})
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// MobileLogin тестирует мобильную авторизацию (возвращает access и refresh токены)
|
if resp.StatusCode != 200 {
|
||||||
t.Run("MobileLogin", func(t *testing.T) {
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
user := config.CreateTestUser(t)
|
}
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
resp, err := config.Request("POST", "/auth/mobile/login", map[string]interface{}{
|
newToken, err := config.GetAuthToken(user.Email, newPassword)
|
||||||
"email": user.Email,
|
if err != nil {
|
||||||
"password": user.Password,
|
t.Errorf("Failed to login with new password: %v", err)
|
||||||
}, "")
|
}
|
||||||
if err != nil {
|
if newToken == "" {
|
||||||
t.Fatalf("Failed to mobile login: %v", err)
|
t.Error("Failed to get token with new password")
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
})
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
t.Run("MobileLogin", func(t *testing.T) {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
user := config.CreateTestUser(t)
|
||||||
}
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
var result map[string]interface{}
|
resp, err := config.Request("POST", "/auth/mobile/login", map[string]interface{}{
|
||||||
if err := config.ParseResponse(resp, &result); err != nil {
|
"email": user.Email,
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
"password": user.Password,
|
||||||
}
|
}, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to mobile login: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// Для мобильной авторизации ожидаем специальные поля
|
if resp.StatusCode != 200 {
|
||||||
requiredFields := []string{"access_token", "refresh_token", "expires_at", "user"}
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
for _, field := range requiredFields {
|
}
|
||||||
if _, ok := result[field]; !ok {
|
|
||||||
t.Errorf("Required field %s not found in response", field)
|
var result map[string]interface{}
|
||||||
}
|
if err := config.ParseResponse(resp, &result); err != nil {
|
||||||
}
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
})
|
}
|
||||||
}
|
|
||||||
|
requiredFields := []string{"access_token", "refresh_token", "expires_at", "user"}
|
||||||
|
for _, field := range requiredFields {
|
||||||
|
if _, ok := result[field]; !ok {
|
||||||
|
t.Errorf("Required field %s not found in response", field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,235 +1,221 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"fmt"
|
||||||
"api_yal/tests/testutils"
|
"testing"
|
||||||
|
"api_yal/tests/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestCommentEndpoints тестирует все эндпоинты для работы с комментариями к отзывам
|
|
||||||
// Включает создание, получение, обновление, удаление комментариев и получение статистики
|
|
||||||
func TestCommentEndpoints(t *testing.T) {
|
func TestCommentEndpoints(t *testing.T) {
|
||||||
config := testutils.NewTestConfig()
|
config := testutils.NewTestConfig()
|
||||||
|
|
||||||
// CreateComment тестирует создание нового комментария к отзыву
|
t.Run("CreateComment", func(t *testing.T) {
|
||||||
t.Run("CreateComment", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
||||||
|
|
||||||
commentData := testutils.CreateCommentRequest{
|
commentData := testutils.CreateCommentRequest{
|
||||||
FeedbackID: feedbackID,
|
FeedbackID: feedbackID,
|
||||||
Text: "Great review! I agree completely.",
|
Text: "Great review! I agree completely.",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := config.Request("POST", "/comments", commentData, user.Token)
|
resp, err := config.Request("POST", "/comments", commentData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create comment: %v", err)
|
t.Fatalf("Failed to create comment: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 201 {
|
if resp.StatusCode != 201 {
|
||||||
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var createdComment map[string]interface{}
|
var createdComment map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdComment); err != nil {
|
if err := config.ParseResponse(resp, &createdComment); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := createdComment["id"]; !ok {
|
if _, ok := createdComment["id"]; !ok {
|
||||||
t.Error("Comment ID not found")
|
t.Error("Comment ID not found")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// GetCommentByID тестирует получение комментария по ID
|
t.Run("GetCommentByID", func(t *testing.T) {
|
||||||
t.Run("GetCommentByID", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
||||||
|
|
||||||
// Создаем комментарий
|
commentData := testutils.CreateCommentRequest{
|
||||||
commentData := testutils.CreateCommentRequest{
|
FeedbackID: feedbackID,
|
||||||
FeedbackID: feedbackID,
|
Text: "Test comment",
|
||||||
Text: "Test comment",
|
}
|
||||||
}
|
resp, err := config.Request("POST", "/comments", commentData, user.Token)
|
||||||
resp, err := config.Request("POST", "/comments", commentData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create comment: %v", err)
|
||||||
t.Fatalf("Failed to create comment: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var createdComment map[string]interface{}
|
var createdComment map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdComment); err != nil {
|
if err := config.ParseResponse(resp, &createdComment); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commentID := createdComment["id"].(float64)
|
commentID := createdComment["id"].(float64)
|
||||||
|
|
||||||
// Получение комментария доступно без авторизации
|
getResp, err := config.Request("GET", "/comments/"+fmt.Sprintf("%.0f", commentID), nil, "")
|
||||||
getResp, err := config.Request("GET", "/comments/"+string(rune(commentID)), nil, "")
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to get comment: %v", err)
|
||||||
t.Fatalf("Failed to get comment: %v", err)
|
}
|
||||||
}
|
defer getResp.Body.Close()
|
||||||
defer getResp.Body.Close()
|
|
||||||
|
|
||||||
if getResp.StatusCode != 200 {
|
if getResp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", getResp.StatusCode)
|
t.Errorf("Expected status 200, got %d", getResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// UpdateComment тестирует обновление текста комментария автором
|
t.Run("UpdateComment", func(t *testing.T) {
|
||||||
t.Run("UpdateComment", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
||||||
|
|
||||||
// Создаем комментарий
|
commentData := testutils.CreateCommentRequest{
|
||||||
commentData := testutils.CreateCommentRequest{
|
FeedbackID: feedbackID,
|
||||||
FeedbackID: feedbackID,
|
Text: "Original comment",
|
||||||
Text: "Original comment",
|
}
|
||||||
}
|
resp, err := config.Request("POST", "/comments", commentData, user.Token)
|
||||||
resp, err := config.Request("POST", "/comments", commentData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create comment: %v", err)
|
||||||
t.Fatalf("Failed to create comment: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var createdComment map[string]interface{}
|
var createdComment map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdComment); err != nil {
|
if err := config.ParseResponse(resp, &createdComment); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commentID := createdComment["id"].(float64)
|
commentID := createdComment["id"].(float64)
|
||||||
|
|
||||||
updateData := map[string]interface{}{
|
updateData := map[string]interface{}{
|
||||||
"text": "Updated comment text",
|
"text": "Updated comment text",
|
||||||
}
|
}
|
||||||
|
|
||||||
updateResp, err := config.Request("PUT", "/comments/"+string(rune(commentID)), updateData, user.Token)
|
updateResp, err := config.Request("PUT", "/comments/"+fmt.Sprintf("%.0f", commentID), updateData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to update comment: %v", err)
|
t.Fatalf("Failed to update comment: %v", err)
|
||||||
}
|
}
|
||||||
defer updateResp.Body.Close()
|
defer updateResp.Body.Close()
|
||||||
|
|
||||||
if updateResp.StatusCode != 200 {
|
if updateResp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", updateResp.StatusCode)
|
t.Errorf("Expected status 200, got %d", updateResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// ListComments тестирует получение списка комментариев с пагинацией
|
t.Run("ListComments", func(t *testing.T) {
|
||||||
t.Run("ListComments", func(t *testing.T) {
|
resp, err := config.Request("GET", "/comments?page=1&page_size=20", nil, "")
|
||||||
resp, err := config.Request("GET", "/comments?page=1&page_size=20", nil, "")
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to list comments: %v", err)
|
||||||
t.Fatalf("Failed to list comments: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// MyComments тестирует получение комментариев текущего пользователя
|
t.Run("MyComments", func(t *testing.T) {
|
||||||
t.Run("MyComments", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/comments/my", nil, user.Token)
|
resp, err := config.Request("GET", "/comments/my", nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get my comments: %v", err)
|
t.Fatalf("Failed to get my comments: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// CommentsByFeedback тестирует получение комментариев для конкретного отзыва
|
t.Run("CommentsByFeedback", func(t *testing.T) {
|
||||||
t.Run("CommentsByFeedback", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/comments/feedback/"+string(rune(feedbackID)), nil, "")
|
resp, err := config.Request("GET", "/comments/feedback/"+fmt.Sprintf("%d", feedbackID), nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get comments by feedback: %v", err)
|
t.Fatalf("Failed to get comments by feedback: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// CommentStats тестирует получение статистики по комментариям
|
t.Run("CommentStats", func(t *testing.T) {
|
||||||
t.Run("CommentStats", func(t *testing.T) {
|
resp, err := config.Request("GET", "/comments/stats", nil, "")
|
||||||
resp, err := config.Request("GET", "/comments/stats", nil, "")
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to get comment stats: %v", err)
|
||||||
t.Fatalf("Failed to get comment stats: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var stats map[string]interface{}
|
var stats map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &stats); err != nil {
|
if err := config.ParseResponse(resp, &stats); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем наличие полей статистики
|
expectedFields := []string{"total_comments", "verified_comments", "unverified_comments"}
|
||||||
expectedFields := []string{"total_comments", "verified_comments", "unverified_comments"}
|
for _, field := range expectedFields {
|
||||||
for _, field := range expectedFields {
|
if _, ok := stats[field]; !ok {
|
||||||
if _, ok := stats[field]; !ok {
|
t.Errorf("Expected field %s not found", field)
|
||||||
t.Errorf("Expected field %s not found", field)
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
// DeleteComment тестирует удаление комментария автором
|
t.Run("DeleteComment", func(t *testing.T) {
|
||||||
t.Run("DeleteComment", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
||||||
|
|
||||||
// Создаем комментарий
|
commentData := testutils.CreateCommentRequest{
|
||||||
commentData := testutils.CreateCommentRequest{
|
FeedbackID: feedbackID,
|
||||||
FeedbackID: feedbackID,
|
Text: "Comment to delete",
|
||||||
Text: "Comment to delete",
|
}
|
||||||
}
|
resp, err := config.Request("POST", "/comments", commentData, user.Token)
|
||||||
resp, err := config.Request("POST", "/comments", commentData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create comment: %v", err)
|
||||||
t.Fatalf("Failed to create comment: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var createdComment map[string]interface{}
|
var createdComment map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdComment); err != nil {
|
if err := config.ParseResponse(resp, &createdComment); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commentID := createdComment["id"].(float64)
|
commentID := createdComment["id"].(float64)
|
||||||
|
|
||||||
deleteResp, err := config.Request("DELETE", "/comments/"+string(rune(commentID)), nil, user.Token)
|
deleteResp, err := config.Request("DELETE", "/comments/"+fmt.Sprintf("%.0f", commentID), nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to delete comment: %v", err)
|
t.Fatalf("Failed to delete comment: %v", err)
|
||||||
}
|
}
|
||||||
defer deleteResp.Body.Close()
|
defer deleteResp.Body.Close()
|
||||||
|
|
||||||
if deleteResp.StatusCode != 200 {
|
if deleteResp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", deleteResp.StatusCode)
|
t.Errorf("Expected status 200, got %d", deleteResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,231 +1,217 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"fmt"
|
||||||
"api_yal/tests/testutils"
|
"testing"
|
||||||
|
"api_yal/tests/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestFeedbackEndpoints тестирует все эндпоинты для работы с отзывами
|
|
||||||
// Включает создание, получение, обновление, удаление отзывов, поиск и статистику
|
|
||||||
func TestFeedbackEndpoints(t *testing.T) {
|
func TestFeedbackEndpoints(t *testing.T) {
|
||||||
config := testutils.NewTestConfig()
|
config := testutils.NewTestConfig()
|
||||||
|
|
||||||
// CreateFeedback тестирует создание нового отзыва
|
t.Run("CreateFeedback", func(t *testing.T) {
|
||||||
t.Run("CreateFeedback", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
feedbackData := testutils.CreateFeedbackRequest{
|
feedbackData := testutils.CreateFeedbackRequest{
|
||||||
ObjectID: objectID,
|
ObjectID: objectID,
|
||||||
Rating: 5,
|
Rating: 5,
|
||||||
Text: "Excellent place! Very recommended.",
|
Text: "Excellent place! Very recommended.",
|
||||||
Platform: "tourist",
|
Platform: "tourist",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := config.Request("POST", "/feedbacks", feedbackData, user.Token)
|
resp, err := config.Request("POST", "/feedbacks", feedbackData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create feedback: %v", err)
|
t.Fatalf("Failed to create feedback: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 201 {
|
if resp.StatusCode != 201 {
|
||||||
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var createdFeedback map[string]interface{}
|
var createdFeedback map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdFeedback); err != nil {
|
if err := config.ParseResponse(resp, &createdFeedback); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := createdFeedback["id"]; !ok {
|
if _, ok := createdFeedback["id"]; !ok {
|
||||||
t.Error("Feedback ID not found")
|
t.Error("Feedback ID not found")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// GetFeedbackByID тестирует получение отзыва по ID
|
t.Run("GetFeedbackByID", func(t *testing.T) {
|
||||||
t.Run("GetFeedbackByID", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/feedbacks/"+string(rune(feedbackID)), nil, "")
|
resp, err := config.Request("GET", "/feedbacks/"+fmt.Sprintf("%d", feedbackID), nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get feedback: %v", err)
|
t.Fatalf("Failed to get feedback: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// UpdateFeedback тестирует обновление отзыва автором
|
t.Run("UpdateFeedback", func(t *testing.T) {
|
||||||
t.Run("UpdateFeedback", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
||||||
|
|
||||||
updateData := map[string]interface{}{
|
updateData := map[string]interface{}{
|
||||||
"rating": 4,
|
"rating": 4,
|
||||||
"text": "Updated feedback text",
|
"text": "Updated feedback text",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := config.Request("PUT", "/feedbacks/"+string(rune(feedbackID)), updateData, user.Token)
|
resp, err := config.Request("PUT", "/feedbacks/"+fmt.Sprintf("%d", feedbackID), updateData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to update feedback: %v", err)
|
t.Fatalf("Failed to update feedback: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var updatedFeedback map[string]interface{}
|
var updatedFeedback map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &updatedFeedback); err != nil {
|
if err := config.ParseResponse(resp, &updatedFeedback); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if text, ok := updatedFeedback["text"].(string); !ok || text != "Updated feedback text" {
|
if text, ok := updatedFeedback["text"].(string); !ok || text != "Updated feedback text" {
|
||||||
t.Error("Feedback text not updated")
|
t.Error("Feedback text not updated")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// ListFeedbacks тестирует получение списка отзывов с пагинацией
|
t.Run("ListFeedbacks", func(t *testing.T) {
|
||||||
t.Run("ListFeedbacks", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/feedbacks?offset=0&limit=20", nil, "")
|
resp, err := config.Request("GET", "/feedbacks?offset=0&limit=20", nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to list feedbacks: %v", err)
|
t.Fatalf("Failed to list feedbacks: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// MyFeedbacks тестирует получение отзывов текущего пользователя
|
t.Run("MyFeedbacks", func(t *testing.T) {
|
||||||
t.Run("MyFeedbacks", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/feedbacks/my", nil, user.Token)
|
resp, err := config.Request("GET", "/feedbacks/my", nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get my feedbacks: %v", err)
|
t.Fatalf("Failed to get my feedbacks: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// FeedbacksByObject тестирует получение отзывов для конкретного объекта
|
t.Run("FeedbacksByObject", func(t *testing.T) {
|
||||||
t.Run("FeedbacksByObject", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/feedbacks/object/"+string(rune(objectID)), nil, "")
|
resp, err := config.Request("GET", "/feedbacks/object/"+fmt.Sprintf("%d", objectID), nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get object feedbacks: %v", err)
|
t.Fatalf("Failed to get object feedbacks: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// FeedbacksByPlatform тестирует получение отзывов по платформе
|
t.Run("FeedbacksByPlatform", func(t *testing.T) {
|
||||||
t.Run("FeedbacksByPlatform", func(t *testing.T) {
|
resp, err := config.Request("GET", "/feedbacks/platform/tourist", nil, "")
|
||||||
resp, err := config.Request("GET", "/feedbacks/platform/tourist", nil, "")
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to get platform feedbacks: %v", err)
|
||||||
t.Fatalf("Failed to get platform feedbacks: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// SearchFeedbacks тестирует поиск отзывов по тексту
|
t.Run("SearchFeedbacks", func(t *testing.T) {
|
||||||
t.Run("SearchFeedbacks", func(t *testing.T) {
|
resp, err := config.Request("GET", "/feedbacks/search?q=excellent", nil, "")
|
||||||
resp, err := config.Request("GET", "/feedbacks/search?q=excellent", nil, "")
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to search feedbacks: %v", err)
|
||||||
t.Fatalf("Failed to search feedbacks: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// FeedbackStats тестирует получение статистики по отзывам
|
t.Run("FeedbackStats", func(t *testing.T) {
|
||||||
t.Run("FeedbackStats", func(t *testing.T) {
|
resp, err := config.Request("GET", "/feedbacks/stats", nil, "")
|
||||||
resp, err := config.Request("GET", "/feedbacks/stats", nil, "")
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to get feedback stats: %v", err)
|
||||||
t.Fatalf("Failed to get feedback stats: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var stats map[string]interface{}
|
var stats map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &stats); err != nil {
|
if err := config.ParseResponse(resp, &stats); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем наличие полей статистики
|
expectedFields := []string{"total_feedbacks", "average_rating", "rating_distribution", "platform_stats"}
|
||||||
expectedFields := []string{"total_feedbacks", "average_rating", "rating_distribution", "platform_stats"}
|
for _, field := range expectedFields {
|
||||||
for _, field := range expectedFields {
|
if _, ok := stats[field]; !ok {
|
||||||
if _, ok := stats[field]; !ok {
|
t.Errorf("Expected field %s not found", field)
|
||||||
t.Errorf("Expected field %s not found", field)
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
// DeleteFeedback тестирует удаление отзыва
|
t.Run("DeleteFeedback", func(t *testing.T) {
|
||||||
t.Run("DeleteFeedback", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
feedbackID := config.CreateTestFeedback(t, user.Token, objectID)
|
||||||
|
|
||||||
resp, err := config.Request("DELETE", "/feedbacks/"+string(rune(feedbackID)), nil, user.Token)
|
resp, err := config.Request("DELETE", "/feedbacks/"+fmt.Sprintf("%d", feedbackID), nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to delete feedback: %v", err)
|
t.Fatalf("Failed to delete feedback: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// Ожидаем статус 204 No Content при успешном удалении
|
if resp.StatusCode != 204 {
|
||||||
if resp.StatusCode != 204 {
|
t.Errorf("Expected status 204, got %d", resp.StatusCode)
|
||||||
t.Errorf("Expected status 204, got %d", resp.StatusCode)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Проверяем, что отзыв удален - должен вернуть 404
|
getResp, err := config.Request("GET", "/feedbacks/"+fmt.Sprintf("%d", feedbackID), nil, "")
|
||||||
getResp, err := config.Request("GET", "/feedbacks/"+string(rune(feedbackID)), nil, "")
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to get feedback: %v", err)
|
||||||
t.Fatalf("Failed to get feedback: %v", err)
|
}
|
||||||
}
|
defer getResp.Body.Close()
|
||||||
defer getResp.Body.Close()
|
|
||||||
|
|
||||||
if getResp.StatusCode != 404 {
|
if getResp.StatusCode != 404 {
|
||||||
t.Errorf("Expected status 404 for deleted feedback, got %d", getResp.StatusCode)
|
t.Errorf("Expected status 404 for deleted feedback, got %d", getResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"api_yal/tests/testutils"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"api_yal/tests/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestObjectEndpoints тестирует все эндпоинты для работы с объектами (местами, заведениями)
|
|
||||||
// Включает создание, получение, обновление, удаление объектов, поиск и геопоиск
|
|
||||||
func TestObjectEndpoints(t *testing.T) {
|
func TestObjectEndpoints(t *testing.T) {
|
||||||
config := testutils.NewTestConfig()
|
config := testutils.NewTestConfig()
|
||||||
|
|
||||||
// CreateObject тестирует создание нового объекта пользователем
|
|
||||||
t.Run("CreateObject", func(t *testing.T) {
|
t.Run("CreateObject", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
@@ -55,14 +53,13 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// GetObjectByID тестирует получение объекта по ID
|
|
||||||
t.Run("GetObjectByID", func(t *testing.T) {
|
t.Run("GetObjectByID", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/objects/"+string(rune(objectID)), nil, "")
|
resp, err := config.Request("GET", "/objects/"+fmt.Sprintf("%d", objectID), nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get object: %v", err)
|
t.Fatalf("Failed to get object: %v", err)
|
||||||
}
|
}
|
||||||
@@ -82,7 +79,6 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// GetNonExistentObject тестирует получение несуществующего объекта
|
|
||||||
t.Run("GetNonExistentObject", func(t *testing.T) {
|
t.Run("GetNonExistentObject", func(t *testing.T) {
|
||||||
resp, err := config.Request("GET", "/objects/999999", nil, "")
|
resp, err := config.Request("GET", "/objects/999999", nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -95,7 +91,6 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// UpdateObject тестирует обновление объекта его владельцем
|
|
||||||
t.Run("UpdateObject", func(t *testing.T) {
|
t.Run("UpdateObject", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
@@ -108,7 +103,7 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
"short_description": "Updated short desc",
|
"short_description": "Updated short desc",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := config.Request("PUT", "/objects/"+string(rune(objectID)), updateData, user.Token)
|
resp, err := config.Request("PUT", "/objects/"+fmt.Sprintf("%d", objectID), updateData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to update object: %v", err)
|
t.Fatalf("Failed to update object: %v", err)
|
||||||
}
|
}
|
||||||
@@ -128,7 +123,6 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// UpdateObjectUnauthorized тестирует попытку обновления чужого объекта
|
|
||||||
t.Run("UpdateObjectUnauthorized", func(t *testing.T) {
|
t.Run("UpdateObjectUnauthorized", func(t *testing.T) {
|
||||||
user1 := config.CreateTestUser(t)
|
user1 := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user1)
|
defer config.CleanupTestUser(t, user1)
|
||||||
@@ -138,8 +132,7 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
|
|
||||||
objectID := config.CreateTestObject(t, user1.Token)
|
objectID := config.CreateTestObject(t, user1.Token)
|
||||||
|
|
||||||
// Пользователь user2 пытается обновить объект user1
|
resp, err := config.Request("PUT", "/objects/"+fmt.Sprintf("%d", objectID), map[string]interface{}{
|
||||||
resp, err := config.Request("PUT", "/objects/"+string(rune(objectID)), map[string]interface{}{
|
|
||||||
"short_name": "Hacked Name",
|
"short_name": "Hacked Name",
|
||||||
}, user2.Token)
|
}, user2.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -147,18 +140,15 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
// Ожидаем ошибку 403 Forbidden
|
|
||||||
if resp.StatusCode != 403 {
|
if resp.StatusCode != 403 {
|
||||||
t.Errorf("Expected status 403, got %d", resp.StatusCode)
|
t.Errorf("Expected status 403, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// ListObjects тестирует получение списка объектов с пагинацией
|
|
||||||
t.Run("ListObjects", func(t *testing.T) {
|
t.Run("ListObjects", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
// Создаем несколько объектов
|
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
config.CreateTestObject(t, user.Token)
|
config.CreateTestObject(t, user.Token)
|
||||||
}
|
}
|
||||||
@@ -183,12 +173,11 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// SearchObjects тестирует поиск объектов по тексту
|
|
||||||
t.Run("SearchObjects", func(t *testing.T) {
|
t.Run("SearchObjects", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
resp, err := config.Request("GET", "/objects/search?q=Test", nil, "")
|
resp, err := config.Request("GET", "/objects/search?q=Test", nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -206,10 +195,8 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Search results: %+v", searchResults)
|
t.Logf("Search results: %+v", searchResults)
|
||||||
_ = objectID // Используем переменную для избежания предупреждения
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// NearbyObjects тестирует поиск объектов рядом с заданными координатами
|
|
||||||
t.Run("NearbyObjects", func(t *testing.T) {
|
t.Run("NearbyObjects", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
@@ -225,14 +212,13 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// DeleteObject тестирует удаление объекта
|
|
||||||
t.Run("DeleteObject", func(t *testing.T) {
|
t.Run("DeleteObject", func(t *testing.T) {
|
||||||
user := config.CreateTestUser(t)
|
user := config.CreateTestUser(t)
|
||||||
defer config.CleanupTestUser(t, user)
|
defer config.CleanupTestUser(t, user)
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
resp, err := config.Request("DELETE", "/objects/"+string(rune(objectID)), nil, user.Token)
|
resp, err := config.Request("DELETE", "/objects/"+fmt.Sprintf("%d", objectID), nil, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to delete object: %v", err)
|
t.Fatalf("Failed to delete object: %v", err)
|
||||||
}
|
}
|
||||||
@@ -242,8 +228,7 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
t.Errorf("Expected status 204, got %d", resp.StatusCode)
|
t.Errorf("Expected status 204, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, что объект удален - должен вернуть 404
|
getResp, err := config.Request("GET", "/objects/"+fmt.Sprintf("%d", objectID), nil, "")
|
||||||
getResp, err := config.Request("GET", "/objects/"+string(rune(objectID)), nil, "")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get object: %v", err)
|
t.Fatalf("Failed to get object: %v", err)
|
||||||
}
|
}
|
||||||
@@ -253,4 +238,4 @@ func TestObjectEndpoints(t *testing.T) {
|
|||||||
t.Errorf("Expected status 404 for deleted object, got %d", getResp.StatusCode)
|
t.Errorf("Expected status 404 for deleted object, got %d", getResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,251 +1,233 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"fmt"
|
||||||
"api_yal/tests/testutils"
|
"testing"
|
||||||
|
"api_yal/tests/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestRatingEndpoints тестирует все эндпоинты для работы с рейтингами и голосованием
|
|
||||||
// Включает создание рейтинга, голосование, изменение голоса и получение статистики
|
|
||||||
func TestRatingEndpoints(t *testing.T) {
|
func TestRatingEndpoints(t *testing.T) {
|
||||||
config := testutils.NewTestConfig()
|
config := testutils.NewTestConfig()
|
||||||
|
|
||||||
// CreateRating тестирует создание нового рейтинга для объекта
|
t.Run("CreateRating", func(t *testing.T) {
|
||||||
t.Run("CreateRating", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
ratingData := map[string]interface{}{
|
ratingData := map[string]interface{}{
|
||||||
"object_id": objectID,
|
"object_id": objectID,
|
||||||
"platform": "tourist",
|
"platform": "tourist",
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create rating: %v", err)
|
t.Fatalf("Failed to create rating: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 201 {
|
if resp.StatusCode != 201 {
|
||||||
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
t.Errorf("Expected status 201, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// CastVote тестирует голосование в рейтинге
|
t.Run("CastVote", func(t *testing.T) {
|
||||||
t.Run("CastVote", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
// Сначала создаем рейтинг
|
ratingData := map[string]interface{}{
|
||||||
ratingData := map[string]interface{}{
|
"object_id": objectID,
|
||||||
"object_id": objectID,
|
"platform": "tourist",
|
||||||
"platform": "tourist",
|
}
|
||||||
}
|
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
||||||
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create rating: %v", err)
|
||||||
t.Fatalf("Failed to create rating: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var createdRating map[string]interface{}
|
var createdRating map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdRating); err != nil {
|
if err := config.ParseResponse(resp, &createdRating); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ratingID := createdRating["id"].(float64)
|
ratingID := createdRating["id"].(float64)
|
||||||
|
|
||||||
// Голосуем с оценкой 5
|
voteData := map[string]interface{}{
|
||||||
voteData := map[string]interface{}{
|
"score": 5,
|
||||||
"score": 5,
|
}
|
||||||
}
|
|
||||||
|
|
||||||
voteResp, err := config.Request("POST", "/ratings/"+string(rune(ratingID))+"/vote/tourist", voteData, user.Token)
|
voteResp, err := config.Request("POST", "/ratings/"+fmt.Sprintf("%.0f", ratingID)+"/vote/tourist", voteData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to cast vote: %v", err)
|
t.Fatalf("Failed to cast vote: %v", err)
|
||||||
}
|
}
|
||||||
defer voteResp.Body.Close()
|
defer voteResp.Body.Close()
|
||||||
|
|
||||||
if voteResp.StatusCode != 200 {
|
if voteResp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", voteResp.StatusCode)
|
t.Errorf("Expected status 200, got %d", voteResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// GetMyVote тестирует получение голоса текущего пользователя
|
t.Run("GetMyVote", func(t *testing.T) {
|
||||||
t.Run("GetMyVote", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
// Создаем рейтинг и голосуем
|
ratingData := map[string]interface{}{
|
||||||
ratingData := map[string]interface{}{
|
"object_id": objectID,
|
||||||
"object_id": objectID,
|
"platform": "tourist",
|
||||||
"platform": "tourist",
|
}
|
||||||
}
|
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
||||||
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to create rating: %v", err)
|
||||||
t.Fatalf("Failed to create rating: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var createdRating map[string]interface{}
|
var createdRating map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdRating); err != nil {
|
if err := config.ParseResponse(resp, &createdRating); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ratingID := createdRating["id"].(float64)
|
ratingID := createdRating["id"].(float64)
|
||||||
|
|
||||||
voteData := map[string]interface{}{
|
voteData := map[string]interface{}{
|
||||||
"score": 5,
|
"score": 5,
|
||||||
}
|
}
|
||||||
_, err = config.Request("POST", "/ratings/"+string(rune(ratingID))+"/vote/tourist", voteData, user.Token)
|
_, err = config.Request("POST", "/ratings/"+fmt.Sprintf("%.0f", ratingID)+"/vote/tourist", voteData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to cast vote: %v", err)
|
t.Fatalf("Failed to cast vote: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Получаем мой голос
|
myVoteResp, err := config.Request("GET", "/ratings/"+fmt.Sprintf("%.0f", ratingID)+"/my-vote/tourist", nil, user.Token)
|
||||||
myVoteResp, err := config.Request("GET", "/ratings/"+string(rune(ratingID))+"/my-vote/tourist", nil, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to get my vote: %v", err)
|
||||||
t.Fatalf("Failed to get my vote: %v", err)
|
}
|
||||||
}
|
defer myVoteResp.Body.Close()
|
||||||
defer myVoteResp.Body.Close()
|
|
||||||
|
|
||||||
if myVoteResp.StatusCode != 200 {
|
if myVoteResp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", myVoteResp.StatusCode)
|
t.Errorf("Expected status 200, got %d", myVoteResp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var voteInfo map[string]interface{}
|
var voteInfo map[string]interface{}
|
||||||
if err := config.ParseResponse(myVoteResp, &voteInfo); err != nil {
|
if err := config.ParseResponse(myVoteResp, &voteInfo); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, что пользователь уже голосовал
|
if hasVoted, ok := voteInfo["has_voted"].(bool); !ok || !hasVoted {
|
||||||
if hasVoted, ok := voteInfo["has_voted"].(bool); !ok || !hasVoted {
|
t.Error("has_voted should be true")
|
||||||
t.Error("has_voted should be true")
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
// UpdateMyVote тестирует обновление голоса пользователя
|
t.Run("UpdateMyVote", func(t *testing.T) {
|
||||||
t.Run("UpdateMyVote", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
ratingData := map[string]interface{}{
|
ratingData := map[string]interface{}{
|
||||||
"object_id": objectID,
|
"object_id": objectID,
|
||||||
"platform": "tourist",
|
"platform": "tourist",
|
||||||
}
|
}
|
||||||
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create rating: %v", err)
|
t.Fatalf("Failed to create rating: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var createdRating map[string]interface{}
|
var createdRating map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdRating); err != nil {
|
if err := config.ParseResponse(resp, &createdRating); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ratingID := createdRating["id"].(float64)
|
ratingID := createdRating["id"].(float64)
|
||||||
|
|
||||||
// Голосуем
|
voteData := map[string]interface{}{
|
||||||
voteData := map[string]interface{}{
|
"score": 5,
|
||||||
"score": 5,
|
}
|
||||||
}
|
_, err = config.Request("POST", "/ratings/"+fmt.Sprintf("%.0f", ratingID)+"/vote/tourist", voteData, user.Token)
|
||||||
_, err = config.Request("POST", "/ratings/"+string(rune(ratingID))+"/vote/tourist", voteData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to cast vote: %v", err)
|
||||||
t.Fatalf("Failed to cast vote: %v", err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Обновляем голос с оценки 5 на 4
|
updateData := map[string]interface{}{
|
||||||
updateData := map[string]interface{}{
|
"score": 4,
|
||||||
"score": 4,
|
}
|
||||||
}
|
updateResp, err := config.Request("PUT", "/ratings/"+fmt.Sprintf("%.0f", ratingID)+"/my-vote/tourist", updateData, user.Token)
|
||||||
updateResp, err := config.Request("PUT", "/ratings/"+string(rune(ratingID))+"/my-vote/tourist", updateData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to update vote: %v", err)
|
||||||
t.Fatalf("Failed to update vote: %v", err)
|
}
|
||||||
}
|
defer updateResp.Body.Close()
|
||||||
defer updateResp.Body.Close()
|
|
||||||
|
|
||||||
if updateResp.StatusCode != 200 {
|
if updateResp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", updateResp.StatusCode)
|
t.Errorf("Expected status 200, got %d", updateResp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// GetRatingStats тестирует получение статистики по рейтингам
|
t.Run("GetRatingStats", func(t *testing.T) {
|
||||||
t.Run("GetRatingStats", func(t *testing.T) {
|
resp, err := config.Request("GET", "/ratings/stats", nil, "")
|
||||||
resp, err := config.Request("GET", "/ratings/stats", nil, "")
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to get rating stats: %v", err)
|
||||||
t.Fatalf("Failed to get rating stats: %v", err)
|
}
|
||||||
}
|
defer resp.Body.Close()
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var stats map[string]interface{}
|
var stats map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &stats); err != nil {
|
if err := config.ParseResponse(resp, &stats); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем наличие полей статистики
|
expectedFields := []string{"total_ratings", "total_votes", "platform_distribution"}
|
||||||
expectedFields := []string{"total_ratings", "total_votes", "platform_distribution"}
|
for _, field := range expectedFields {
|
||||||
for _, field := range expectedFields {
|
if _, ok := stats[field]; !ok {
|
||||||
if _, ok := stats[field]; !ok {
|
t.Errorf("Expected field %s not found", field)
|
||||||
t.Errorf("Expected field %s not found", field)
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
// DeleteMyVote тестирует удаление голоса пользователя
|
t.Run("DeleteMyVote", func(t *testing.T) {
|
||||||
t.Run("DeleteMyVote", func(t *testing.T) {
|
user := config.CreateTestUser(t)
|
||||||
user := config.CreateTestUser(t)
|
defer config.CleanupTestUser(t, user)
|
||||||
defer config.CleanupTestUser(t, user)
|
|
||||||
|
|
||||||
objectID := config.CreateTestObject(t, user.Token)
|
objectID := config.CreateTestObject(t, user.Token)
|
||||||
|
|
||||||
ratingData := map[string]interface{}{
|
ratingData := map[string]interface{}{
|
||||||
"object_id": objectID,
|
"object_id": objectID,
|
||||||
"platform": "tourist",
|
"platform": "tourist",
|
||||||
}
|
}
|
||||||
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
resp, err := config.Request("POST", "/ratings", ratingData, user.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create rating: %v", err)
|
t.Fatalf("Failed to create rating: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var createdRating map[string]interface{}
|
var createdRating map[string]interface{}
|
||||||
if err := config.ParseResponse(resp, &createdRating); err != nil {
|
if err := config.ParseResponse(resp, &createdRating); err != nil {
|
||||||
t.Fatalf("Failed to parse response: %v", err)
|
t.Fatalf("Failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ratingID := createdRating["id"].(float64)
|
ratingID := createdRating["id"].(float64)
|
||||||
|
|
||||||
// Голосуем
|
voteData := map[string]interface{}{
|
||||||
voteData := map[string]interface{}{
|
"score": 5,
|
||||||
"score": 5,
|
}
|
||||||
}
|
_, err = config.Request("POST", "/ratings/"+fmt.Sprintf("%.0f", ratingID)+"/vote/tourist", voteData, user.Token)
|
||||||
_, err = config.Request("POST", "/ratings/"+string(rune(ratingID))+"/vote/tourist", voteData, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to cast vote: %v", err)
|
||||||
t.Fatalf("Failed to cast vote: %v", err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Удаляем голос
|
deleteResp, err := config.Request("DELETE", "/ratings/"+fmt.Sprintf("%.0f", ratingID)+"/my-vote/tourist", nil, user.Token)
|
||||||
deleteResp, err := config.Request("DELETE", "/ratings/"+string(rune(ratingID))+"/my-vote/tourist", nil, user.Token)
|
if err != nil {
|
||||||
if err != nil {
|
t.Fatalf("Failed to delete vote: %v", err)
|
||||||
t.Fatalf("Failed to delete vote: %v", err)
|
}
|
||||||
}
|
defer deleteResp.Body.Close()
|
||||||
defer deleteResp.Body.Close()
|
|
||||||
|
|
||||||
// Ожидаем статус 204 No Content при успешном удалении
|
if deleteResp.StatusCode != 204 {
|
||||||
if deleteResp.StatusCode != 204 {
|
t.Errorf("Expected status 204, got %d", deleteResp.StatusCode)
|
||||||
t.Errorf("Expected status 204, got %d", deleteResp.StatusCode)
|
}
|
||||||
}
|
})
|
||||||
})
|
}
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user