boxes-api/main_test.go

349 lines
10 KiB
Go

package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
)
func TestMain(m *testing.M) {
// Load the configuration
var err error
config, err = LoadConfig("config.yaml")
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
// Set the environment variable for the test database
os.Setenv("TEST_DATABASE_PATH", "data/my_test_database.db")
config.DatabasePath = os.Getenv("TEST_DATABASE_PATH")
// Connect to the database using the test database path
db, err = ConnectDB(config.DatabasePath)
if err != nil {
log.Fatalf("Failed to connect to test database: %v", err)
}
fmt.Println("DB is connected")
defer db.Close()
// Truncate tables before running tests
for _, table := range []string{"boxes", "items", "users"} { // Add all your table names here
if err := db.Exec(fmt.Sprintf("DELETE FROM %s", table)).Error; err != nil {
log.Fatalf("Failed to truncate table %s: %v", table, err)
}
}
db.LogMode(true)
// Run the tests
exitCode := m.Run()
os.Exit(exitCode)
}
func TestGetBoxes(t *testing.T) {
// 1. Create a request (no need for a real token in testing)
req := httptest.NewRequest("GET", "/boxes", nil)
req = req.WithContext(context.WithValue(req.Context(), userKey, "testuser")) // Simulate authenticated user
// 2. Create a recorder
rr := httptest.NewRecorder()
// 3. Initialize your router
router := mux.NewRouter()
router.Handle("/boxes", http.HandlerFunc(GetBoxesHandler)).Methods("GET")
// 4. Serve the request
router.ServeHTTP(rr, req)
// 5. Assert the response
assert.Equal(t, http.StatusOK, rr.Code)
// Add more assertions to check response body, headers, etc.
}
func TestCreateBox(t *testing.T) {
// 1. Create a request with a new box in the body
newBox := Box{Name: "Test Box"}
reqBody, _ := json.Marshal(newBox)
req := httptest.NewRequest("POST", "/boxes", bytes.NewBuffer(reqBody))
req = req.WithContext(context.WithValue(req.Context(), userKey, "testuser")) // Simulate authenticated user
req.Header.Set("Content-Type", "application/json")
// 2. Create a recorder
rr := httptest.NewRecorder()
// 3. Initialize your router
router := mux.NewRouter()
router.Handle("/boxes", http.HandlerFunc(CreateBoxHandler)).Methods("POST")
// 4. Serve the request
router.ServeHTTP(rr, req)
// 5. Assert the response
assert.Equal(t, http.StatusOK, rr.Code)
// 6. Decode the response body
var createdBox Box
json.Unmarshal(rr.Body.Bytes(), &createdBox)
// 7. Assert the created box
assert.Equal(t, newBox.Name, createdBox.Name)
}
func TestGetItem(t *testing.T) {
// Create a test item in the database
testItem := Item{Name: "Test Item", Description: "Test Description", BoxID: 1}
db.Create(&testItem)
// Create a request to get the test item
req := httptest.NewRequest("GET", fmt.Sprintf("/items/%d", testItem.ID), nil)
req = req.WithContext(context.WithValue(req.Context(), userKey, "testuser")) // Simulate authenticated user
// Create a response recorder
rr := httptest.NewRecorder()
// Initialize the router
router := mux.NewRouter()
router.Handle("/items/{id}", http.HandlerFunc(GetItemHandler)).Methods("GET")
// Serve the request
router.ServeHTTP(rr, req)
// Check the response status code
assert.Equal(t, http.StatusOK, rr.Code)
// Decode the response body
var retrievedItem Item
err := json.Unmarshal(rr.Body.Bytes(), &retrievedItem)
assert.NoError(t, err)
// Check if the retrieved item matches the test item
assert.Equal(t, testItem.ID, retrievedItem.ID)
assert.Equal(t, testItem.Name, retrievedItem.Name)
assert.Equal(t, testItem.Description, retrievedItem.Description)
assert.Equal(t, testItem.BoxID, retrievedItem.BoxID)
fmt.Println("TestGetItem")
}
func TestGetItemsInBox(t *testing.T) {
// Create test items associated with a specific box
testBox := Box{Name: "Test Box for Items"}
fmt.Println("testBox.ID (before create):", testBox.ID) // Should be 0
if err := db.Create(&testBox).Error; err != nil { // Check for errors!
t.Fatalf("Failed to create test box: %v", err)
}
// temporarily disable callbacks
db.Callback().Create().Replace("gorm:create", nil)
fmt.Println("testBox.ID (after create):", testBox.ID) // Should be a non-zero value
defaultImagePath := "default.jpg"
testItems := []Item{
{Name: "Item 1", Description: "Description 1", BoxID: testBox.ID, ImagePath: &defaultImagePath}, // Use "" for empty string
{Name: "Item 2", Description: "Description 2", BoxID: testBox.ID, ImagePath: &defaultImagePath}, // Use "" for empty string
}
fmt.Println("Right before creating test items in database")
// Marshal the testItems slice to JSON
jsonData, err := json.MarshalIndent(testItems, "", " ") // Use " " for indentation
if err != nil {
t.Fatalf("Failed to marshal testItems to JSON: %v", err)
}
// Print the formatted JSON
fmt.Println("testItems:", string(jsonData))
if err := db.Create(&testItems).Error; err != nil { // Check for errors!
t.Fatalf("Failed to create test items: %v", err)
}
fmt.Println("Right AFTER creating test items in database")
// Create a request to get items in the test box
req := httptest.NewRequest("GET", fmt.Sprintf("/items/%d/items", testBox.ID), nil)
req = req.WithContext(context.WithValue(req.Context(), userKey, "testuser")) // Simulate authenticated user
// Create a response recorder
rr := httptest.NewRecorder()
// Initialize the router
router := mux.NewRouter()
router.Handle("/items/{id}/items", http.HandlerFunc(GetItemsInBoxHandler)).Methods("GET")
// Serve the request
router.ServeHTTP(rr, req)
// Check the response status code
assert.Equal(t, http.StatusOK, rr.Code)
// Decode the response body
var retrievedItems []Item
err = json.Unmarshal(rr.Body.Bytes(), &retrievedItems)
assert.NoError(t, err)
// Check if the correct number of items is retrieved
assert.Equal(t, len(testItems), len(retrievedItems))
// You can add more assertions to check the content of retrievedItems
}
func TestUpdateItem(t *testing.T) {
// Create a test item in the database
testItem := Item{Name: "Test Item", Description: "Test Description", BoxID: 1}
db.Create(&testItem)
// Create a request to update the test item
updatedItem := Item{Name: "Updated Item", Description: "Updated Description"}
reqBody, _ := json.Marshal(updatedItem)
req := httptest.NewRequest("PUT", fmt.Sprintf("/items/%d", testItem.ID), bytes.NewBuffer(reqBody))
req = req.WithContext(context.WithValue(req.Context(), userKey, "testuser")) // Simulate authenticated user
req.Header.Set("Content-Type", "application/json")
// Create a response recorder
rr := httptest.NewRecorder()
// Initialize the router
router := mux.NewRouter()
router.Handle("/items/{id}", http.HandlerFunc(UpdateItemHandler)).Methods("PUT")
// Serve the request
router.ServeHTTP(rr, req)
// Check the response status code
assert.Equal(t, http.StatusOK, rr.Code)
// Retrieve the updated item from the database
var dbItem Item
db.First(&dbItem, testItem.ID)
// Check if the item is updated in the database
assert.Equal(t, updatedItem.Name, dbItem.Name)
assert.Equal(t, updatedItem.Description, dbItem.Description)
}
func TestDeleteItem(t *testing.T) {
// Create a test item in the database
testItem := Item{Name: "Test Item", Description: "Test Description", BoxID: 1}
db.Create(&testItem)
// Create a request to delete the test item
req := httptest.NewRequest("DELETE", fmt.Sprintf("/items/%d", testItem.ID), nil)
req = req.WithContext(context.WithValue(req.Context(), userKey, "testuser")) // Simulate authenticated user
// Create a response recorder
rr := httptest.NewRecorder()
// Initialize the router
router := mux.NewRouter()
router.Handle("/items/{id}", http.HandlerFunc(DeleteItemHandler)).Methods("DELETE")
// Serve the request
router.ServeHTTP(rr, req)
// Check the response status code
assert.Equal(t, http.StatusNoContent, rr.Code)
// Try to retrieve the deleted item from the database
var deletedItem Item
err := db.First(&deletedItem, testItem.ID).Error
assert.Error(t, err) // Expect an error because the item should be deleted
}
func TestCreateItem(t *testing.T) {
// 1. Create a request with a new item in the body
newItem := Item{Name: "Test Item", Description: "Test Description", BoxID: 1}
reqBody, _ := json.Marshal(newItem)
req := httptest.NewRequest("POST", "/items", bytes.NewBuffer(reqBody))
req = req.WithContext(context.WithValue(req.Context(), userKey, "testuser")) // Simulate authenticated user
req.Header.Set("Content-Type", "application/json")
// 2. Create a recorder
rr := httptest.NewRecorder()
// 3. Initialize your router
router := mux.NewRouter()
router.Handle("/items", http.HandlerFunc(CreateItemHandler)).Methods("POST")
// 4. Serve the request
router.ServeHTTP(rr, req)
// 5. Assert the response
assert.Equal(t, http.StatusOK, rr.Code)
// 6. Decode the response body
var createdItem Item
json.Unmarshal(rr.Body.Bytes(), &createdItem)
// 7. Assert the created item
assert.Equal(t, newItem.Name, createdItem.Name)
assert.Equal(t, newItem.Description, createdItem.Description)
assert.Equal(t, newItem.BoxID, createdItem.BoxID)
}
func TestGetItems(t *testing.T) {
// 1. Create a request (no need for a real token in testing)
req := httptest.NewRequest("GET", "/items", nil)
req = req.WithContext(context.WithValue(req.Context(), userKey, "testuser")) // Simulate authenticated user
// 2. Create a recorder
rr := httptest.NewRecorder()
// 3. Initialize your router
router := mux.NewRouter()
router.Handle("/items", http.HandlerFunc(GetItemsHandler)).Methods("GET")
// 4. Serve the request
router.ServeHTTP(rr, req)
// 5. Assert the response
assert.Equal(t, http.StatusOK, rr.Code)
// Add more assertions to check response body, headers, etc.
}
func ExampleLoginHandler() {
// Create a request with login credentials
loginReq := LoginRequest{
Username: "testuser",
Password: "testpassword",
}
reqBody, _ := json.Marshal(loginReq)
req := httptest.NewRequest("POST", "/login", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
// Create a response recorder
rr := httptest.NewRecorder()
// Create a test handler (usually your LoginHandler)
handler := http.HandlerFunc(LoginHandler)
// Serve the request
handler.ServeHTTP(rr, req)
// Check the response status code
if rr.Code != http.StatusOK {
fmt.Printf("Login failed with status code: %d\n", rr.Code)
} else {
// Decode the response body to get the token
var loginResp LoginResponse
json.Unmarshal(rr.Body.Bytes(), &loginResp)
fmt.Println("Login successful! Token:", loginResp.Token)
}
}