package facebook import ( "testing" "github.com/stretchr/testify/assert" ) // TestIsIGCommentEvent verifies that comment event types are correctly identified. func TestIsIGCommentEvent(t *testing.T) { tests := []struct { name string eventType WebhookEventType expected bool }{ {"comment event", EventIGComment, true}, {"comment reply event", EventIGCommentReply, true}, {"comment deleted event", EventIGCommentDeleted, true}, {"FB message event", EventFBMessage, false}, {"IG message event", EventIGMessage, false}, {"IG postback event", EventIGPostback, false}, {"delivery event", EventFBDelivery, false}, {"read event", EventFBRead, false}, {"pass thread event", EventFBPassThread, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { event := &ParsedWebhookEvent{EventType: tt.eventType} assert.Equal(t, tt.expected, IsIGCommentEvent(event)) }) } } // TestParseIGCommentChangeValue verifies parsing of Instagram comment change values // from raw map[string]interface{} (as received from Facebook Graph API webhook). func TestParseIGCommentChangeValue(t *testing.T) { t.Run("new comment", func(t *testing.T) { value := map[string]interface{}{ "from": map[string]interface{}{ "id": "17841400123456789", "username": "testuser", }, "media_id": "18027993912345678", "id": "17870412345678901", "text": "Great photo!", "timestamp": "2023-09-18T12:00:00+0000", } result, err := parseIGCommentChangeValue(value) assert.NoError(t, err) assert.NotNil(t, result) assert.Equal(t, "17841400123456789", result.From.ID) assert.Equal(t, "testuser", result.From.Username) assert.Equal(t, "18027993912345678", result.MediaID) assert.Equal(t, "17870412345678901", result.CommentID) assert.Equal(t, "Great photo!", result.Text) assert.Equal(t, "2023-09-18T12:00:00+0000", result.Timestamp) assert.False(t, result.IsDeleted) }) t.Run("comment reply with parent_id", func(t *testing.T) { value := map[string]interface{}{ "from": map[string]interface{}{ "id": "17841400987654321", "username": "replyuser", }, "media_id": "18027993912345678", "id": "17870498765432109", "text": "Thanks for the comment!", "parent_id": "17870412345678901", "timestamp": "2023-09-18T12:05:00+0000", } result, err := parseIGCommentChangeValue(value) assert.NoError(t, err) assert.NotNil(t, result) assert.Equal(t, "17870498765432109", result.CommentID) assert.Equal(t, "17870412345678901", result.ParentID) assert.Equal(t, "replyuser", result.From.Username) }) t.Run("deleted comment", func(t *testing.T) { value := map[string]interface{}{ "id": "17870412345678901", "media_id": "18027993912345678", "is_deleted": true, "timestamp": "2023-09-18T12:30:00+0000", } result, err := parseIGCommentChangeValue(value) assert.NoError(t, err) assert.NotNil(t, result) assert.Equal(t, "17870412345678901", result.CommentID) assert.Equal(t, "18027993912345678", result.MediaID) assert.True(t, result.IsDeleted) }) t.Run("nil value returns empty struct", func(t *testing.T) { // parseIGCommentChangeValue marshals nil → "null" → unmarshals to empty struct result, err := parseIGCommentChangeValue(nil) // json.Marshal(nil) produces "null", json.Unmarshal("null", &struct) clears it assert.NoError(t, err) assert.NotNil(t, result) assert.Equal(t, "", result.CommentID) assert.Equal(t, "", result.MediaID) }) t.Run("missing from field", func(t *testing.T) { value := map[string]interface{}{ "media_id": "18027993912345678", "id": "17870412345678901", "text": "Hello", } result, err := parseIGCommentChangeValue(value) assert.NoError(t, err) assert.NotNil(t, result) assert.Equal(t, "18027993912345678", result.MediaID) assert.Equal(t, "Hello", result.Text) assert.Equal(t, "", result.From.ID) assert.Equal(t, "", result.From.Username) }) } // TestWebhookParserClassifyCommentEvent tests the classifyChangeEvent method // for Instagram comment changes. func TestWebhookParserClassifyCommentEvent(t *testing.T) { wp := NewWebhookParser() t.Run("new comment classified as EventIGComment", func(t *testing.T) { change := FBChangeEvent{ Field: "comments", Value: map[string]interface{}{ "from": map[string]interface{}{ "id": "17841400123456", "username": " commenter1", }, "media_id": "18027993912345", "id": "17870412345678", "text": "Nice!", }, } result := wp.classifyChangeEvent("instagram", "page123", change, 1695000000000, nil) assert.NotNil(t, result) assert.Equal(t, EventIGComment, result.EventType) assert.Equal(t, "instagram", result.Object) assert.NotNil(t, result.Comment) }) t.Run("comment reply classified as EventIGCommentReply", func(t *testing.T) { change := FBChangeEvent{ Field: "comments", Value: map[string]interface{}{ "from": map[string]interface{}{ "id": "17841400987", "username": "replyer", }, "media_id": "18027993912345", "id": "17870498765432", "text": "Reply text", "parent_id": "17870412345678", }, } result := wp.classifyChangeEvent("instagram", "page123", change, 1695000000000, nil) assert.NotNil(t, result) assert.Equal(t, EventIGCommentReply, result.EventType) assert.NotNil(t, result.Comment) assert.Equal(t, "17870412345678", result.Comment.ParentID) }) t.Run("deleted comment classified as EventIGCommentDeleted", func(t *testing.T) { change := FBChangeEvent{ Field: "comments", Value: map[string]interface{}{ "id": "17870412345678", "media_id": "18027993912345", "is_deleted": true, }, } result := wp.classifyChangeEvent("instagram", "page123", change, 1695000000000, nil) assert.NotNil(t, result) assert.Equal(t, EventIGCommentDeleted, result.EventType) }) }