diff --git a/backend/plugins/q_dev/api/connection_test.go b/backend/plugins/q_dev/api/connection_test.go index 916fbd155d0..6c39dee3f0c 100644 --- a/backend/plugins/q_dev/api/connection_test.go +++ b/backend/plugins/q_dev/api/connection_test.go @@ -231,11 +231,11 @@ func TestConnectionSanitization_PreservesIdentityStore(t *testing.T) { // Secret should be sanitized assert.NotEqual(t, "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", sanitized.SecretAccessKey) - + // Identity Store fields should be preserved assert.Equal(t, "d-1234567890", sanitized.IdentityStoreId) assert.Equal(t, "us-west-2", sanitized.IdentityStoreRegion) - + // Other fields should be preserved assert.Equal(t, "AKIAIOSFODNN7EXAMPLE", sanitized.AccessKeyId) assert.Equal(t, "us-east-1", sanitized.Region) diff --git a/backend/plugins/q_dev/impl/impl.go b/backend/plugins/q_dev/impl/impl.go index 5cf8bf393ad..b2568334be4 100644 --- a/backend/plugins/q_dev/impl/impl.go +++ b/backend/plugins/q_dev/impl/impl.go @@ -19,6 +19,7 @@ package impl import ( "fmt" + "github.com/apache/incubator-devlake/core/context" "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" diff --git a/backend/plugins/q_dev/models/migrationscripts/archived/user_metrics.go b/backend/plugins/q_dev/models/migrationscripts/archived/user_metrics.go index d26b75aea0b..be948feea3f 100644 --- a/backend/plugins/q_dev/models/migrationscripts/archived/user_metrics.go +++ b/backend/plugins/q_dev/models/migrationscripts/archived/user_metrics.go @@ -18,8 +18,9 @@ limitations under the License. package archived import ( - "github.com/apache/incubator-devlake/core/models/migrationscripts/archived" "time" + + "github.com/apache/incubator-devlake/core/models/migrationscripts/archived" ) // QDevUserMetrics 存储按用户聚合的指标数据 diff --git a/backend/plugins/q_dev/models/user_data_test.go b/backend/plugins/q_dev/models/user_data_test.go index d45d1748fec..74d5dfcfeea 100644 --- a/backend/plugins/q_dev/models/user_data_test.go +++ b/backend/plugins/q_dev/models/user_data_test.go @@ -20,7 +20,7 @@ package models import ( "testing" "time" - + "github.com/stretchr/testify/assert" ) @@ -28,59 +28,59 @@ func TestQDevUserDataAllMetrics(t *testing.T) { // Create a test user data object with all metrics userData := &QDevUserData{ ConnectionId: 1, - UserId: "test-user-id", - Date: time.Now(), - DisplayName: "Test User", - + UserId: "test-user-id", + Date: time.Now(), + DisplayName: "Test User", + // Set values for existing metrics - CodeReview_FindingsCount: 10, - CodeReview_SucceededEventCount: 11, - InlineChat_AcceptanceEventCount: 12, - InlineChat_AcceptedLineAdditions: 13, - InlineChat_AcceptedLineDeletions: 14, - InlineChat_DismissalEventCount: 15, + CodeReview_FindingsCount: 10, + CodeReview_SucceededEventCount: 11, + InlineChat_AcceptanceEventCount: 12, + InlineChat_AcceptedLineAdditions: 13, + InlineChat_AcceptedLineDeletions: 14, + InlineChat_DismissalEventCount: 15, InlineChat_DismissedLineAdditions: 16, InlineChat_DismissedLineDeletions: 17, - InlineChat_RejectedLineAdditions: 18, - InlineChat_RejectedLineDeletions: 19, - InlineChat_RejectionEventCount: 20, - InlineChat_TotalEventCount: 21, - Inline_AICodeLines: 22, - Inline_AcceptanceCount: 23, - Inline_SuggestionsCount: 24, - + InlineChat_RejectedLineAdditions: 18, + InlineChat_RejectedLineDeletions: 19, + InlineChat_RejectionEventCount: 20, + InlineChat_TotalEventCount: 21, + Inline_AICodeLines: 22, + Inline_AcceptanceCount: 23, + Inline_SuggestionsCount: 24, + // Set values for new metrics - Chat_AICodeLines: 25, - Chat_MessagesInteracted: 26, - Chat_MessagesSent: 27, - CodeFix_AcceptanceEventCount: 28, - CodeFix_AcceptedLines: 29, - CodeFix_GeneratedLines: 30, - CodeFix_GenerationEventCount: 31, - CodeReview_FailedEventCount: 32, - Dev_AcceptanceEventCount: 33, - Dev_AcceptedLines: 34, - Dev_GeneratedLines: 35, - Dev_GenerationEventCount: 36, - DocGeneration_AcceptedFileUpdates: 37, + Chat_AICodeLines: 25, + Chat_MessagesInteracted: 26, + Chat_MessagesSent: 27, + CodeFix_AcceptanceEventCount: 28, + CodeFix_AcceptedLines: 29, + CodeFix_GeneratedLines: 30, + CodeFix_GenerationEventCount: 31, + CodeReview_FailedEventCount: 32, + Dev_AcceptanceEventCount: 33, + Dev_AcceptedLines: 34, + Dev_GeneratedLines: 35, + Dev_GenerationEventCount: 36, + DocGeneration_AcceptedFileUpdates: 37, DocGeneration_AcceptedFilesCreations: 38, - DocGeneration_AcceptedLineAdditions: 39, - DocGeneration_AcceptedLineUpdates: 40, - DocGeneration_EventCount: 41, - DocGeneration_RejectedFileCreations: 42, - DocGeneration_RejectedFileUpdates: 43, - DocGeneration_RejectedLineAdditions: 44, - DocGeneration_RejectedLineUpdates: 45, - TestGeneration_AcceptedLines: 46, - TestGeneration_AcceptedTests: 47, - TestGeneration_EventCount: 48, - TestGeneration_GeneratedLines: 49, - TestGeneration_GeneratedTests: 50, - Transformation_EventCount: 51, - Transformation_LinesGenerated: 52, - Transformation_LinesIngested: 53, + DocGeneration_AcceptedLineAdditions: 39, + DocGeneration_AcceptedLineUpdates: 40, + DocGeneration_EventCount: 41, + DocGeneration_RejectedFileCreations: 42, + DocGeneration_RejectedFileUpdates: 43, + DocGeneration_RejectedLineAdditions: 44, + DocGeneration_RejectedLineUpdates: 45, + TestGeneration_AcceptedLines: 46, + TestGeneration_AcceptedTests: 47, + TestGeneration_EventCount: 48, + TestGeneration_GeneratedLines: 49, + TestGeneration_GeneratedTests: 50, + Transformation_EventCount: 51, + Transformation_LinesGenerated: 52, + Transformation_LinesIngested: 53, } - + // Verify that all metrics are accessible // Existing metrics assert.Equal(t, 10, userData.CodeReview_FindingsCount) @@ -98,7 +98,7 @@ func TestQDevUserDataAllMetrics(t *testing.T) { assert.Equal(t, 22, userData.Inline_AICodeLines) assert.Equal(t, 23, userData.Inline_AcceptanceCount) assert.Equal(t, 24, userData.Inline_SuggestionsCount) - + // New metrics assert.Equal(t, 25, userData.Chat_AICodeLines) assert.Equal(t, 26, userData.Chat_MessagesInteracted) diff --git a/backend/plugins/q_dev/tasks/s3_data_extractor.go b/backend/plugins/q_dev/tasks/s3_data_extractor.go index f091e15b90a..10ab6a7cdca 100644 --- a/backend/plugins/q_dev/tasks/s3_data_extractor.go +++ b/backend/plugins/q_dev/tasks/s3_data_extractor.go @@ -119,7 +119,7 @@ func processCSVData(taskCtx plugin.SubTaskContext, db dal.Dal, reader io.ReadClo // 读取标头 headers, err := csvReader.Read() - fmt.Printf("headers: %+v\n", headers) + taskCtx.GetLogger().Debug("CSV headers: %+v", headers) if err != nil { return errors.Convert(err) } @@ -135,7 +135,7 @@ func processCSVData(taskCtx plugin.SubTaskContext, db dal.Dal, reader io.ReadClo } // 创建用户数据对象 (updated to include display name resolution) - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, data.IdentityClient) + userData, err := createUserDataWithDisplayName(taskCtx.GetLogger(), headers, record, fileMeta, data.IdentityClient) if err != nil { return errors.Default.Wrap(err, "failed to create user data") } @@ -156,7 +156,9 @@ type UserDisplayNameResolver interface { } // 从CSV记录创建用户数据对象 (enhanced with display name resolution) -func createUserDataWithDisplayName(headers []string, record []string, fileMeta *models.QDevS3FileMeta, identityClient UserDisplayNameResolver) (*models.QDevUserData, errors.Error) { +func createUserDataWithDisplayName(logger interface { + Debug(format string, a ...interface{}) +}, headers []string, record []string, fileMeta *models.QDevS3FileMeta, identityClient UserDisplayNameResolver) (*models.QDevUserData, errors.Error) { userData := &models.QDevUserData{ ConnectionId: fileMeta.ConnectionId, } @@ -165,13 +167,12 @@ func createUserDataWithDisplayName(headers []string, record []string, fileMeta * fieldMap := make(map[string]string) for i, header := range headers { if i < len(record) { - // 打印每个header和对应的值,帮助调试 - fmt.Printf("Mapping header[%d]: '%s' -> '%s'\n", i, header, record[i]) + logger.Debug("Mapping header[%d]: '%s' -> '%s'", i, header, record[i]) fieldMap[header] = record[i] // 同时添加去除空格的版本 trimmedHeader := strings.TrimSpace(header) if trimmedHeader != header { - fmt.Printf("Also adding trimmed header: '%s'\n", trimmedHeader) + logger.Debug("Also adding trimmed header: '%s'", trimmedHeader) fieldMap[trimmedHeader] = record[i] } } @@ -188,7 +189,7 @@ func createUserDataWithDisplayName(headers []string, record []string, fileMeta * } // 设置DisplayName (new functionality) - userData.DisplayName = resolveDisplayName(userData.UserId, identityClient) + userData.DisplayName = resolveDisplayName(logger, userData.UserId, identityClient) // 设置Date dateStr, ok := fieldMap["Date"] @@ -251,7 +252,9 @@ func createUserDataWithDisplayName(headers []string, record []string, fileMeta * } // resolveDisplayName resolves user ID to display name using Identity Client -func resolveDisplayName(userId string, identityClient UserDisplayNameResolver) string { +func resolveDisplayName(logger interface { + Debug(format string, a ...interface{}) +}, userId string, identityClient UserDisplayNameResolver) string { // If no identity client available, use userId as fallback if identityClient == nil { return userId @@ -261,7 +264,7 @@ func resolveDisplayName(userId string, identityClient UserDisplayNameResolver) s displayName, err := identityClient.ResolveUserDisplayName(userId) if err != nil { // Log error but continue with userId as fallback - fmt.Printf("Failed to resolve display name for user %s: %v\n", userId, err) + logger.Debug("Failed to resolve display name for user %s: %v", userId, err) return userId } diff --git a/backend/plugins/q_dev/tasks/s3_data_extractor_test.go b/backend/plugins/q_dev/tasks/s3_data_extractor_test.go index 1e84e81ef05..fbea299dc28 100644 --- a/backend/plugins/q_dev/tasks/s3_data_extractor_test.go +++ b/backend/plugins/q_dev/tasks/s3_data_extractor_test.go @@ -40,18 +40,32 @@ func (m *MockIdentityClient) ResolveUserDisplayName(userId string) (string, erro // Ensure MockIdentityClient implements UserDisplayNameResolver var _ UserDisplayNameResolver = (*MockIdentityClient)(nil) +// MockLogger is a mock implementation of the logger interface for testing +type MockLogger struct { + mock.Mock +} + +func (m *MockLogger) Debug(format string, args ...interface{}) { + m.Called(format, args) +} + func TestCreateUserDataWithDisplayName_Success(t *testing.T) { headers := []string{"UserId", "Date", "CodeReview_FindingsCount", "Inline_AcceptanceCount"} record := []string{"user-123", "2025-06-23", "5", "10"} fileMeta := &models.QDevS3FileMeta{ ConnectionId: 1, } - + mockIdentityClient := &MockIdentityClient{} mockIdentityClient.On("ResolveUserDisplayName", "user-123").Return("John Doe", nil) - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, mockIdentityClient) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, mockIdentityClient) + assert.NoError(t, err) assert.NotNil(t, userData) assert.Equal(t, "user-123", userData.UserId) @@ -59,7 +73,7 @@ func TestCreateUserDataWithDisplayName_Success(t *testing.T) { assert.Equal(t, uint64(1), userData.ConnectionId) assert.Equal(t, 5, userData.CodeReview_FindingsCount) assert.Equal(t, 10, userData.Inline_AcceptanceCount) - + mockIdentityClient.AssertExpectations(t) } @@ -69,17 +83,23 @@ func TestCreateUserDataWithDisplayName_FallbackToUUID(t *testing.T) { fileMeta := &models.QDevS3FileMeta{ ConnectionId: 1, } - + mockIdentityClient := &MockIdentityClient{} mockIdentityClient.On("ResolveUserDisplayName", "user-456").Return("user-456", assert.AnError) - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, mockIdentityClient) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Failed to resolve display name for user %s: %v", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, mockIdentityClient) + assert.NoError(t, err) assert.NotNil(t, userData) assert.Equal(t, "user-456", userData.UserId) assert.Equal(t, "user-456", userData.DisplayName) // Should fallback to UUID - + mockIdentityClient.AssertExpectations(t) } @@ -89,9 +109,14 @@ func TestCreateUserDataWithDisplayName_NoIdentityClient(t *testing.T) { fileMeta := &models.QDevS3FileMeta{ ConnectionId: 1, } - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, nil) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, nil) + assert.NoError(t, err) assert.NotNil(t, userData) assert.Equal(t, "user-789", userData.UserId) @@ -104,17 +129,22 @@ func TestCreateUserDataWithDisplayName_EmptyDisplayName(t *testing.T) { fileMeta := &models.QDevS3FileMeta{ ConnectionId: 1, } - + mockIdentityClient := &MockIdentityClient{} mockIdentityClient.On("ResolveUserDisplayName", "user-empty").Return("", nil) - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, mockIdentityClient) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, mockIdentityClient) + assert.NoError(t, err) assert.NotNil(t, userData) assert.Equal(t, "user-empty", userData.UserId) assert.Equal(t, "user-empty", userData.DisplayName) // Should fallback when empty - + mockIdentityClient.AssertExpectations(t) } @@ -134,24 +164,29 @@ func TestCreateUserDataWithDisplayName_AllExistingMetrics(t *testing.T) { fileMeta := &models.QDevS3FileMeta{ ConnectionId: 123, } - + mockIdentityClient := &MockIdentityClient{} mockIdentityClient.On("ResolveUserDisplayName", "test-user").Return("Test User", nil) - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, mockIdentityClient) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, mockIdentityClient) + assert.NoError(t, err) assert.NotNil(t, userData) - + // Verify basic fields assert.Equal(t, "test-user", userData.UserId) assert.Equal(t, "Test User", userData.DisplayName) assert.Equal(t, uint64(123), userData.ConnectionId) - + // Verify date parsing expectedDate, _ := time.Parse("2006-01-02", "2025-06-23") assert.Equal(t, expectedDate, userData.Date) - + // Verify all existing metric fields assert.Equal(t, 1, userData.CodeReview_FindingsCount) assert.Equal(t, 2, userData.CodeReview_SucceededEventCount) @@ -168,7 +203,7 @@ func TestCreateUserDataWithDisplayName_AllExistingMetrics(t *testing.T) { assert.Equal(t, 13, userData.Inline_AICodeLines) assert.Equal(t, 14, userData.Inline_AcceptanceCount) assert.Equal(t, 15, userData.Inline_SuggestionsCount) - + mockIdentityClient.AssertExpectations(t) } @@ -186,30 +221,35 @@ func TestCreateUserDataWithDisplayName_AllNewMetrics(t *testing.T) { "TestGeneration_GeneratedLines", "TestGeneration_GeneratedTests", "Transformation_EventCount", "Transformation_LinesGenerated", "Transformation_LinesIngested", } - + record := []string{ "test-user", "2025-06-23", "101", "102", "103", "104", "105", "106", "107", "108", "109", "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", } - + fileMeta := &models.QDevS3FileMeta{ ConnectionId: 123, } - + mockIdentityClient := &MockIdentityClient{} mockIdentityClient.On("ResolveUserDisplayName", "test-user").Return("Test User", nil) - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, mockIdentityClient) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, mockIdentityClient) + assert.NoError(t, err) assert.NotNil(t, userData) - + // Verify basic fields assert.Equal(t, "test-user", userData.UserId) assert.Equal(t, "Test User", userData.DisplayName) - + // Verify all new metric fields assert.Equal(t, 101, userData.Chat_AICodeLines) assert.Equal(t, 102, userData.Chat_MessagesInteracted) @@ -240,7 +280,7 @@ func TestCreateUserDataWithDisplayName_AllNewMetrics(t *testing.T) { assert.Equal(t, 127, userData.Transformation_EventCount) assert.Equal(t, 128, userData.Transformation_LinesGenerated) assert.Equal(t, 129, userData.Transformation_LinesIngested) - + mockIdentityClient.AssertExpectations(t) } @@ -248,60 +288,70 @@ func TestCreateUserDataWithDisplayName_MissingMetrics(t *testing.T) { // Only provide a few metrics in the CSV headers := []string{"UserId", "Date", "CodeReview_FindingsCount", "Chat_AICodeLines"} record := []string{"test-user", "2025-06-23", "42", "99"} - + fileMeta := &models.QDevS3FileMeta{ ConnectionId: 123, } - + mockIdentityClient := &MockIdentityClient{} mockIdentityClient.On("ResolveUserDisplayName", "test-user").Return("Test User", nil) - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, mockIdentityClient) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, mockIdentityClient) + assert.NoError(t, err) assert.NotNil(t, userData) - + // Verify provided metrics are set correctly assert.Equal(t, 42, userData.CodeReview_FindingsCount) assert.Equal(t, 99, userData.Chat_AICodeLines) - + // Verify missing metrics are set to 0 assert.Equal(t, 0, userData.CodeReview_SucceededEventCount) assert.Equal(t, 0, userData.InlineChat_AcceptanceEventCount) assert.Equal(t, 0, userData.Chat_MessagesInteracted) assert.Equal(t, 0, userData.TestGeneration_AcceptedTests) assert.Equal(t, 0, userData.Transformation_LinesIngested) - + mockIdentityClient.AssertExpectations(t) } func TestCreateUserDataWithDisplayName_InvalidMetricValues(t *testing.T) { headers := []string{ - "UserId", "Date", "CodeReview_FindingsCount", "Chat_AICodeLines", + "UserId", "Date", "CodeReview_FindingsCount", "Chat_AICodeLines", "InlineChat_AcceptanceEventCount", "TestGeneration_AcceptedTests", } record := []string{"test-user", "2025-06-23", "42", "not-a-number", "abc", ""} - + fileMeta := &models.QDevS3FileMeta{ ConnectionId: 123, } - + mockIdentityClient := &MockIdentityClient{} mockIdentityClient.On("ResolveUserDisplayName", "test-user").Return("Test User", nil) - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, mockIdentityClient) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, mockIdentityClient) + assert.NoError(t, err) assert.NotNil(t, userData) - + // Verify valid metric is set correctly assert.Equal(t, 42, userData.CodeReview_FindingsCount) - + // Verify invalid metrics are set to 0 assert.Equal(t, 0, userData.Chat_AICodeLines) assert.Equal(t, 0, userData.InlineChat_AcceptanceEventCount) assert.Equal(t, 0, userData.TestGeneration_AcceptedTests) - + mockIdentityClient.AssertExpectations(t) } @@ -311,9 +361,14 @@ func TestCreateUserDataWithDisplayName_MissingUserId(t *testing.T) { fileMeta := &models.QDevS3FileMeta{ ConnectionId: 1, } - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, nil) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, nil) + assert.Error(t, err) assert.Nil(t, userData) assert.Contains(t, err.Error(), "UserId not found") @@ -325,9 +380,14 @@ func TestCreateUserDataWithDisplayName_MissingDate(t *testing.T) { fileMeta := &models.QDevS3FileMeta{ ConnectionId: 1, } - - userData, err := createUserDataWithDisplayName(headers, record, fileMeta, nil) - + + mockLogger := &MockLogger{} + // Add expectations for Debug calls + mockLogger.On("Debug", "Mapping header[%d]: '%s' -> '%s'", mock.Anything).Return() + mockLogger.On("Debug", "Also adding trimmed header: '%s'", mock.Anything).Return() + + userData, err := createUserDataWithDisplayName(mockLogger, headers, record, fileMeta, nil) + assert.Error(t, err) assert.Nil(t, userData) assert.Contains(t, err.Error(), "Date not found") @@ -346,10 +406,10 @@ func TestParseDate(t *testing.T) { {"2025-07-10T15:04:05Z", time.Date(2025, 7, 10, 15, 4, 5, 0, time.UTC), false}, {"invalid-date", time.Time{}, true}, } - + for _, tc := range testCases { date, err := parseDate(tc.dateStr) - + if tc.expectError { assert.Error(t, err) } else { @@ -361,13 +421,13 @@ func TestParseDate(t *testing.T) { func TestParseInt(t *testing.T) { fieldMap := map[string]string{ - "ValidInt": "42", - "ZeroInt": "0", + "ValidInt": "42", + "ZeroInt": "0", "NegativeInt": "-10", - "InvalidInt": "not-a-number", + "InvalidInt": "not-a-number", "EmptyString": "", } - + assert.Equal(t, 42, parseInt(fieldMap, "ValidInt")) assert.Equal(t, 0, parseInt(fieldMap, "ZeroInt")) assert.Equal(t, -10, parseInt(fieldMap, "NegativeInt"))