Files
gochat/internal/channel/facebook/webhook_handler_test.go
T
2026-06-04 15:44:48 +08:00

188 lines
5.8 KiB
Go

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