399 lines
12 KiB
Go
399 lines
12 KiB
Go
package integration
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"wish-list-api/api/handlers"
|
|
"wish-list-api/api/middleware"
|
|
"wish-list-api/pkg/auth"
|
|
"wish-list-api/pkg/entities"
|
|
"wish-list-api/pkg/user"
|
|
wishlist "wish-list-api/pkg/wish-list"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/golang-jwt/jwt/v5"
|
|
"github.com/stretchr/testify/assert"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
var (
|
|
app *fiber.App
|
|
testDB *mongo.Database
|
|
client *mongo.Client
|
|
authSvc auth.Service
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
setup()
|
|
|
|
exitCode := m.Run()
|
|
|
|
teardown()
|
|
|
|
os.Exit(exitCode)
|
|
}
|
|
|
|
func setup() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
var err error
|
|
mongoURI := os.Getenv("MONGODB_URI")
|
|
if mongoURI == "" {
|
|
mongoURI = "mongodb://mongo_user:mongo_password@localhost:27017/admin"
|
|
}
|
|
|
|
client, err = mongo.Connect(ctx, options.Client().ApplyURI(mongoURI))
|
|
if err != nil {
|
|
log.Fatalf("Error connecting to MongoDB: %v", err)
|
|
}
|
|
|
|
err = client.Ping(ctx, nil)
|
|
if err != nil {
|
|
log.Fatalf("Could not connect to MongoDB: %v", err)
|
|
}
|
|
|
|
dbName := fmt.Sprintf("wishlist_test_%d", time.Now().UnixNano())
|
|
testDB = client.Database(dbName)
|
|
|
|
userCollection := testDB.Collection("users")
|
|
wishlistCollection := testDB.Collection("wishlists")
|
|
wishlistItemCollection := testDB.Collection("wishlist_items")
|
|
|
|
userRepo := user.NewMongoRepository(userCollection)
|
|
wishlistRepo := wishlist.NewMongoRepository(wishlistCollection, wishlistItemCollection)
|
|
|
|
userService := user.NewService(userRepo)
|
|
|
|
authSvc = auth.NewService(auth.ServiceConfig{
|
|
UserService: userService,
|
|
})
|
|
|
|
wishlistSvc := wishlist.NewService(wishlistRepo)
|
|
|
|
app = fiber.New()
|
|
|
|
api := app.Group("/api")
|
|
|
|
api.Post("/auth/register", handlers.Register(authSvc))
|
|
api.Post("/auth/login", handlers.Login(authSvc))
|
|
api.Post("/auth/refresh", handlers.RefreshToken(authSvc))
|
|
|
|
wishListHandler := handlers.NewWishListHandler(wishlistSvc, authSvc)
|
|
|
|
wishList := api.Group("/wishlist")
|
|
|
|
wishList.Get("/:id", wishListHandler.GetWishList)
|
|
|
|
wishList.Get("/user/:userId", wishListHandler.GetUserWishLists)
|
|
|
|
wishList.Get("/:wishlistId/items", wishListHandler.GetWishListItems)
|
|
|
|
wishList.Get("/item/:id", wishListHandler.GetWishListItem)
|
|
|
|
wishList.Post("/", middleware.Protected(authSvc), wishListHandler.CreateWishList)
|
|
wishList.Put("/:id", middleware.Protected(authSvc), wishListHandler.UpdateWishList)
|
|
wishList.Delete("/:id", middleware.Protected(authSvc), wishListHandler.DeleteWishList)
|
|
|
|
wishList.Post("/item", middleware.Protected(authSvc), wishListHandler.CreateWishListItem)
|
|
wishList.Put("/item/:id", middleware.Protected(authSvc), wishListHandler.UpdateWishListItem)
|
|
wishList.Delete("/item/:id", middleware.Protected(authSvc), wishListHandler.DeleteWishListItem)
|
|
}
|
|
|
|
func teardown() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
if err := testDB.Drop(ctx); err != nil {
|
|
log.Printf("Error dropping test database: %v", err)
|
|
}
|
|
|
|
if err := client.Disconnect(ctx); err != nil {
|
|
log.Printf("Error disconnecting from MongoDB: %v", err)
|
|
}
|
|
}
|
|
|
|
func registerTestUser(t *testing.T) (string, primitive.ObjectID) {
|
|
userData := entities.RegisterRequest{
|
|
Email: fmt.Sprintf("test%d@example.com", time.Now().UnixNano()),
|
|
Password: "password123",
|
|
}
|
|
|
|
jsonBody, _ := json.Marshal(userData)
|
|
req := httptest.NewRequest("POST", "/api/auth/register", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
var response struct {
|
|
Status bool `json:"status"`
|
|
Data entities.TokenPair `json:"data"`
|
|
Error *string `json:"error"`
|
|
}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
|
assert.NoError(t, err)
|
|
|
|
claims, err := authSvc.ValidateToken(response.Data.AccessToken)
|
|
assert.NoError(t, err)
|
|
|
|
mapClaims := claims.Claims.(jwt.MapClaims)
|
|
userIDStr := mapClaims["user_id"].(string)
|
|
userID, err := primitive.ObjectIDFromHex(userIDStr)
|
|
assert.NoError(t, err)
|
|
|
|
return response.Data.AccessToken, userID
|
|
}
|
|
|
|
func TestRegister(t *testing.T) {
|
|
userData := entities.RegisterRequest{
|
|
Email: fmt.Sprintf("test%d@example.com", time.Now().UnixNano()),
|
|
Password: "password123",
|
|
}
|
|
|
|
jsonBody, _ := json.Marshal(userData)
|
|
req := httptest.NewRequest("POST", "/api/auth/register", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
req = httptest.NewRequest("POST", "/api/auth/register", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusConflict, resp.StatusCode)
|
|
}
|
|
|
|
func TestLogin(t *testing.T) {
|
|
email := fmt.Sprintf("test%d@example.com", time.Now().UnixNano())
|
|
userData := entities.RegisterRequest{
|
|
Email: email,
|
|
Password: "password123",
|
|
}
|
|
|
|
jsonBody, _ := json.Marshal(userData)
|
|
req := httptest.NewRequest("POST", "/api/auth/register", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
loginData := entities.LoginRequest{
|
|
Email: email,
|
|
Password: "password123",
|
|
}
|
|
|
|
jsonBody, _ = json.Marshal(loginData)
|
|
req = httptest.NewRequest("POST", "/api/auth/login", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
loginData.Password = "wrongpassword"
|
|
jsonBody, _ = json.Marshal(loginData)
|
|
req = httptest.NewRequest("POST", "/api/auth/login", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
|
}
|
|
|
|
func TestWishListCRUD(t *testing.T) {
|
|
token, userID := registerTestUser(t)
|
|
|
|
wishlistData := entities.WishList{
|
|
Title: "Test Wishlist",
|
|
Description: "Integration test wishlist",
|
|
IsPublic: true,
|
|
}
|
|
|
|
jsonBody, _ := json.Marshal(wishlistData)
|
|
req := httptest.NewRequest("POST", "/api/wishlist", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
|
|
resp, err := app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
|
|
|
var createResponse struct {
|
|
Status bool `json:"status"`
|
|
Data entities.WishList `json:"data"`
|
|
Error *string `json:"error"`
|
|
}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&createResponse)
|
|
assert.NoError(t, err)
|
|
wishlistID := createResponse.Data.ID
|
|
|
|
req = httptest.NewRequest("GET", "/api/wishlist/"+wishlistID, nil)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
updatedData := entities.WishList{
|
|
Title: "Updated Title",
|
|
Description: "Updated description",
|
|
IsPublic: false,
|
|
}
|
|
|
|
jsonBody, _ = json.Marshal(updatedData)
|
|
req = httptest.NewRequest("PUT", "/api/wishlist/"+wishlistID, bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
req = httptest.NewRequest("GET", "/api/wishlist/"+wishlistID, nil)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
|
|
|
req = httptest.NewRequest("GET", "/api/wishlist/"+wishlistID, nil)
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
req = httptest.NewRequest("GET", "/api/wishlist/user/"+userID.Hex(), nil)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
req = httptest.NewRequest("DELETE", "/api/wishlist/"+wishlistID, nil)
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
req = httptest.NewRequest("GET", "/api/wishlist/"+wishlistID, nil)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
}
|
|
|
|
func TestWishListItemsCRUD(t *testing.T) {
|
|
token, _ := registerTestUser(t)
|
|
|
|
wishlistData := entities.WishList{
|
|
Title: "Test Wishlist for Items",
|
|
Description: "Testing wishlist items",
|
|
IsPublic: true,
|
|
}
|
|
|
|
jsonBody, _ := json.Marshal(wishlistData)
|
|
req := httptest.NewRequest("POST", "/api/wishlist", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
|
|
resp, err := app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
|
|
|
var createResponse struct {
|
|
Status bool `json:"status"`
|
|
Data entities.WishList `json:"data"`
|
|
Error *string `json:"error"`
|
|
}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&createResponse)
|
|
assert.NoError(t, err)
|
|
wishlistID := createResponse.Data.ID
|
|
|
|
itemData := entities.WishListItem{
|
|
Title: "Test Item",
|
|
Description: "Test item description",
|
|
URL: "https://example.com",
|
|
Cost: 99.99,
|
|
WishListID: wishlistID,
|
|
}
|
|
|
|
jsonBody, _ = json.Marshal(itemData)
|
|
req = httptest.NewRequest("POST", "/api/wishlist/item", bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
|
|
|
var itemResponse struct {
|
|
Status bool `json:"status"`
|
|
Data entities.WishListItem `json:"data"`
|
|
Error *string `json:"error"`
|
|
}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&itemResponse)
|
|
assert.NoError(t, err)
|
|
itemID := itemResponse.Data.ID
|
|
|
|
req = httptest.NewRequest("GET", "/api/wishlist/item/"+itemID, nil)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
updatedItemData := entities.WishListItem{
|
|
Title: "Updated Item Title",
|
|
Description: "Updated item description",
|
|
URL: "https://example.com",
|
|
Cost: 149.99,
|
|
}
|
|
|
|
jsonBody, _ = json.Marshal(updatedItemData)
|
|
req = httptest.NewRequest("PUT", "/api/wishlist/item/"+itemID, bytes.NewReader(jsonBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
req = httptest.NewRequest("GET", "/api/wishlist/"+wishlistID+"/items", nil)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
var itemsResponse struct {
|
|
Status bool `json:"status"`
|
|
Data []entities.WishListItem `json:"data"`
|
|
Error *string `json:"error"`
|
|
}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&itemsResponse)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(itemsResponse.Data))
|
|
|
|
req = httptest.NewRequest("DELETE", "/api/wishlist/item/"+itemID, nil)
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
req = httptest.NewRequest("GET", "/api/wishlist/item/"+itemID, nil)
|
|
resp, err = app.Test(req, -1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
}
|