214 lines
5.2 KiB
Go
214 lines
5.2 KiB
Go
package cart
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gorilla/mux"
|
|
"sismedika.com/sas/westone/types"
|
|
)
|
|
|
|
var mockProducts = []types.Product{
|
|
{ID: 1, Name: "product 1", Price: 10, Quantity: 100},
|
|
{ID: 2, Name: "product 2", Price: 20, Quantity: 200},
|
|
{ID: 3, Name: "product 3", Price: 30, Quantity: 300},
|
|
{ID: 4, Name: "empty stock", Price: 30, Quantity: 0},
|
|
{ID: 5, Name: "almost stock", Price: 30, Quantity: 1},
|
|
}
|
|
|
|
func TestCartServiceHandler(t *testing.T) {
|
|
productStore := &mockProductStore{}
|
|
orderStore := &mockOrderStore{}
|
|
handler := NewHandler(productStore, orderStore, nil)
|
|
|
|
t.Run("should fail to checkout if the cart items do not exist", func(t *testing.T) {
|
|
payload := types.CartCheckoutPayload{
|
|
Items: []types.CartCheckoutItem{
|
|
{ProductID: 99, Quantity: 100},
|
|
},
|
|
}
|
|
|
|
marshalled, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, "/cart/checkout", bytes.NewBuffer(marshalled))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rr := httptest.NewRecorder()
|
|
router := mux.NewRouter()
|
|
|
|
router.HandleFunc("/cart/checkout", handler.handleCheckout).Methods(http.MethodPost)
|
|
|
|
router.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusBadRequest {
|
|
t.Errorf("expected status code %d, got %d", http.StatusBadRequest, rr.Code)
|
|
}
|
|
})
|
|
|
|
t.Run("should fail to checkout if the cart has negative quantities", func(t *testing.T) {
|
|
payload := types.CartCheckoutPayload{
|
|
Items: []types.CartCheckoutItem{
|
|
{ProductID: 1, Quantity: 0}, // invalid quantity
|
|
},
|
|
}
|
|
|
|
marshalled, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, "/cart/checkout", bytes.NewBuffer(marshalled))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rr := httptest.NewRecorder()
|
|
router := mux.NewRouter()
|
|
|
|
router.HandleFunc("/cart/checkout", handler.handleCheckout).Methods(http.MethodPost)
|
|
|
|
router.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusBadRequest {
|
|
t.Errorf("expected status code %d, got %d", http.StatusBadRequest, rr.Code)
|
|
}
|
|
})
|
|
|
|
t.Run("should fail to checkout if there is no stock for an item", func(t *testing.T) {
|
|
payload := types.CartCheckoutPayload{
|
|
Items: []types.CartCheckoutItem{
|
|
{ProductID: 4, Quantity: 2},
|
|
},
|
|
}
|
|
|
|
marshalled, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, "/cart/checkout", bytes.NewBuffer(marshalled))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rr := httptest.NewRecorder()
|
|
router := mux.NewRouter()
|
|
|
|
router.HandleFunc("/cart/checkout", handler.handleCheckout).Methods(http.MethodPost)
|
|
|
|
router.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusBadRequest {
|
|
t.Errorf("expected status code %d, got %d", http.StatusBadRequest, rr.Code)
|
|
}
|
|
})
|
|
|
|
t.Run("should fail to checkout if there is not enough stock", func(t *testing.T) {
|
|
payload := types.CartCheckoutPayload{
|
|
Items: []types.CartCheckoutItem{
|
|
{ProductID: 5, Quantity: 2},
|
|
},
|
|
}
|
|
|
|
marshalled, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, "/cart/checkout", bytes.NewBuffer(marshalled))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rr := httptest.NewRecorder()
|
|
router := mux.NewRouter()
|
|
|
|
router.HandleFunc("/cart/checkout", handler.handleCheckout).Methods(http.MethodPost)
|
|
|
|
router.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusBadRequest {
|
|
t.Errorf("expected status code %d, got %d", http.StatusBadRequest, rr.Code)
|
|
}
|
|
})
|
|
|
|
t.Run("should checkout and calculate the price correctly", func(t *testing.T) {
|
|
payload := types.CartCheckoutPayload{
|
|
Items: []types.CartCheckoutItem{
|
|
{ProductID: 1, Quantity: 10},
|
|
{ProductID: 2, Quantity: 20},
|
|
{ProductID: 5, Quantity: 1},
|
|
},
|
|
}
|
|
|
|
marshalled, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, "/cart/checkout", bytes.NewBuffer(marshalled))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rr := httptest.NewRecorder()
|
|
router := mux.NewRouter()
|
|
|
|
router.HandleFunc("/cart/checkout", handler.handleCheckout).Methods(http.MethodPost)
|
|
|
|
router.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusOK {
|
|
t.Errorf("expected status code %d, got %d", http.StatusOK, rr.Code)
|
|
}
|
|
|
|
var response map[string]interface{}
|
|
if err := json.NewDecoder(rr.Body).Decode(&response); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if response["total_price"] != 530.0 {
|
|
t.Errorf("expected total price to be 530, got %f", response["total_price"])
|
|
}
|
|
})
|
|
}
|
|
|
|
type mockProductStore struct{}
|
|
|
|
func (m *mockProductStore) GetProductByID(productID int) (*types.Product, error) {
|
|
return &types.Product{}, nil
|
|
}
|
|
|
|
func (m *mockProductStore) GetProducts() ([]*types.Product, error) {
|
|
return []*types.Product{}, nil
|
|
}
|
|
|
|
func (m *mockProductStore) CreateProduct(product types.CreateProductPayload) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *mockProductStore) GetProductsByID(ids []int) ([]types.Product, error) {
|
|
return mockProducts, nil
|
|
}
|
|
|
|
func (m *mockProductStore) UpdateProduct(product types.Product) error {
|
|
return nil
|
|
}
|
|
|
|
type mockOrderStore struct{}
|
|
|
|
func (m *mockOrderStore) CreateOrder(order types.Order) (int, error) {
|
|
return 0, nil
|
|
}
|
|
|
|
func (m *mockOrderStore) CreateOrderItem(orderItem types.OrderItem) error {
|
|
return nil
|
|
} |