diff --git a/main_dc/yalarba/api_yal/test/e2e/api_test.go b/main_dc/yalarba/api_yal/test/e2e/api_test.go new file mode 100644 index 0000000..e69de29 diff --git a/main_dc/yalarba/api_yal/test/fixtures/test_data.go b/main_dc/yalarba/api_yal/test/fixtures/test_data.go new file mode 100644 index 0000000..e69de29 diff --git a/main_dc/yalarba/api_yal/test/intergration/account_intergration_test.go b/main_dc/yalarba/api_yal/test/intergration/account_intergration_test.go new file mode 100644 index 0000000..e69de29 diff --git a/main_dc/yalarba/api_yal/test/intergration/auth_integration_test.go b/main_dc/yalarba/api_yal/test/intergration/auth_integration_test.go new file mode 100644 index 0000000..c669950 --- /dev/null +++ b/main_dc/yalarba/api_yal/test/intergration/auth_integration_test.go @@ -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") +} \ No newline at end of file diff --git a/main_dc/yalarba/api_yal/test/intergration/objects_integration_test.go b/main_dc/yalarba/api_yal/test/intergration/objects_integration_test.go new file mode 100644 index 0000000..36ee382 --- /dev/null +++ b/main_dc/yalarba/api_yal/test/intergration/objects_integration_test.go @@ -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) + } +} \ No newline at end of file diff --git a/main_dc/yalarba/api_yal/test/intergration/setup_test.go b/main_dc/yalarba/api_yal/test/intergration/setup_test.go new file mode 100644 index 0000000..4cbb1bb --- /dev/null +++ b/main_dc/yalarba/api_yal/test/intergration/setup_test.go @@ -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) + } + } +} \ No newline at end of file