diff --git a/TODO b/TODO index 2c51c77..91ff6df 100644 --- a/TODO +++ b/TODO @@ -1,2 +1 @@ -- Write some tests - Validation system \ No newline at end of file diff --git a/app/controllers/post/create.go b/app/controllers/post/create.go index 9da13b8..0c09686 100644 --- a/app/controllers/post/create.go +++ b/app/controllers/post/create.go @@ -12,6 +12,12 @@ func Create(ctx *fiber.Ctx) error { return err } + if len(post.Content) < 1 { + return ctx.Status(400).JSON(fiber.Map{ + "message": "Content is required", + }) + } + if err := database.Connection().Create(&post).Error; err != nil { return err } diff --git a/app/controllers/post/create_test.go b/app/controllers/post/create_test.go new file mode 100644 index 0000000..061341f --- /dev/null +++ b/app/controllers/post/create_test.go @@ -0,0 +1,106 @@ +package post + +import ( + "bytes" + "encoding/json" + "io" + "net/http/httptest" + "testing" + + "github.com/gofiber/fiber/v2" +) + +func TestCreate(t *testing.T) { + type wanted struct { + statusCode int + expectedKeys []string + } + + // Create fiber app for testing purposes + app := fiber.New() + app.Post("/", Create) + + // Tests struct + tests := []struct { + name string + description string + endpoint string + payload any + want wanted + }{ + { + name: "Create a fake post", + description: "This test should return 200 status code and created post", + endpoint: "/", + payload: map[string]any{ + "title": "Example post", + "content": "Lorem ipsum", + }, + want: wanted{ + statusCode: 200, + expectedKeys: []string{ + "id", + "title", + "content", + }, + }, + }, + { + name: "Create a post with blank content", + description: "This test should return 400 status code and error message", + endpoint: "/", + payload: map[string]any{ + "title": "Example post2", + "content": "", + }, + want: wanted{ + statusCode: 400, + expectedKeys: []string{ + "message", + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + body, err := json.Marshal(tt.payload) + if err != nil { + t.Errorf("Cannot parse body: %v", err) + t.Fail() + } + + req := httptest.NewRequest("POST", tt.endpoint, bytes.NewReader(body)) + req.Header.Add("Content-Type", "application/json") + + // Create request + res, err := app.Test(req) + if err != nil { + t.Errorf("Cannot test Fiber handler: %v", err) + t.Fail() + } + + // Assertions + if res.StatusCode != tt.want.statusCode { + t.Errorf("Expected status code %d, got %d", tt.want.statusCode, res.StatusCode) + } + + answer, err := io.ReadAll(res.Body) + if err != nil { + t.Errorf("Cannot parse body: %v", err) + } + + var message map[string]any + err = json.Unmarshal([]byte(answer), &message) + if err != nil { + t.Errorf("Cannot unmarshal response: %v", err) + } + + for _, s := range tt.want.expectedKeys { + if _, ok := message[s]; !ok { + t.Errorf("Expected response body to contain key %s but it can not be found", s) + } + } + }) + } +} diff --git a/app/controllers/post/index_test.go b/app/controllers/post/index_test.go new file mode 100644 index 0000000..4e85469 --- /dev/null +++ b/app/controllers/post/index_test.go @@ -0,0 +1,67 @@ +package post + +import ( + "encoding/json" + "io" + "net/http/httptest" + "strings" + "testing" + + "github.com/dogukanoksuz/go-rest-api-boilerplate/app/models" + "github.com/gofiber/fiber/v2" +) + +func TestIndex(t *testing.T) { + type wanted struct { + statusCode int + } + + // Create fiber app for testing purposes + app := fiber.New() + app.Get("/", Index) + + // Tests struct + tests := []struct { + name string + description string + endpoint string + want wanted + }{ + { + name: "Get posts list", + description: "This test should return 200 status code and return a list of posts", + endpoint: "/", + want: wanted{ + statusCode: 200, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := httptest.NewRequest("GET", tt.endpoint, strings.NewReader("")) + + // Create request + res, err := app.Test(req) + if err != nil { + t.Errorf("Cannot test Fiber handler: %v", err) + t.Fail() + } + + // Assertions + if res.StatusCode != tt.want.statusCode { + t.Errorf("Expected status code %d, got %d", tt.want.statusCode, res.StatusCode) + } + + answer, err := io.ReadAll(res.Body) + if err != nil { + t.Errorf("Cannot parse body: %v", err) + } + + var posts []models.Post + if err := json.Unmarshal(answer, &posts); err != nil { + t.Errorf("Cannot unmarshal body, might returned wrong type of output: %v", err) + } + }) + } +} diff --git a/app/models/post.go b/app/models/post.go index 469c026..98d8234 100644 --- a/app/models/post.go +++ b/app/models/post.go @@ -6,9 +6,9 @@ import ( ) type Post struct { - ID string `gorm:"primary_key"` - Title string - Content string `gorm:"type:text"` + ID string `gorm:"primary_key" json:"id"` + Title string `json:"title"` + Content string `gorm:"type:text" json:"content"` } func (post *Post) BeforeCreate(tx *gorm.DB) error {