1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
mareshq-yggdrasil/internal/server/server_test.go

638 lines
18 KiB
Go

package server
import (
"bytes"
"encoding/json"
"github.com/gofiber/fiber/v2"
"github.com/oapi-codegen/runtime/types"
"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"
"time"
)
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)
})
t.Run("Add training date", func(t *testing.T) {
tr := &training.Training{
Name: "Testing Training for training date",
Description: "This is a test training for training date",
Days: 1,
Pricing: []training.TrainingPrice{
{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
Type: training.OpenTrainingPrice,
},
},
}
_ = handlers.trainingRepository.Create(tr)
date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC)
startTime := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
newTrainingDate := NewTrainingDate{
Address: "Test Address 123, NYC",
Capacity: 12,
Date: types.Date{Time: date},
Days: tr.Days,
IsOnline: false,
Location: "NYC",
StartTime: startTime.Format("15:04"),
Price: Price{
Amount: "200",
Currency: "EUR",
},
}
rr, err := doPost(t, app, "/v1/trainings/"+tr.ID.String()+"/dates", newTrainingDate)
assert.Equal(t, http.StatusCreated, rr.StatusCode)
var resultTrainingDate TrainingDate
err = json.NewDecoder(rr.Body).Decode(&resultTrainingDate)
assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, newTrainingDate.Address, resultTrainingDate.Address)
assert.Equal(t, newTrainingDate.Location, resultTrainingDate.Location)
assert.Equal(t, newTrainingDate.Capacity, resultTrainingDate.Capacity)
assert.Equal(t, newTrainingDate.Days, resultTrainingDate.Days)
assert.Equal(t, newTrainingDate.StartTime, resultTrainingDate.StartTime)
assert.Equal(t, newTrainingDate.IsOnline, resultTrainingDate.IsOnline)
assert.Equal(t, newTrainingDate.Price, resultTrainingDate.Price)
assert.Equal(t, newTrainingDate.Date, resultTrainingDate.Date)
})
t.Run("Training not found", func(t *testing.T) {
tr := &training.Training{
Name: "Testing Training for training date",
Description: "This is a test training for training date",
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()+"/dates/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 training dates", func(t *testing.T) {
tr := &training.Training{
Name: "Testing Training for training date",
Description: "This is a test training for training date",
Days: 1,
Pricing: []training.TrainingPrice{
{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
Type: training.OpenTrainingPrice,
},
},
}
_ = handlers.trainingRepository.Create(tr)
date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC)
td := &training.TrainingDate{
Address: "Test Address 123, NYC",
Capacity: 12,
Date: date,
Days: tr.Days,
IsOnline: false,
Location: "NYC",
StartTime: date,
Price: money.Price{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
},
}
trainingCount := 5
for range trainingCount {
_ = handlers.trainingDateRepository.Create(tr.ID, td)
}
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates")
assert.Equal(t, http.StatusOK, rr.StatusCode)
var trainingDates []TrainingDate
err := json.NewDecoder(rr.Body).Decode(&trainingDates)
assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, len(trainingDates), trainingCount)
})
t.Run("Update training date", func(t *testing.T) {
tr := &training.Training{
Name: "Testing Training for training date",
Description: "This is a test training for training date",
Days: 1,
Pricing: []training.TrainingPrice{
{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
Type: training.OpenTrainingPrice,
},
},
}
_ = handlers.trainingRepository.Create(tr)
date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC)
td := &training.TrainingDate{
Address: "Test Address 123, NYC",
Capacity: 12,
Date: date,
Days: tr.Days,
IsOnline: false,
Location: "NYC",
StartTime: date,
Price: money.Price{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
},
}
_ = handlers.trainingDateRepository.Create(tr.ID, td)
updTd := NewTrainingDate{
Address: "Updated Address 123, NYC",
Capacity: 8,
Date: types.Date{Time: date},
Days: tr.Days,
IsOnline: true,
Location: "NYC",
StartTime: date.Format("15:04"),
Price: Price{
Amount: "200",
Currency: "EUR",
},
}
rr, _ := doPut(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String(), updTd)
assert.Equal(t, http.StatusOK, rr.StatusCode)
var tdrr TrainingDate
err := json.NewDecoder(rr.Body).Decode(&tdrr)
assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, updTd.Address, tdrr.Address)
assert.Equal(t, updTd.Capacity, tdrr.Capacity)
assert.Equal(t, updTd.Date, tdrr.Date)
assert.Equal(t, updTd.Days, tdrr.Days)
assert.Equal(t, updTd.IsOnline, tdrr.IsOnline)
assert.Equal(t, updTd.Location, tdrr.Location)
assert.Equal(t, updTd.StartTime, tdrr.StartTime)
assert.Equal(t, updTd.Price, tdrr.Price)
})
t.Run("Delete training date", func(t *testing.T) {
tr := &training.Training{
Name: "Testing Training for training date",
Description: "This is a test training for training date",
Days: 1,
Pricing: []training.TrainingPrice{
{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
Type: training.OpenTrainingPrice,
},
},
}
_ = handlers.trainingRepository.Create(tr)
date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC)
td := &training.TrainingDate{
Address: "Test Address 123, NYC",
Capacity: 12,
Date: date,
Days: tr.Days,
IsOnline: false,
Location: "NYC",
StartTime: date,
Price: money.Price{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
},
}
_ = handlers.trainingDateRepository.Create(tr.ID, td)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String())
assert.Equal(t, http.StatusOK, rr.StatusCode)
var tdrr TrainingDate
err := json.NewDecoder(rr.Body).Decode(&tdrr)
assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, td.ID, tdrr.Id)
drr, _ := doDelete(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String())
assert.Equal(t, http.StatusNoContent, drr.StatusCode)
rr, _ = doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.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/"+tr.ID.String()+"/dates")
assert.Equal(t, http.StatusOK, lrr.StatusCode)
var trainingDates []TrainingDate
err = json.NewDecoder(lrr.Body).Decode(&trainingDates)
assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, len(trainingDates), 0)
})
t.Run("List upcoming training dates for training", func(t *testing.T) {
tr := &training.Training{
Name: "Testing Training for training date",
Description: "This is a test training for training date",
Days: 1,
Pricing: []training.TrainingPrice{
{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
Type: training.OpenTrainingPrice,
},
},
}
_ = handlers.trainingRepository.Create(tr)
now := time.Now()
upcomingTrainingCount := 5
for i := -4; i <= 5; i++ {
date := now.AddDate(0, 0, i)
td := &training.TrainingDate{
Address: "Test Address 123, NYC",
Capacity: 12,
Date: date,
Days: tr.Days,
IsOnline: false,
Location: "NYC",
StartTime: date,
Price: money.Price{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
},
}
_ = handlers.trainingDateRepository.Create(tr.ID, td)
}
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/upcoming-dates")
assert.Equal(t, http.StatusOK, rr.StatusCode)
var trainingDatesReturned []TrainingDate
err := json.NewDecoder(rr.Body).Decode(&trainingDatesReturned)
assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, len(trainingDatesReturned), upcomingTrainingCount)
})
t.Run("List all upcoming training dates", func(t *testing.T) {
tr1 := &training.Training{
Name: "Testing Training for training date 1",
Description: "This is a test training for training date",
Days: 1,
Pricing: []training.TrainingPrice{
{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
Type: training.OpenTrainingPrice,
},
},
}
_ = handlers.trainingRepository.Create(tr1)
tr2 := &training.Training{
Name: "Testing Training for training date 2",
Description: "This is a test training for training date",
Days: 1,
Pricing: []training.TrainingPrice{
{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
Type: training.OpenTrainingPrice,
},
},
}
_ = handlers.trainingRepository.Create(tr2)
tr3 := &training.Training{
Name: "Testing Training for training date 3",
Description: "This is a test training for training date",
Days: 1,
Pricing: []training.TrainingPrice{
{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
Type: training.OpenTrainingPrice,
},
},
}
_ = handlers.trainingRepository.Create(tr3)
allTrainings, _ := handlers.trainingRepository.FindAll()
now := time.Now()
upcomingTrainingCount := 5
for i := -4; i <= upcomingTrainingCount; i++ {
date := now.AddDate(0, 0, i)
td1 := &training.TrainingDate{
Address: "Test Address 123, NYC",
Capacity: 12,
Date: date,
Days: tr1.Days,
IsOnline: false,
Location: "NYC",
StartTime: date,
Price: money.Price{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
},
}
_ = handlers.trainingDateRepository.Create(tr1.ID, td1)
td2 := &training.TrainingDate{
Address: "Test Address 123, NYC",
Capacity: 12,
Date: date,
Days: tr2.Days,
IsOnline: false,
Location: "NYC",
StartTime: date,
Price: money.Price{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
},
}
_ = handlers.trainingDateRepository.Create(tr2.ID, td2)
td3 := &training.TrainingDate{
Address: "Test Address 123, NYC",
Capacity: 12,
Date: date,
Days: tr3.Days,
IsOnline: false,
Location: "NYC",
StartTime: date,
Price: money.Price{
Amount: decimal.NewFromInt(200),
Currency: "EUR",
},
}
_ = handlers.trainingDateRepository.Create(tr3.ID, td3)
}
rr, _ := doGet(t, app, "/v1/trainings/upcoming-dates")
assert.Equal(t, http.StatusOK, rr.StatusCode)
var trainingDatesReturned ListAllUpcomingTrainingDatesResponse
err := json.NewDecoder(rr.Body).Decode(&trainingDatesReturned)
assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, len(allTrainings), len(trainingDatesReturned))
for _, tdr := range trainingDatesReturned {
if tdr.TrainingID == tr1.ID || tdr.TrainingID == tr2.ID || tdr.TrainingID == tr3.ID {
assert.Equal(t, len(tdr.Dates), upcomingTrainingCount)
}
}
})
}