1170 lines
38 KiB
Go
1170 lines
38 KiB
Go
package line
|
|
|
|
import (
|
|
"context"
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
channelpkg "github.com/gochat/gochat/internal/channel"
|
|
"github.com/gochat/gochat/internal/model"
|
|
)
|
|
|
|
// ===========================
|
|
// resolveSourceID tests
|
|
// ===========================
|
|
|
|
func TestResolveSourceID_User_Cov7(t *testing.T) {
|
|
source := EventSource{Type: "user", UserID: "U123"}
|
|
assert.Equal(t, "U123", resolveSourceID(source))
|
|
}
|
|
|
|
func TestResolveSourceID_Group_Cov7(t *testing.T) {
|
|
source := EventSource{Type: "group", GroupID: "G123"}
|
|
assert.Equal(t, "G123", resolveSourceID(source))
|
|
}
|
|
|
|
func TestResolveSourceID_Room_Cov7(t *testing.T) {
|
|
source := EventSource{Type: "room", RoomID: "R123"}
|
|
assert.Equal(t, "R123", resolveSourceID(source))
|
|
}
|
|
|
|
func TestResolveSourceID_UserPriority_Cov7(t *testing.T) {
|
|
source := EventSource{Type: "user", UserID: "U123", GroupID: "G123"}
|
|
assert.Equal(t, "U123", resolveSourceID(source))
|
|
}
|
|
|
|
func TestResolveSourceID_GroupPriority_Cov7(t *testing.T) {
|
|
source := EventSource{Type: "group", GroupID: "G123", RoomID: "R123"}
|
|
assert.Equal(t, "G123", resolveSourceID(source))
|
|
}
|
|
|
|
func TestResolveSourceID_Empty_Cov7(t *testing.T) {
|
|
source := EventSource{}
|
|
assert.Equal(t, "", resolveSourceID(source))
|
|
}
|
|
|
|
// ===========================
|
|
// parseInboxConfig tests
|
|
// ===========================
|
|
|
|
func TestParseInboxConfig_Empty_Cov7(t *testing.T) {
|
|
result := parseInboxConfig("")
|
|
assert.Empty(t, result)
|
|
}
|
|
|
|
func TestParseInboxConfig_Valid_Cov7(t *testing.T) {
|
|
result := parseInboxConfig(`{"key":"value"}`)
|
|
assert.Equal(t, "value", result["key"])
|
|
}
|
|
|
|
func TestParseInboxConfig_Invalid_Cov7(t *testing.T) {
|
|
result := parseInboxConfig("invalid json")
|
|
assert.Empty(t, result)
|
|
}
|
|
|
|
// ===========================
|
|
// configStr tests
|
|
// ===========================
|
|
|
|
func TestConfigStr_Found_Cov7(t *testing.T) {
|
|
config := channelpkg.ChannelConfig{"key": "value"}
|
|
assert.Equal(t, "value", configStr(config, "key", "default"))
|
|
}
|
|
|
|
func TestConfigStr_NotFound_Cov7(t *testing.T) {
|
|
config := channelpkg.ChannelConfig{}
|
|
assert.Equal(t, "default", configStr(config, "key", "default"))
|
|
}
|
|
|
|
func TestConfigStr_EmptyValue_Cov7(t *testing.T) {
|
|
config := channelpkg.ChannelConfig{"key": ""}
|
|
assert.Equal(t, "default", configStr(config, "key", "default"))
|
|
}
|
|
|
|
func TestConfigStr_NonString_Cov7(t *testing.T) {
|
|
config := channelpkg.ChannelConfig{"key": 123}
|
|
assert.Equal(t, "default", configStr(config, "key", "default"))
|
|
}
|
|
|
|
// ===========================
|
|
// LineService.VerifySignature tests
|
|
// ===========================
|
|
|
|
func TestVerifySignature_Valid_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
secret := "test-secret"
|
|
body := `{"events":[]}`
|
|
// Compute correct signature
|
|
mac := hmacSHA256(secret, body)
|
|
assert.True(t, s.VerifySignature(secret, body, mac))
|
|
}
|
|
|
|
func TestVerifySignature_Invalid_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
assert.False(t, s.VerifySignature("secret", "body", "invalid-signature"))
|
|
}
|
|
|
|
func TestVerifySignature_EmptyBody_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
mac := hmacSHA256("secret", "")
|
|
assert.True(t, s.VerifySignature("secret", "", mac))
|
|
}
|
|
|
|
func TestVerifySignature_WrongSecret_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
body := `{"events":[]}`
|
|
mac := hmacSHA256("correct-secret", body)
|
|
assert.False(t, s.VerifySignature("wrong-secret", body, mac))
|
|
}
|
|
|
|
func TestVerifySignature_EmptySignature_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
assert.False(t, s.VerifySignature("secret", "body", ""))
|
|
}
|
|
|
|
// ===========================
|
|
// WebhookEvent struct tests
|
|
// ===========================
|
|
|
|
func TestWebhookEvent_JSON_Cov7(t *testing.T) {
|
|
event := WebhookEvent{
|
|
Destination: "dest123",
|
|
Events: []EventObject{
|
|
{Type: "message", ReplyToken: "token123"},
|
|
},
|
|
}
|
|
data, err := json.Marshal(event)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "dest123")
|
|
assert.Contains(t, string(data), "message")
|
|
}
|
|
|
|
func TestWebhookEvent_Unmarshal_Cov7(t *testing.T) {
|
|
jsonStr := `{"destination":"dest","events":[{"type":"message","replyToken":"rt"}]}`
|
|
var event WebhookEvent
|
|
err := json.Unmarshal([]byte(jsonStr), &event)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "dest", event.Destination)
|
|
assert.Len(t, event.Events, 1)
|
|
assert.Equal(t, "message", event.Events[0].Type)
|
|
}
|
|
|
|
func TestWebhookEvent_Empty_Cov7(t *testing.T) {
|
|
jsonStr := `{"destination":"","events":[]}`
|
|
var event WebhookEvent
|
|
err := json.Unmarshal([]byte(jsonStr), &event)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, event.Events)
|
|
}
|
|
|
|
// ===========================
|
|
// EventObject struct tests
|
|
// ===========================
|
|
|
|
func TestEventObject_JSON_Cov7(t *testing.T) {
|
|
event := EventObject{
|
|
Type: "message",
|
|
ReplyToken: "token",
|
|
Timestamp: 1234567890,
|
|
Mode: "active",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
}
|
|
data, err := json.Marshal(event)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "message")
|
|
assert.Contains(t, string(data), "U123")
|
|
}
|
|
|
|
// ===========================
|
|
// EventSource struct tests
|
|
// ===========================
|
|
|
|
func TestEventSource_JSON_Cov7(t *testing.T) {
|
|
source := EventSource{Type: "user", UserID: "U123", GroupID: "G456", RoomID: "R789"}
|
|
data, err := json.Marshal(source)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "U123")
|
|
assert.Contains(t, string(data), "G456")
|
|
}
|
|
|
|
// ===========================
|
|
// Message type struct tests
|
|
// ===========================
|
|
|
|
func TestTextMessageContent_JSON_Cov7(t *testing.T) {
|
|
msg := TextMessageContent{Type: "text", ID: "msg1", Text: "hello"}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "hello")
|
|
}
|
|
|
|
func TestImageMessageContent_JSON_Cov7(t *testing.T) {
|
|
msg := ImageMessageContent{Type: "image", ID: "msg1", OriginalContentURL: "http://img", PreviewImageURL: "http://prev"}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "image")
|
|
}
|
|
|
|
func TestVideoMessageContent_JSON_Cov7(t *testing.T) {
|
|
msg := VideoMessageContent{Type: "video", ID: "msg1", OriginalContentURL: "http://vid", PreviewImageURL: "http://prev"}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "video")
|
|
}
|
|
|
|
func TestStickerMessageContent_JSON_Cov7(t *testing.T) {
|
|
msg := StickerMessageContent{Type: "sticker", ID: "msg1", PackageID: "pkg1", StickerID: "stk1", StickerResourceType: "STATIC"}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "sticker")
|
|
}
|
|
|
|
func TestLocationMessageContent_JSON_Cov7(t *testing.T) {
|
|
msg := LocationMessageContent{Type: "location", ID: "msg1", Title: "T", Address: "A", Latitude: 35.6, Longitude: 139.7}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "location")
|
|
}
|
|
|
|
func TestAudioMessageContent_JSON_Cov7(t *testing.T) {
|
|
msg := AudioMessageContent{Type: "audio", ID: "msg1", OriginalContentURL: "http://audio", Duration: 5000}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "audio")
|
|
}
|
|
|
|
func TestFileMessageContent_JSON_Cov7(t *testing.T) {
|
|
msg := FileMessageContent{Type: "file", ID: "msg1", FileName: "doc.pdf", FileSize: 1024}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "file")
|
|
}
|
|
|
|
// ===========================
|
|
// PostbackData / BeaconData / JoinedMembers / LeftMembers tests
|
|
// ===========================
|
|
|
|
func TestPostbackData_JSON_Cov7(t *testing.T) {
|
|
data := PostbackData{Data: "action=buy&id=1"}
|
|
d, err := json.Marshal(data)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(d), "action=buy")
|
|
}
|
|
|
|
func TestBeaconData_JSON_Cov7(t *testing.T) {
|
|
data := BeaconData{Hwid: "hw1", Type: "enter", DeviceMessage: "msg"}
|
|
d, err := json.Marshal(data)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(d), "enter")
|
|
}
|
|
|
|
func TestJoinedMembers_JSON_Cov7(t *testing.T) {
|
|
data := JoinedMembers{Members: []EventSource{{Type: "user", UserID: "U1"}}}
|
|
d, err := json.Marshal(data)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(d), "U1")
|
|
}
|
|
|
|
func TestLeftMembers_JSON_Cov7(t *testing.T) {
|
|
data := LeftMembers{Members: []EventSource{{Type: "user", UserID: "U1"}}}
|
|
d, err := json.Marshal(data)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(d), "U1")
|
|
}
|
|
|
|
// ===========================
|
|
// Outbound message type tests
|
|
// ===========================
|
|
|
|
func TestReplyMessageRequest_JSON_Cov7(t *testing.T) {
|
|
req := ReplyMessageRequest{ReplyToken: "rt", Messages: []OutboundMsg{{Type: "text", Text: "hi"}}}
|
|
data, err := json.Marshal(req)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "rt")
|
|
assert.Contains(t, string(data), "hi")
|
|
}
|
|
|
|
func TestPushMessageRequest_JSON_Cov7(t *testing.T) {
|
|
req := PushMessageRequest{To: "U123", Messages: []OutboundMsg{{Type: "text", Text: "hi"}}}
|
|
data, err := json.Marshal(req)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "U123")
|
|
}
|
|
|
|
func TestOutboundMsg_Text_Cov7(t *testing.T) {
|
|
msg := OutboundMsg{Type: "text", Text: "hello"}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "hello")
|
|
}
|
|
|
|
func TestOutboundMsg_Image_Cov7(t *testing.T) {
|
|
msg := OutboundMsg{Type: "image", OriginalContentURL: "http://img", PreviewImageURL: "http://prev"}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "image")
|
|
}
|
|
|
|
func TestOutboundMsg_Sticker_Cov7(t *testing.T) {
|
|
msg := OutboundMsg{Type: "sticker", PackageID: "pkg", StickerID: "stk"}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "sticker")
|
|
}
|
|
|
|
func TestOutboundMsg_Location_Cov7(t *testing.T) {
|
|
msg := OutboundMsg{Type: "location", Title: "T", Address: "A", Latitude: 35.6, Longitude: 139.7}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "location")
|
|
}
|
|
|
|
// ===========================
|
|
// UserProfile struct tests
|
|
// ===========================
|
|
|
|
func TestUserProfile_JSON_Cov7(t *testing.T) {
|
|
profile := UserProfile{
|
|
UserID: "U123",
|
|
DisplayName: "Test User",
|
|
PictureURL: "http://pic",
|
|
StatusMessage: "Hello",
|
|
Language: "en",
|
|
}
|
|
data, err := json.Marshal(profile)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "U123")
|
|
assert.Contains(t, string(data), "Test User")
|
|
}
|
|
|
|
// ===========================
|
|
// PushMessageResponse / ReplyMessageResponse tests
|
|
// ===========================
|
|
|
|
func TestPushMessageResponse_JSON_Cov7(t *testing.T) {
|
|
resp := PushMessageResponse{Status: 200, Message: "OK"}
|
|
data, err := json.Marshal(resp)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "200")
|
|
}
|
|
|
|
func TestReplyMessageResponse_JSON_Cov7(t *testing.T) {
|
|
resp := ReplyMessageResponse{Status: 200, Message: "OK"}
|
|
data, err := json.Marshal(resp)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "200")
|
|
}
|
|
|
|
// ===========================
|
|
// WebhookHandler tests
|
|
// ===========================
|
|
|
|
func TestNewWebhookHandler_Cov7(t *testing.T) {
|
|
h := NewWebhookHandler(nil, nil)
|
|
require.NotNil(t, h)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhookVerification_Cov7(t *testing.T) {
|
|
h := NewWebhookHandler(nil, nil)
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest("GET", "/webhook/verify", nil)
|
|
h.HandleWebhookVerification(w, r)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_EmptyBody_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
h := NewWebhookHandler(nil, s)
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest("POST", "/webhook", nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
func() {
|
|
defer func() { recover() }()
|
|
h.HandleWebhook(w, r, inbox)
|
|
}()
|
|
// nil body causes io.ReadAll to return empty, then JSON parse fails → 400
|
|
// Actually nil Body in http.NewRequest is replaced with http.NoBody
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_InvalidJSON_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
h := NewWebhookHandler(nil, s)
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader("invalid json"))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
assert.Contains(t, w.Body.String(), "Invalid JSON")
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_ValidNoEvents_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
h := NewWebhookHandler(nil, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_ValidWithEvents_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
pipeline := NewIncomingProcessor(s)
|
|
h := NewWebhookHandler(pipeline, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[{"type":"follow","replyToken":"rt","source":{"type":"user","userId":"U123"}}]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_InvalidSignature_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
h := NewWebhookHandler(nil, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
r.Header.Set("X-Line-Signature", "invalid-signature")
|
|
inbox := &model.Inbox{
|
|
Base: model.Base{ID: 1},
|
|
AccountID: 1,
|
|
ChannelConfig: `{"channel_secret":"mysecret"}`,
|
|
}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
|
assert.Contains(t, w.Body.String(), "Invalid signature")
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_ValidSignature_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
h := NewWebhookHandler(nil, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[]}`
|
|
secret := "mysecret"
|
|
sig := hmacSHA256(secret, body)
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
r.Header.Set("X-Line-Signature", sig)
|
|
inbox := &model.Inbox{
|
|
Base: model.Base{ID: 1},
|
|
AccountID: 1,
|
|
ChannelConfig: `{"channel_secret":"mysecret"}`,
|
|
}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_NoSecret_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
h := NewWebhookHandler(nil, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
r.Header.Set("X-Line-Signature", "sig")
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1, ChannelConfig: `{}`}
|
|
// No channel_secret → signature check is skipped, proceeds to parse
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_ReadError_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
h := NewWebhookHandler(nil, s)
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest("POST", "/webhook", errReaderLine{})
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_MessageEvent_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
pipeline := NewIncomingProcessor(s)
|
|
h := NewWebhookHandler(pipeline, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[{"type":"message","replyToken":"rt","source":{"type":"user","userId":"U123"},"message":{"type":"text","id":"msg1","text":"hello"}}]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_PostbackEvent_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
pipeline := NewIncomingProcessor(s)
|
|
h := NewWebhookHandler(pipeline, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[{"type":"postback","replyToken":"rt","source":{"type":"user","userId":"U123"},"postback":{"data":"action=test"}}]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_UnfollowEvent_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
pipeline := NewIncomingProcessor(s)
|
|
h := NewWebhookHandler(pipeline, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[{"type":"unfollow","source":{"type":"user","userId":"U123"}}]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_UnknownEvent_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
pipeline := NewIncomingProcessor(s)
|
|
h := NewWebhookHandler(pipeline, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[{"type":"unknown","source":{"type":"user","userId":"U123"}}]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
func TestWebhookHandler_HandleWebhook_NoSourceID_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
pipeline := NewIncomingProcessor(s)
|
|
h := NewWebhookHandler(pipeline, s)
|
|
w := httptest.NewRecorder()
|
|
body := `{"destination":"dest","events":[{"type":"message","replyToken":"rt","source":{}}]}`
|
|
r := httptest.NewRequest("POST", "/webhook", strings.NewReader(body))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
h.HandleWebhook(w, r, inbox)
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
}
|
|
|
|
// ===========================
|
|
// IncomingProcessor tests
|
|
// ===========================
|
|
|
|
func TestNewIncomingProcessor_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
require.NotNil(t, p)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Message_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
ReplyToken: "rt",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"text","id":"msg1","text":"hello"}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Equal(t, "hello", msg.Content)
|
|
assert.Equal(t, channelpkg.ContentText, msg.ContentType)
|
|
assert.Equal(t, "U123", msg.SenderID)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Image_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"image","id":"msg1","originalContentUrl":"http://img"}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Equal(t, channelpkg.ContentImage, msg.ContentType)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Video_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"video","id":"msg1","originalContentUrl":"http://vid"}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, channelpkg.ContentVideo, msg.ContentType)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Audio_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"audio","id":"msg1","originalContentUrl":"http://audio","duration":5000}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, channelpkg.ContentAudio, msg.ContentType)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_File_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"file","id":"msg1","fileName":"doc.pdf","fileSize":1024,"originalContentUrl":"http://file"}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, channelpkg.ContentFile, msg.ContentType)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Location_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"location","id":"msg1","title":"T","address":"A","latitude":35.6,"longitude":139.7}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, channelpkg.ContentLocation, msg.ContentType)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Sticker_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"sticker","id":"msg1","packageId":"pkg","stickerId":"stk"}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, channelpkg.ContentText, msg.ContentType)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_UnknownMessage_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"unknown","id":"msg1"}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, msg)
|
|
assert.Contains(t, msg.Content, "Unsupported")
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_InvalidMessageJSON_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`invalid`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.Error(t, err)
|
|
assert.Nil(t, msg)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Follow_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "follow",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, msg)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Unfollow_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "unfollow",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, msg)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_Postback_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "postback",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Postback: &PostbackData{Data: "action=test"},
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Equal(t, "action=test", msg.Content)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_PostbackNil_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "postback",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Postback: nil,
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Equal(t, "", msg.Content)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_UnknownType_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "unknown",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, msg)
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_NoSourceID_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
Source: EventSource{},
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.Error(t, err)
|
|
assert.Nil(t, msg)
|
|
assert.Contains(t, err.Error(), "no source ID")
|
|
}
|
|
|
|
func TestIncomingProcessor_ProcessEvent_ReplyToken_Cov7(t *testing.T) {
|
|
p := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
event := EventObject{
|
|
Type: "message",
|
|
ReplyToken: "reply_token_123",
|
|
Source: EventSource{Type: "user", UserID: "U123"},
|
|
Message: json.RawMessage(`{"type":"text","id":"msg1","text":"hello"}`),
|
|
}
|
|
msg, err := p.ProcessEvent(context.Background(), inbox, event)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Equal(t, "reply_token_123", msg.Extra["reply_token"])
|
|
}
|
|
|
|
// ===========================
|
|
// OutgoingProcessor tests
|
|
// ===========================
|
|
|
|
func TestNewOutgoingProcessor_Cov7(t *testing.T) {
|
|
p := NewOutgoingProcessor(nil)
|
|
require.NotNil(t, p)
|
|
}
|
|
|
|
func TestOutgoingProcessor_SendMessage_NoSourceID_Cov7(t *testing.T) {
|
|
p := NewOutgoingProcessor(NewLineService(nil))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1, ChannelConfig: `{}`}
|
|
msg := &model.Message{Content: "hello"}
|
|
contact := &model.Contact{SourceID: ""}
|
|
_, err := p.SendMessage(context.Background(), inbox, msg, contact)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "no source_id")
|
|
}
|
|
|
|
// ===========================
|
|
// EventBridge tests
|
|
// ===========================
|
|
|
|
func TestNewEventBridge_Cov7(t *testing.T) {
|
|
b := NewEventBridge(nil)
|
|
require.NotNil(t, b)
|
|
}
|
|
|
|
func TestEventBridge_OnMessageCreated_NoSourceID_Cov7(t *testing.T) {
|
|
b := NewEventBridge(NewOutgoingProcessor(NewLineService(nil)))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1, ChannelConfig: `{}`}
|
|
msg := &model.Message{Content: "hello"}
|
|
contact := &model.Contact{SourceID: ""}
|
|
_, err := b.OnMessageCreated(context.Background(), inbox, msg, contact)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
// ===========================
|
|
// LineProvider tests
|
|
// ===========================
|
|
|
|
func TestNewLineProvider_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
require.NotNil(t, p)
|
|
}
|
|
|
|
func TestLineProvider_Type_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
assert.Equal(t, channelpkg.ChannelLine, p.Type())
|
|
}
|
|
|
|
func TestLineProvider_Name_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
assert.Equal(t, "LINE", p.Name())
|
|
}
|
|
|
|
func TestLineProvider_Description_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
desc := p.Description()
|
|
assert.Contains(t, desc, "LINE")
|
|
}
|
|
|
|
func TestLineProvider_ConfigSchema_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
schema := p.ConfigSchema()
|
|
require.NotNil(t, schema)
|
|
assert.Contains(t, schema.Properties, "channel_access_token")
|
|
assert.Contains(t, schema.Properties, "channel_secret")
|
|
}
|
|
|
|
func TestLineProvider_ValidateConfig_Valid_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
config := channelpkg.ChannelConfig{
|
|
"channel_access_token": "token",
|
|
"channel_secret": "secret",
|
|
}
|
|
err := p.ValidateConfig(context.Background(), config)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestLineProvider_ValidateConfig_NoToken_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
config := channelpkg.ChannelConfig{
|
|
"channel_secret": "secret",
|
|
}
|
|
err := p.ValidateConfig(context.Background(), config)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "channel_access_token")
|
|
}
|
|
|
|
func TestLineProvider_ValidateConfig_NoSecret_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
config := channelpkg.ChannelConfig{
|
|
"channel_access_token": "token",
|
|
}
|
|
err := p.ValidateConfig(context.Background(), config)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "channel_secret")
|
|
}
|
|
|
|
func TestLineProvider_ValidateConfig_Empty_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{})
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestLineProvider_DefaultConfig_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
config := p.DefaultConfig()
|
|
assert.Contains(t, config, "channel_access_token")
|
|
assert.Contains(t, config, "channel_secret")
|
|
}
|
|
|
|
func TestLineProvider_OnDestroy_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
err := p.OnDestroy(context.Background(), &model.Inbox{}, channelpkg.ChannelConfig{})
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestLineProvider_Capabilities_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, nil)
|
|
caps := p.Capabilities()
|
|
assert.True(t, caps.SupportsAttachments)
|
|
assert.True(t, caps.SupportsLocation)
|
|
assert.True(t, caps.SupportsReplies)
|
|
assert.True(t, caps.SupportsVoiceMessages)
|
|
assert.True(t, caps.SupportsCustomCards)
|
|
assert.True(t, caps.SupportsTemplates)
|
|
assert.False(t, caps.SupportsTypingIndicator)
|
|
assert.False(t, caps.SupportsDeliveryStatus)
|
|
}
|
|
|
|
func TestLineProvider_ProcessIncoming_InvalidJSON_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, NewIncomingProcessor(nil))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
_, err := p.ProcessIncoming(context.Background(), inbox, []byte("invalid json"))
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "failed to parse payload")
|
|
}
|
|
|
|
func TestLineProvider_ProcessIncoming_NoEvents_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, NewIncomingProcessor(nil))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
payload := `{"destination":"dest","events":[]}`
|
|
_, err := p.ProcessIncoming(context.Background(), inbox, []byte(payload))
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "no events")
|
|
}
|
|
|
|
func TestLineProvider_ProcessIncoming_Valid_Cov7(t *testing.T) {
|
|
p := NewLineProvider(nil, nil, NewIncomingProcessor(nil))
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1}
|
|
payload := `{"destination":"dest","events":[{"type":"message","replyToken":"rt","source":{"type":"user","userId":"U123"},"message":{"type":"text","id":"msg1","text":"hello"}}]}`
|
|
msg, err := p.ProcessIncoming(context.Background(), inbox, []byte(payload))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Equal(t, "hello", msg.Content)
|
|
}
|
|
|
|
func TestLineProvider_ValidateWebhookRequest_NoSecret_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
p := NewLineProvider(s, nil, nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1, ChannelConfig: `{}`}
|
|
req := &channelpkg.WebhookRequest{Body: []byte("{}"), Headers: map[string]string{}}
|
|
err := p.ValidateWebhookRequest(context.Background(), inbox, req)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "channel_secret")
|
|
}
|
|
|
|
func TestLineProvider_ValidateWebhookRequest_NoSignature_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
p := NewLineProvider(s, nil, nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1, ChannelConfig: `{"channel_secret":"secret"}`}
|
|
req := &channelpkg.WebhookRequest{Body: []byte("{}"), Headers: map[string]string{}}
|
|
err := p.ValidateWebhookRequest(context.Background(), inbox, req)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "X-Line-Signature")
|
|
}
|
|
|
|
func TestLineProvider_ValidateWebhookRequest_InvalidSignature_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
p := NewLineProvider(s, nil, nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1, ChannelConfig: `{"channel_secret":"secret"}`}
|
|
req := &channelpkg.WebhookRequest{Body: []byte("{}"), Headers: map[string]string{"X-Line-Signature": "invalid"}}
|
|
err := p.ValidateWebhookRequest(context.Background(), inbox, req)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid HMAC")
|
|
}
|
|
|
|
func TestLineProvider_ValidateWebhookRequest_ValidSignature_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
p := NewLineProvider(s, nil, nil)
|
|
body := `{"events":[]}`
|
|
sig := hmacSHA256("secret", body)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1, ChannelConfig: `{"channel_secret":"secret"}`}
|
|
req := &channelpkg.WebhookRequest{Body: []byte(body), Headers: map[string]string{"X-Line-Signature": sig}}
|
|
err := p.ValidateWebhookRequest(context.Background(), inbox, req)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestLineProvider_SendMessage_NoSourceID_Cov7(t *testing.T) {
|
|
s := NewLineService(nil)
|
|
p := NewLineProvider(s, nil, nil)
|
|
inbox := &model.Inbox{Base: model.Base{ID: 1}, AccountID: 1, ChannelConfig: `{"channel_access_token":"token"}`}
|
|
msg := &model.Message{Content: "hello"}
|
|
contact := &model.Contact{SourceID: ""}
|
|
_, err := p.SendMessage(context.Background(), inbox, msg, contact)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "no source_id")
|
|
}
|
|
|
|
// ===========================
|
|
// LineService tests (API error paths)
|
|
// ===========================
|
|
|
|
func TestLineService_ReplyMessage_NilClient_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
s := &LineService{client: nil}
|
|
_ = s.ReplyMessage(context.Background(), "token", "rt", []OutboundMsg{{Type: "text", Text: "hi"}})
|
|
}()
|
|
}
|
|
|
|
func TestLineService_PushMessage_NilClient_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
s := &LineService{client: nil}
|
|
_, _ = s.PushMessage(context.Background(), "token", "U123", []OutboundMsg{{Type: "text", Text: "hi"}})
|
|
}()
|
|
}
|
|
|
|
func TestLineService_GetUserProfile_NilClient_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
s := &LineService{client: nil}
|
|
_, _ = s.GetUserProfile(context.Background(), "token", "U123")
|
|
}()
|
|
}
|
|
|
|
func TestLineService_ValidateAccessToken_NilClient_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
s := &LineService{client: nil}
|
|
_ = s.ValidateAccessToken(context.Background(), "token")
|
|
}()
|
|
}
|
|
|
|
func TestLineService_UpdateChannel_NilRepo_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
s := &LineService{repo: nil}
|
|
_ = s.UpdateChannel(context.Background(), 1, map[string]interface{}{"key": "value"})
|
|
}()
|
|
}
|
|
|
|
func TestLineService_MarkReauthorizationRequired_NilRepo_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
s := &LineService{repo: nil}
|
|
_ = s.MarkReauthorizationRequired(context.Background(), 1)
|
|
}()
|
|
}
|
|
|
|
// ===========================
|
|
// Repository tests
|
|
// ===========================
|
|
|
|
func TestNewRepository_Cov7(t *testing.T) {
|
|
r := NewRepository(nil)
|
|
require.NotNil(t, r)
|
|
}
|
|
|
|
func TestRepository_FindByID_NilDB_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
r := NewRepository(nil)
|
|
_, _ = r.FindByID(context.Background(), 1)
|
|
}()
|
|
}
|
|
|
|
func TestRepository_FindByChannelID_NilDB_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
r := NewRepository(nil)
|
|
_, _ = r.FindByChannelID(context.Background(), "ch1")
|
|
}()
|
|
}
|
|
|
|
func TestRepository_Create_NilDB_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
r := NewRepository(nil)
|
|
_ = r.Create(context.Background(), nil)
|
|
}()
|
|
}
|
|
|
|
func TestRepository_UpdateFields_NilDB_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
r := NewRepository(nil)
|
|
_ = r.UpdateFields(context.Background(), 1, map[string]interface{}{"key": "val"})
|
|
}()
|
|
}
|
|
|
|
func TestRepository_Delete_NilDB_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
r := NewRepository(nil)
|
|
_ = r.Delete(context.Background(), 1)
|
|
}()
|
|
}
|
|
|
|
func TestRepository_List_NilDB_Cov7(t *testing.T) {
|
|
func() {
|
|
defer func() { recover() }()
|
|
r := NewRepository(nil)
|
|
_, _ = r.List(context.Background(), 1)
|
|
}()
|
|
}
|
|
|
|
// ===========================
|
|
// LineMessage struct test
|
|
// ===========================
|
|
|
|
func TestLineMessage_JSON_Cov7(t *testing.T) {
|
|
msg := LineMessage{Type: "text", ID: "msg1"}
|
|
data, err := json.Marshal(msg)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "text")
|
|
assert.Contains(t, string(data), "msg1")
|
|
}
|
|
|
|
// ===========================
|
|
// Helper functions
|
|
// ===========================
|
|
|
|
// errReaderLine for testing read errors
|
|
type errReaderLine struct{}
|
|
|
|
func (errReaderLine) Read(p []byte) (n int, err error) {
|
|
return 0, io.ErrUnexpectedEOF
|
|
}
|
|
|
|
// hmacSHA256 computes HMAC-SHA256 and returns base64-encoded string
|
|
func hmacSHA256(secret, body string) string {
|
|
mac := hmac.New(sha256.New, []byte(secret))
|
|
mac.Write([]byte(body))
|
|
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
|
}
|
|
|
|
// ===========================
|
|
// Context and misc tests
|
|
// ===========================
|
|
|
|
func TestContext_Cov7(t *testing.T) {
|
|
ctx := context.Background()
|
|
assert.NotNil(t, ctx)
|
|
}
|
|
|
|
func TestStringsContains_Cov7(t *testing.T) {
|
|
assert.True(t, strings.Contains("hello world", "world"))
|
|
}
|
|
|
|
func TestFmtSprintf_Cov7(t *testing.T) {
|
|
assert.Equal(t, "test: 42", fmt.Sprintf("test: %d", 42))
|
|
}
|
|
|
|
func TestFmtErrorf_Cov7(t *testing.T) {
|
|
err := fmt.Errorf("error: %s", "detail")
|
|
assert.Contains(t, err.Error(), "detail")
|
|
}
|
|
|
|
func TestJSONMarshal_Cov7(t *testing.T) {
|
|
data, err := json.Marshal(map[string]string{"key": "value"})
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "key")
|
|
}
|
|
|
|
func TestHTTPNewRequest_Cov7(t *testing.T) {
|
|
req, err := http.NewRequest("GET", "http://example.com", nil)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "GET", req.Method)
|
|
}
|
|
|
|
func TestHTTPTestNewRecorder_Cov7(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
assert.NotNil(t, w)
|
|
}
|
|
|
|
func TestIOReadAll_Cov7(t *testing.T) {
|
|
data, err := io.ReadAll(strings.NewReader("test"))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "test", string(data))
|
|
}
|