package server import ( "bytes" "encoding/json" "github.com/gofiber/fiber/v2" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "gitlab.mareshq.com/hq/yggdrasil/internal/money" "gitlab.mareshq.com/hq/yggdrasil/pkg/training" "net/http" "net/http/httptest" "net/url" "testing" ) func doGet(t *testing.T, app *fiber.App, rawURL string) (*http.Response, error) { u, err := url.Parse(rawURL) if err != nil { t.Fatalf("Invalid url: %s", rawURL) } req := httptest.NewRequest("GET", u.RequestURI(), nil) req.Header.Add("Accept", "application/json") req.Host = u.Host return app.Test(req) } func doPost(t *testing.T, app *fiber.App, rawURL string, jsonBody interface{}) (*http.Response, error) { u, err := url.Parse(rawURL) if err != nil { t.Fatalf("Invalid url: %s", rawURL) } buf, err := json.Marshal(jsonBody) if err != nil { return nil, err } req := httptest.NewRequest("POST", u.RequestURI(), bytes.NewReader(buf)) req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") req.Host = u.Host return app.Test(req) } func doPut(t *testing.T, app *fiber.App, rawURL string, jsonBody interface{}) (*http.Response, error) { u, err := url.Parse(rawURL) if err != nil { t.Fatalf("Invalid url: %s", rawURL) } buf, err := json.Marshal(jsonBody) if err != nil { return nil, err } req := httptest.NewRequest("PUT", u.RequestURI(), bytes.NewReader(buf)) req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") req.Host = u.Host return app.Test(req) } func doDelete(t *testing.T, app *fiber.App, rawURL string) (*http.Response, error) { u, err := url.Parse(rawURL) if err != nil { t.Fatalf("Invalid url: %s", rawURL) } req := httptest.NewRequest("DELETE", u.RequestURI(), nil) req.Header.Add("Accept", "application/json") req.Host = u.Host return app.Test(req) } func TestServer(t *testing.T) { //var err error trainingRepo := training.NewInMemoryTrainingRepository() trainingDateRepo := training.NewInMemoryTrainingDateRepository() trainingDateAttendeeRepo := training.NewInMemoryTrainingDateAttendeeRepository() handlers := NewAPIHandlers(trainingRepo, trainingDateRepo, trainingDateAttendeeRepo) app := NewTestingServer(handlers) t.Run("Add training", func(t *testing.T) { newTraining := NewTraining{ Name: "Testing Training", Description: "This is a test training", Days: 1, Pricing: []TrainingPrice{ { Amount: "200", Currency: "EUR", Type: OPEN, }, { Amount: "1000", Currency: "EUR", Type: CORPORATE, }, { Amount: "4900", Currency: "CZK", Type: OPEN, }, { Amount: "24000", Currency: "CZK", Type: CORPORATE, }, }, } rr, _ := doPost(t, app, "/v1/trainings", newTraining) assert.Equal(t, http.StatusCreated, rr.StatusCode) var resultTraining Training err := json.NewDecoder(rr.Body).Decode(&resultTraining) assert.NoError(t, err, "error unmarshalling response") assert.Equal(t, newTraining.Name, resultTraining.Name) assert.Equal(t, newTraining.Description, resultTraining.Description) assert.Equal(t, newTraining.Days, resultTraining.Days) assert.Equal(t, newTraining.Pricing, resultTraining.Pricing) }) t.Run("Training not found", func(t *testing.T) { rr, _ := doGet(t, app, "/v1/trainings/97b0e954-14f3-4908-98fa-271f505056d3") assert.Equal(t, http.StatusNotFound, rr.StatusCode) var trainingError NotFoundError err := json.NewDecoder(rr.Body).Decode(&trainingError) assert.NoError(t, err, "error getting response", err) assert.Equal(t, http.StatusNotFound, trainingError.Status) }) t.Run("List all trainings", func(t *testing.T) { tr := &training.Training{ Name: "Testing Training", Description: "This is a test training", Days: 1, Pricing: []training.TrainingPrice{ { Amount: decimal.NewFromInt(200), Currency: "EUR", Type: training.OpenTrainingPrice, }, }, } _ = handlers.trainingRepository.Create(tr) rr, _ := doGet(t, app, "/v1/trainings") assert.Equal(t, http.StatusOK, rr.StatusCode) var trainings []Training err := json.NewDecoder(rr.Body).Decode(&trainings) assert.NoError(t, err, "error unmarshalling response") assert.Greater(t, len(trainings), 0) }) t.Run("Update training", func(t *testing.T) { tr := &training.Training{ Name: "Testing Training", Description: "This is a test training", Days: 1, Pricing: []training.TrainingPrice{ { Amount: decimal.NewFromInt(200), Currency: "EUR", Type: training.OpenTrainingPrice, }, }, } _ = handlers.trainingRepository.Create(tr) updTr := NewTraining{ Name: "Updated Training", Description: tr.Description, Days: tr.Days, Pricing: []TrainingPrice{ { Amount: decimal.NewFromInt(200).String(), Currency: money.EUR, Type: OPEN, }, }, } rr, _ := doPut(t, app, "/v1/trainings/"+tr.ID.String(), updTr) assert.Equal(t, http.StatusOK, rr.StatusCode) var trr Training err := json.NewDecoder(rr.Body).Decode(&trr) assert.NoError(t, err, "error unmarshalling response") assert.Equal(t, updTr.Name, trr.Name) }) t.Run("Delete training", func(t *testing.T) { tr := &training.Training{ Name: "Testing Training", Description: "This is a test training", Days: 1, Pricing: []training.TrainingPrice{ { Amount: decimal.NewFromInt(200), Currency: "EUR", Type: training.OpenTrainingPrice, }, }, } _ = handlers.trainingRepository.Create(tr) rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()) assert.Equal(t, http.StatusOK, rr.StatusCode) var trr Training err := json.NewDecoder(rr.Body).Decode(&trr) assert.NoError(t, err, "error unmarshalling response") assert.Equal(t, tr.ID, trr.Id) drr, _ := doDelete(t, app, "/v1/trainings/"+tr.ID.String()) assert.Equal(t, http.StatusNoContent, drr.StatusCode) rr, _ = doGet(t, app, "/v1/trainings/"+tr.ID.String()) assert.Equal(t, http.StatusNotFound, rr.StatusCode) var trainingError NotFoundError err = json.NewDecoder(rr.Body).Decode(&trainingError) assert.NoError(t, err, "error getting response", err) assert.Equal(t, http.StatusNotFound, trainingError.Status) lrr, _ := doGet(t, app, "/v1/trainings") assert.Equal(t, http.StatusOK, lrr.StatusCode) }) }