package services import ( "authentication/models" "database/sql" "encoding/json" "testing" "time" "github.com/DATA-DOG/go-sqlmock" ) func TestInsertAccessLogLogin(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() userID := "user123" participantID := "part456" activityType := 17 ipAddress := "192.168.1.1" fieldData := json.RawMessage(`{"key": "value"}`) currentTime := time.Now() accessLog := models.UserAccessLog{ UserID: &userID, ParticipantID: &participantID, ActivityType: activityType, IPAddress: ipAddress, FieldUpdated: &fieldData, Time: currentTime, } mock.ExpectExec(`INSERT INTO access_log \( user_id, activity_type, ip_address, field_updated, time\) VALUES \(\?, \?, \?, \?, \?\)`). WithArgs(&userID, activityType, ipAddress, &fieldData, currentTime). WillReturnResult(sqlmock.NewResult(1, 1)) err := InsertAccessLogLogin(accessLog) if err != nil { t.Errorf("Expected no error, got: %v", err) } if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("Unfulfilled expectations: %v", err) } } func TestInsertAccessLogLoginNullFields(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() activityType := 5 ipAddress := "10.0.0.1" currentTime := time.Now() accessLog := models.UserAccessLog{ UserID: nil, ParticipantID: nil, ActivityType: activityType, IPAddress: ipAddress, FieldUpdated: nil, Time: currentTime, } mock.ExpectExec(`INSERT INTO access_log \( user_id, activity_type, ip_address, field_updated, time\) VALUES \(\?, \?, \?, \?, \?\)`). WithArgs(nil, activityType, ipAddress, nil, currentTime). WillReturnResult(sqlmock.NewResult(1, 1)) err := InsertAccessLogLogin(accessLog) if err != nil { t.Errorf("Expected no error, got: %v", err) } } func TestInsertAccessLogLoginError(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() userID := "user999" activityType := 17 ipAddress := "172.16.0.1" currentTime := time.Now() accessLog := models.UserAccessLog{ UserID: &userID, ActivityType: activityType, IPAddress: ipAddress, Time: currentTime, } mock.ExpectExec(`INSERT INTO access_log`). WillReturnError(sql.ErrConnDone) err := InsertAccessLogLogin(accessLog) if err == nil { t.Error("Expected error, got nil") } if err != sql.ErrConnDone { t.Errorf("Expected sql.ErrConnDone, got: %v", err) } } func TestGetActivityMessages(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() activityID := 17 expectedDescription := "User logged in" rows := sqlmock.NewRows([]string{"Description"}). AddRow(expectedDescription) mock.ExpectQuery(`SELECT Description FROM activity_type WHERE id = \?`). WithArgs(activityID). WillReturnRows(rows) description, err := GetActivityMessages(activityID) if err != nil { t.Errorf("Expected no error, got: %v", err) } if description != expectedDescription { t.Errorf("Expected description '%s', got '%s'", expectedDescription, description) } if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("Unfulfilled expectations: %v", err) } } func TestGetActivityMessagesNotFound(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() activityID := 999 mock.ExpectQuery(`SELECT Description FROM activity_type WHERE id = \?`). WithArgs(activityID). WillReturnError(sql.ErrNoRows) description, err := GetActivityMessages(activityID) if err != sql.ErrNoRows { t.Errorf("Expected sql.ErrNoRows, got: %v", err) } if description != "" { t.Errorf("Expected empty description, got '%s'", description) } } func TestGetActivityMessagesError(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() activityID := 5 mock.ExpectQuery(`SELECT Description FROM activity_type WHERE id = \?`). WithArgs(activityID). WillReturnError(sql.ErrConnDone) description, err := GetActivityMessages(activityID) if err == nil { t.Error("Expected error, got nil") } if description != "" { t.Errorf("Expected empty description on error, got '%s'", description) } } func TestInsertAccessLogLoginMultipleActivityTypes(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() activityTypes := []int{1, 5, 10, 17, 20} for _, actType := range activityTypes { userID := "user123" ipAddress := "192.168.1.1" currentTime := time.Now() accessLog := models.UserAccessLog{ UserID: &userID, ActivityType: actType, IPAddress: ipAddress, Time: currentTime, } mock.ExpectExec(`INSERT INTO access_log`). WillReturnResult(sqlmock.NewResult(1, 1)) err := InsertAccessLogLogin(accessLog) if err != nil { t.Errorf("Expected no error for activity type %d, got: %v", actType, err) } } } func TestGetActivityMessagesMultipleTypes(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() testCases := []struct { id int description string }{ {1, "User created"}, {5, "User updated"}, {10, "User deleted"}, {17, "User logged in"}, {20, "Password changed"}, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { rows := sqlmock.NewRows([]string{"Description"}). AddRow(tc.description) mock.ExpectQuery(`SELECT Description FROM activity_type WHERE id = \?`). WithArgs(tc.id). WillReturnRows(rows) description, err := GetActivityMessages(tc.id) if err != nil { t.Errorf("Expected no error, got: %v", err) } if description != tc.description { t.Errorf("Expected '%s', got '%s'", tc.description, description) } }) } } func TestInsertAccessLogLoginWithJSONField(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() userID := "user789" activityType := 17 ipAddress := "192.168.1.100" currentTime := time.Now() // Complex JSON field complexJSON := map[string]interface{}{ "action": "login", "timestamp": time.Now().Unix(), "metadata": map[string]string{ "browser": "Chrome", "os": "Windows", }, } jsonData, _ := json.Marshal(complexJSON) fieldData := json.RawMessage(jsonData) accessLog := models.UserAccessLog{ UserID: &userID, ActivityType: activityType, IPAddress: ipAddress, FieldUpdated: &fieldData, Time: currentTime, } mock.ExpectExec(`INSERT INTO access_log`). WillReturnResult(sqlmock.NewResult(1, 1)) err := InsertAccessLogLogin(accessLog) if err != nil { t.Errorf("Expected no error, got: %v", err) } } func TestInsertAccessLogLoginIPv6(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() userID := "user123" activityType := 17 ipAddressV6 := "2001:0db8:85a3:0000:0000:8a2e:0370:7334" currentTime := time.Now() accessLog := models.UserAccessLog{ UserID: &userID, ActivityType: activityType, IPAddress: ipAddressV6, Time: currentTime, } mock.ExpectExec(`INSERT INTO access_log`). WillReturnResult(sqlmock.NewResult(1, 1)) err := InsertAccessLogLogin(accessLog) if err != nil { t.Errorf("Expected no error, got: %v", err) } } func TestGetActivityMessagesEmptyDescription(t *testing.T) { mock, cleanup := setupMockDB(t) defer cleanup() activityID := 99 rows := sqlmock.NewRows([]string{"Description"}). AddRow("") mock.ExpectQuery(`SELECT Description FROM activity_type WHERE id = \?`). WithArgs(activityID). WillReturnRows(rows) description, err := GetActivityMessages(activityID) if err != nil { t.Errorf("Expected no error, got: %v", err) } if description != "" { t.Errorf("Expected empty description, got '%s'", description) } }