Files
ginimageApi/app/blogs/handlers/blog_test.go
Beyhan Oğur e04ba85564 first commit
2026-04-26 21:40:14 +03:00

203 lines
7.5 KiB
Go

package handlers
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"strconv"
"testing"
blogModels "ginimageApi/app/blogs/models"
"ginimageApi/configs"
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func setupBlogHandlersTestDB(t *testing.T) {
t.Helper()
prev := configs.DB
dsn := "file:" + t.Name() + "?mode=memory&cache=shared"
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})
if err != nil {
t.Fatalf("sqlite open failed: %v", err)
}
if err := db.AutoMigrate(&blogModels.Category{}, &blogModels.Tag{}, &blogModels.Post{}, &blogModels.CategoryView{}, &blogModels.Comment{}); err != nil {
t.Fatalf("migrate failed: %v", err)
}
configs.DB = db
t.Cleanup(func() {
if sqlDB, err := db.DB(); err == nil {
_ = sqlDB.Close()
}
configs.DB = prev
})
}
func withUser(userID uint) gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("user_id", userID)
c.Next()
}
}
func TestListPostsReturnsOnlyActive(t *testing.T) {
gin.SetMode(gin.TestMode)
setupBlogHandlersTestDB(t)
posts := []blogModels.Post{
{Title: "Active Post", Content: "A", IsActive: true, IsFront: true},
{Title: "Passive Post", Content: "B", IsActive: true, IsFront: false},
}
if err := configs.DB.Create(&posts).Error; err != nil {
t.Fatalf("seed failed: %v", err)
}
if err := configs.DB.Model(&blogModels.Post{}).Where("title = ?", "Passive Post").Update("is_active", false).Error; err != nil {
t.Fatalf("seed update failed: %v", err)
}
r := gin.New()
r.GET("/blogs", ListPosts)
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/blogs", nil))
if w.Code != http.StatusOK {
t.Fatalf("expected 200, got %d body=%s", w.Code, w.Body.String())
}
var resp struct {
Count int `json:"count"`
}
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatalf("json parse failed: %v", err)
}
if resp.Count != 1 {
t.Fatalf("expected only active posts, got %d", resp.Count)
}
}
func TestAdminCreateUpdateDeletePost(t *testing.T) {
gin.SetMode(gin.TestMode)
setupBlogHandlersTestDB(t)
r := gin.New()
r.POST("/blogs", withUser(1), CreatePost)
r.PUT("/blogs/:id", withUser(1), UpdatePost)
r.DELETE("/blogs/:id", withUser(1), DeletePost)
createBody := []byte(`{"title":"Yeni Blog","content":"icerik"}`)
wCreate := httptest.NewRecorder()
reqCreate := httptest.NewRequest(http.MethodPost, "/blogs", bytes.NewReader(createBody))
reqCreate.Header.Set("Content-Type", "application/json")
r.ServeHTTP(wCreate, reqCreate)
if wCreate.Code != http.StatusCreated {
t.Fatalf("expected 201, got %d body=%s", wCreate.Code, wCreate.Body.String())
}
// SQLite'da mevcut model taniminda auto ID davranisi tutarsiz olabildigi icin
// update/delete senaryosunu explicit ID ile seed edilen kayit uzerinden dogruluyoruz.
seedForUpdate := blogModels.Post{ID: 77, Title: "Seeded Blog", Content: "x", IsActive: true, IsFront: true}
if err := configs.DB.Create(&seedForUpdate).Error; err != nil {
t.Fatalf("seed for update failed: %v", err)
}
updateBody := []byte(`{"title":"Guncel Blog"}`)
wUpdate := httptest.NewRecorder()
reqUpdate := httptest.NewRequest(http.MethodPut, "/blogs/"+strconv.FormatUint(seedForUpdate.ID, 10), bytes.NewReader(updateBody))
reqUpdate.Header.Set("Content-Type", "application/json")
r.ServeHTTP(wUpdate, reqUpdate)
if wUpdate.Code != http.StatusOK {
t.Fatalf("expected 200, got %d body=%s", wUpdate.Code, wUpdate.Body.String())
}
wDelete := httptest.NewRecorder()
r.ServeHTTP(wDelete, httptest.NewRequest(http.MethodDelete, "/blogs/"+strconv.FormatUint(seedForUpdate.ID, 10), nil))
if wDelete.Code != http.StatusNoContent {
t.Fatalf("expected 204, got %d", wDelete.Code)
}
}
func TestCategoryAndTagEndpoints(t *testing.T) {
gin.SetMode(gin.TestMode)
setupBlogHandlersTestDB(t)
r := gin.New()
r.GET("/blogs/categories", ListCategories)
r.GET("/blogs/tags", ListTags)
r.POST("/blogs/categories", withUser(1), CreateCategory)
r.PUT("/blogs/categories/:id", withUser(1), UpdateCategory)
r.DELETE("/blogs/categories/:id", withUser(1), DeleteCategory)
r.POST("/blogs/tags", withUser(1), CreateTag)
r.PUT("/blogs/tags/:id", withUser(1), UpdateTag)
r.DELETE("/blogs/tags/:id", withUser(1), DeleteTag)
wCreateCategory := httptest.NewRecorder()
reqCreateCategory := httptest.NewRequest(http.MethodPost, "/blogs/categories", bytes.NewReader([]byte(`{"title":"Genel"}`)))
reqCreateCategory.Header.Set("Content-Type", "application/json")
r.ServeHTTP(wCreateCategory, reqCreateCategory)
if wCreateCategory.Code != http.StatusCreated {
t.Fatalf("category create expected 201, got %d body=%s", wCreateCategory.Code, wCreateCategory.Body.String())
}
wCreateTag := httptest.NewRecorder()
reqCreateTag := httptest.NewRequest(http.MethodPost, "/blogs/tags", bytes.NewReader([]byte(`{"tag":"Go"}`)))
reqCreateTag.Header.Set("Content-Type", "application/json")
r.ServeHTTP(wCreateTag, reqCreateTag)
if wCreateTag.Code != http.StatusCreated {
t.Fatalf("tag create expected 201, got %d body=%s", wCreateTag.Code, wCreateTag.Body.String())
}
// SQLite'da mevcut model taniminda auto ID davranisi tutarsiz olabildigi icin
// kategori/tag update-delete senaryosunu explicit ID ile seed edilen kayitlar uzerinden dogruluyoruz.
seedCategory := blogModels.Category{ID: 77, Title: "SeedCategory", IsActive: true, Order: 1}
if err := configs.DB.Create(&seedCategory).Error; err != nil {
t.Fatalf("seed category for update failed: %v", err)
}
seedTag := blogModels.Tag{ID: 88, Tag: "SeedTag", IsActive: true}
if err := configs.DB.Create(&seedTag).Error; err != nil {
t.Fatalf("seed tag for update failed: %v", err)
}
wListCategories := httptest.NewRecorder()
r.ServeHTTP(wListCategories, httptest.NewRequest(http.MethodGet, "/blogs/categories", nil))
if wListCategories.Code != http.StatusOK {
t.Fatalf("category list expected 200, got %d", wListCategories.Code)
}
wListTags := httptest.NewRecorder()
r.ServeHTTP(wListTags, httptest.NewRequest(http.MethodGet, "/blogs/tags", nil))
if wListTags.Code != http.StatusOK {
t.Fatalf("tag list expected 200, got %d", wListTags.Code)
}
wUpdateCategory := httptest.NewRecorder()
reqUpdateCategory := httptest.NewRequest(http.MethodPut, "/blogs/categories/"+strconv.FormatUint(seedCategory.ID, 10), bytes.NewReader([]byte(`{"title":"Teknoloji"}`)))
reqUpdateCategory.Header.Set("Content-Type", "application/json")
r.ServeHTTP(wUpdateCategory, reqUpdateCategory)
if wUpdateCategory.Code != http.StatusOK {
t.Fatalf("category update expected 200, got %d body=%s", wUpdateCategory.Code, wUpdateCategory.Body.String())
}
wUpdateTag := httptest.NewRecorder()
reqUpdateTag := httptest.NewRequest(http.MethodPut, "/blogs/tags/"+strconv.FormatUint(seedTag.ID, 10), bytes.NewReader([]byte(`{"tag":"Golang"}`)))
reqUpdateTag.Header.Set("Content-Type", "application/json")
r.ServeHTTP(wUpdateTag, reqUpdateTag)
if wUpdateTag.Code != http.StatusOK {
t.Fatalf("tag update expected 200, got %d body=%s", wUpdateTag.Code, wUpdateTag.Body.String())
}
wDeleteCategory := httptest.NewRecorder()
r.ServeHTTP(wDeleteCategory, httptest.NewRequest(http.MethodDelete, "/blogs/categories/"+strconv.FormatUint(seedCategory.ID, 10), nil))
if wDeleteCategory.Code != http.StatusNoContent {
t.Fatalf("category delete expected 204, got %d", wDeleteCategory.Code)
}
wDeleteTag := httptest.NewRecorder()
r.ServeHTTP(wDeleteTag, httptest.NewRequest(http.MethodDelete, "/blogs/tags/"+strconv.FormatUint(seedTag.ID, 10), nil))
if wDeleteTag.Code != http.StatusNoContent {
t.Fatalf("tag delete expected 204, got %d", wDeleteTag.Code)
}
}