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) } }