//go:build end2end package end2end import ( "bytes" "context" "encoding/json" "fmt" "git.gocasts.ir/ebhomengo/niki/delivery/http_server/end2end/setup" "git.gocasts.ir/ebhomengo/niki/entity" addressparam "git.gocasts.ir/ebhomengo/niki/param/benefactor/address" benefactoreparam "git.gocasts.ir/ebhomengo/niki/param/benefactor/benefactor" errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg" "github.com/labstack/echo/v4" "github.com/stretchr/testify/suite" "net/http" "net/http/httptest" "testing" ) type BenefactorAddressTestSuit struct { suite.Suite benefactorPhone string benefactorID uint addressID uint getAllExpected map[string]interface{} getExpected addressparam.GetAddressResponse createData addressparam.BenefactorAddAddressRequest updateData addressparam.UpdateAddressRequest teardown func() } // SetupTest runs before each test in the suite func (suite *BenefactorAddressTestSuit) SetupTest() { teardown := setup.SeedMariaDB(testContainer.GetMariaDBConfig()) suite.T().Cleanup(teardown) suite.benefactorPhone = "09384664404" suite.benefactorID = 1 suite.addressID = 1 suite.getAllExpected = map[string]interface{}{ "count": 1, } suite.getExpected = addressparam.GetAddressResponse{ Address: entity.Address{ ID: suite.addressID, PostalCode: "3719655861", Address: "tehran sare koche 1", Lat: 35.632508, Lon: 51.452859, Name: "home1", CityID: 8, BenefactorID: suite.benefactorID, }, } suite.createData = addressparam.BenefactorAddAddressRequest{ PostalCode: "3719655861", Address: "create shiraz kaf sharo", Lat: 29.62949, Lon: 52.497287, CityID: 194, Name: "create shiraz", } suite.updateData = addressparam.UpdateAddressRequest{ PostalCode: "3719655861", Address: "update shiraz kaf sharo", Lat: 29.62949, Lon: 52.497287, CityID: 194, Name: "update shiraz", } } func TestBenefactorAddressTestSuit(t *testing.T) { suite.Run(t, new(BenefactorAddressTestSuit)) } // loginBenefactor authenticates the benefactor and returns an access token func (suite *BenefactorAddressTestSuit) loginBenefactor() string { sendOTPRes, err := services.BenefactorSvc.SendOtp(context.Background(), benefactoreparam.SendOtpRequest{ PhoneNumber: suite.benefactorPhone, }) suite.Require().NoError(err, "failed to send OTP") registerRes, err := services.BenefactorSvc.LoginOrRegister(context.Background(), benefactoreparam.LoginOrRegisterRequest{ PhoneNumber: suite.benefactorPhone, VerificationCode: sendOTPRes.Code, }) suite.Require().NoError(err, "failed to login or register") return registerRes.Tokens.AccessToken } // createRequest is a utility function to create and send HTTP requests func (suite *BenefactorAddressTestSuit) createRequest(method, url string, body interface{}) *httptest.ResponseRecorder { var buf bytes.Buffer if body != nil { err := json.NewEncoder(&buf).Encode(body) suite.Require().NoError(err, "could not encode body") } token := suite.loginBenefactor() req := httptest.NewRequest(method, url, &buf) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) req.Header.Set(echo.HeaderAuthorization, fmt.Sprintf("Bearer %s", token)) rec := httptest.NewRecorder() testServer.Serve(rec, req) return rec } // TestBenefactorAddressGet tests the GET /address/:id endpoint func (suite *BenefactorAddressTestSuit) TestBenefactorAddressGet() { responseRecord := suite.createRequest("GET", fmt.Sprintf("/address/%d", suite.addressID), nil) suite.Require().Equal(http.StatusOK, responseRecord.Code) var response addressparam.GetAddressResponse err := json.NewDecoder(responseRecord.Body).Decode(&response) suite.Require().NoError(err, "could not decode response body") suite.Require().Equal(suite.addressID, response.Address.ID) suite.Require().Equal(suite.benefactorID, response.Address.BenefactorID) suite.Require().Equal(suite.getExpected.Address.PostalCode, response.Address.PostalCode) suite.Require().Equal(suite.getExpected.Address.Address, response.Address.Address) // TODO: Fix //suite.Require().Equal(suite.getExpected.Address.Lat, response.Address.Lat) //suite.Require().Equal(suite.getExpected.Address.Lon, response.Address.Lon) suite.Require().Equal(suite.getExpected.Address.Name, response.Address.Name) suite.Require().Equal(suite.getExpected.Address.CityID, response.Address.CityID) } // TestBenefactorAddressGetAll tests the GET /address/ endpoint func (suite *BenefactorAddressTestSuit) TestBenefactorAddressGetAll() { responseRecord := suite.createRequest("GET", "/address/", nil) suite.Require().Equal(http.StatusOK, responseRecord.Code) var response addressparam.GetAllAddressesResponse err := json.NewDecoder(responseRecord.Body).Decode(&response) suite.Require().NoError(err, "could not decode response body") suite.Require().Equal(suite.getAllExpected["count"], len(response.AllAddresses)) } // TestBenefactorAddressCreate tests the POST /address/ endpoint func (suite *BenefactorAddressTestSuit) TestBenefactorAddressCreate() { responseRecord := suite.createRequest("POST", "/address/", suite.createData) suite.Require().Equal(http.StatusCreated, responseRecord.Code) var response addressparam.BenefactorAddAddressResponse err := json.NewDecoder(responseRecord.Body).Decode(&response) suite.Require().NoError(err, "could not decode response body") suite.Require().Equal(suite.benefactorID, response.Address.BenefactorID) suite.Require().Equal(suite.createData.Address, response.Address.Address) suite.Require().Equal(suite.createData.PostalCode, response.Address.PostalCode) suite.Require().Equal(suite.createData.Name, response.Address.Name) suite.Require().Equal(suite.createData.CityID, response.Address.CityID) } // TestBenefactorAddressUpdate tests the PUT /address/:id endpoint func (suite *BenefactorAddressTestSuit) TestBenefactorAddressUpdate() { // TODO: check Method is patch, however, all fields are required !! responseRecord := suite.createRequest("PATCH", fmt.Sprintf("/address/%d", suite.addressID), suite.updateData) suite.Require().Equal(http.StatusNoContent, responseRecord.Code) updatedAddress, sErr := services.BenefactorAddressSvc.Get(context.Background(), addressparam.GetAddressRequest{ AddressID: suite.addressID, BenefactorID: suite.benefactorID, }) suite.Require().NoError(sErr, "failed to get benefactor address") suite.Require().Equal(suite.updateData.PostalCode, updatedAddress.Address.PostalCode) suite.Require().Equal(suite.updateData.Address, updatedAddress.Address.Address) suite.Require().Equal(suite.updateData.Name, updatedAddress.Address.Name) suite.Require().Equal(suite.updateData.CityID, updatedAddress.Address.CityID) // TODO Fixing floating-point comparison with tolerance //suite.Require().Equal(suite.updateData.Lat, updatedAddress.Address.Lat) //suite.Require().Equal(suite.updateData.Lon, updatedAddress.Address.Lon) } // TestBenefactorAddressDelete tests the DELETE /address/:id endpoint func (suite *BenefactorAddressTestSuit) TestBenefactorAddressDelete() { responseRecord := suite.createRequest("DELETE", fmt.Sprintf("/address/%d", suite.addressID), nil) suite.Require().Equal(http.StatusNoContent, responseRecord.Code) _, err := services.BenefactorAddressSvc.Get(context.Background(), addressparam.GetAddressRequest{ AddressID: suite.addressID, BenefactorID: suite.benefactorID, }, ) message, code := httpmsg.Error(err) suite.Require().Error(err) suite.Equal(http.StatusNotFound, code) suite.Equal(errmsg.ErrorMsgNotFound, message) }