On branch main
new file: main_dc/yalarba/api_yal/test/e2e/api_test.go new file: main_dc/yalarba/api_yal/test/fixtures/test_data.go new file: main_dc/yalarba/api_yal/test/intergration/account_intergration_test.go new file: main_dc/yalarba/api_yal/test/intergration/auth_integration_test.go new file: main_dc/yalarba/api_yal/test/intergration/objects_integration_test.go new file: main_dc/yalarba/api_yal/test/intergration/setup_test.go add test files not implemented
This commit is contained in:
@@ -0,0 +1,112 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAuthIntegration_Register(t *testing.T) {
|
||||||
|
// Очищаем БД перед тестом
|
||||||
|
CleanDatabase(t)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
payload map[string]interface{}
|
||||||
|
wantStatus int
|
||||||
|
wantError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Успешная регистрация",
|
||||||
|
payload: map[string]interface{}{
|
||||||
|
"email": "test@example.com",
|
||||||
|
"password": "password123",
|
||||||
|
"name": "Test User",
|
||||||
|
},
|
||||||
|
wantStatus: http.StatusCreated,
|
||||||
|
wantError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Регистрация с существующим email",
|
||||||
|
payload: map[string]interface{}{
|
||||||
|
"email": "test@example.com", // тот же email
|
||||||
|
"password": "password123",
|
||||||
|
"name": "Another User",
|
||||||
|
},
|
||||||
|
wantStatus: http.StatusConflict,
|
||||||
|
wantError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Невалидные данные",
|
||||||
|
payload: map[string]interface{}{
|
||||||
|
"email": "invalid-email",
|
||||||
|
},
|
||||||
|
wantStatus: http.StatusBadRequest,
|
||||||
|
wantError: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
body, _ := json.Marshal(tc.payload)
|
||||||
|
req := httptest.NewRequest("POST", "/api/v1/auth/register", bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
|
TestRouter.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.wantStatus, rr.Code)
|
||||||
|
|
||||||
|
if !tc.wantError {
|
||||||
|
var response map[string]interface{}
|
||||||
|
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Contains(t, response, "user_id")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAuthIntegration_Login(t *testing.T) {
|
||||||
|
CleanDatabase(t)
|
||||||
|
|
||||||
|
// Сначала создаем пользователя
|
||||||
|
registerPayload := map[string]interface{}{
|
||||||
|
"email": "logintest@example.com",
|
||||||
|
"password": "testpass123",
|
||||||
|
"name": "Login Test User",
|
||||||
|
}
|
||||||
|
body, _ := json.Marshal(registerPayload)
|
||||||
|
req := httptest.NewRequest("POST", "/api/v1/auth/register", bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
TestRouter.ServeHTTP(rr, req)
|
||||||
|
assert.Equal(t, http.StatusCreated, rr.Code)
|
||||||
|
|
||||||
|
// Теперь логинимся
|
||||||
|
loginPayload := map[string]interface{}{
|
||||||
|
"email": "logintest@example.com",
|
||||||
|
"password": "testpass123",
|
||||||
|
}
|
||||||
|
body, _ = json.Marshal(loginPayload)
|
||||||
|
req = httptest.NewRequest("POST", "/api/v1/auth/login", bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
rr = httptest.NewRecorder()
|
||||||
|
|
||||||
|
TestRouter.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Проверяем наличие токенов
|
||||||
|
assert.Contains(t, response, "access_token")
|
||||||
|
assert.Contains(t, response, "refresh_token")
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestObjectsIntegration_CreateObject(t *testing.T) {
|
||||||
|
CleanDatabase(t)
|
||||||
|
|
||||||
|
// Сначала создаем пользователя и получаем токен
|
||||||
|
token := createTestUserAndGetToken(t)
|
||||||
|
|
||||||
|
testObject := map[string]interface{}{
|
||||||
|
"name": "Test Object",
|
||||||
|
"description": "Test Description",
|
||||||
|
"latitude": 55.751244,
|
||||||
|
"longitude": 37.618423,
|
||||||
|
"type": "museum",
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := json.Marshal(testObject)
|
||||||
|
req := httptest.NewRequest("POST", "/api/v1/objects", bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("Authorization", "Bearer "+token)
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
|
TestRouter.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusCreated, rr.Code)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, response["id"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestObjectsIntegration_GetNearbyObjects(t *testing.T) {
|
||||||
|
CleanDatabase(t)
|
||||||
|
|
||||||
|
// Создаем тестовые объекты
|
||||||
|
createTestObjects(t)
|
||||||
|
|
||||||
|
req := httptest.NewRequest("GET", "/api/v1/objects/nearby?lat=55.75&lon=37.61&radius=1000", nil)
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
|
TestRouter.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, rr.Code)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
objects, ok := response["objects"].([]interface{})
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.GreaterOrEqual(t, len(objects), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вспомогательные функции
|
||||||
|
func createTestUserAndGetToken(t *testing.T) string {
|
||||||
|
// Регистрация
|
||||||
|
registerPayload := map[string]interface{}{
|
||||||
|
"email": "testuser@example.com",
|
||||||
|
"password": "testpass123",
|
||||||
|
"name": "Test User",
|
||||||
|
}
|
||||||
|
body, _ := json.Marshal(registerPayload)
|
||||||
|
req := httptest.NewRequest("POST", "/api/v1/auth/register", bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
TestRouter.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
// Логин
|
||||||
|
loginPayload := map[string]interface{}{
|
||||||
|
"email": "testuser@example.com",
|
||||||
|
"password": "testpass123",
|
||||||
|
}
|
||||||
|
body, _ = json.Marshal(loginPayload)
|
||||||
|
req = httptest.NewRequest("POST", "/api/v1/auth/login", bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
rr = httptest.NewRecorder()
|
||||||
|
TestRouter.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
json.Unmarshal(rr.Body.Bytes(), &response)
|
||||||
|
return response["access_token"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestObjects(t *testing.T) {
|
||||||
|
objects := []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"name": "Museum 1",
|
||||||
|
"latitude": 55.751244,
|
||||||
|
"longitude": 37.618423,
|
||||||
|
"type": "museum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Park 1",
|
||||||
|
"latitude": 55.755814,
|
||||||
|
"longitude": 37.617635,
|
||||||
|
"type": "park",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, obj := range objects {
|
||||||
|
body, _ := json.Marshal(obj)
|
||||||
|
req := httptest.NewRequest("POST", "/api/v1/objects", bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
TestRouter.ServeHTTP(rr, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/ory/dockertest/v3"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
// Импортируйте ваши модели и конфиги
|
||||||
|
"your_project/internal/config"
|
||||||
|
"your_project/internal/database"
|
||||||
|
"your_project/internal/router"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
TestDB *gorm.DB
|
||||||
|
TestRouter *chi.Mux
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestMain - запускается один раз перед всеми тестами в пакете
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
// Поднимаем PostgreSQL в Docker
|
||||||
|
db, cleanup := setupTestDatabase()
|
||||||
|
TestDB = db
|
||||||
|
|
||||||
|
// Инициализируем роутер с тестовой БД
|
||||||
|
TestRouter = setupTestRouter(TestDB)
|
||||||
|
|
||||||
|
// Запускаем тесты
|
||||||
|
code := m.Run()
|
||||||
|
|
||||||
|
// Очищаем ресурсы
|
||||||
|
cleanup()
|
||||||
|
|
||||||
|
os.Exit(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupTestDatabase() (*gorm.DB, func()) {
|
||||||
|
// Используем dockertest
|
||||||
|
pool, err := dockertest.NewPool("")
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Could not connect to Docker: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запускаем PostgreSQL контейнер
|
||||||
|
resource, err := pool.Run("postgres", "15-alpine", []string{
|
||||||
|
"POSTGRES_PASSWORD=testpass",
|
||||||
|
"POSTGRES_USER=testuser",
|
||||||
|
"POSTGRES_DB=testdb",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Could not start PostgreSQL container: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ждем пока база поднимется
|
||||||
|
var db *gorm.DB
|
||||||
|
if err := pool.Retry(func() error {
|
||||||
|
var err error
|
||||||
|
dsn := fmt.Sprintf("host=localhost port=%s user=testuser password=testpass dbname=testdb sslmode=disable",
|
||||||
|
resource.GetPort("5432/tcp"))
|
||||||
|
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sqlDB, err := db.DB()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return sqlDB.Ping()
|
||||||
|
}); err != nil {
|
||||||
|
panic(fmt.Sprintf("Could not connect to database: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Выполняем миграции (как в вашем main.go)
|
||||||
|
if err := database.MigrateModels(db); err != nil {
|
||||||
|
panic(fmt.Sprintf("Could not migrate: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Очищаем базу после тестов
|
||||||
|
cleanup := func() {
|
||||||
|
if err := pool.Purge(resource); err != nil {
|
||||||
|
fmt.Printf("Could not purge resource: %s\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return db, cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupTestRouter(db *gorm.DB) *chi.Mux {
|
||||||
|
// Инициализируем ваш роутер с тестовой БД
|
||||||
|
appConfig := &config.Config{
|
||||||
|
Environment: "test",
|
||||||
|
AppPort: "8089",
|
||||||
|
// ... другие настройки
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ваша функция настройки роутера
|
||||||
|
return router.SetupRouter(db, appConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вспомогательная функция для очистки таблиц между тестами
|
||||||
|
func CleanDatabase(t *testing.T) {
|
||||||
|
tables := []string{
|
||||||
|
"users",
|
||||||
|
"accounts",
|
||||||
|
"objects",
|
||||||
|
"feedbacks",
|
||||||
|
"comments",
|
||||||
|
"ratings",
|
||||||
|
"appeals",
|
||||||
|
// Добавьте все ваши таблицы
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, table := range tables {
|
||||||
|
if err := TestDB.Exec(fmt.Sprintf("TRUNCATE TABLE %s RESTART IDENTITY CASCADE", table)).Error; err != nil {
|
||||||
|
t.Logf("Warning: could not truncate table %s: %v", table, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user