diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4d8ff29 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.10.x + - master + +go_import_path: github.com/paked/messenger + +install: go get -t ./... +script: go test -v ./... diff --git a/README.md b/README.md index 16c4143..f1e7550 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Messenger [![GoDoc](https://godoc.org/github.com/paked/messenger?status.svg)](https://godoc.org/github.com/paked/messenger) +# Messenger [![GoDoc](https://godoc.org/github.com/paked/messenger?status.svg)](https://godoc.org/github.com/paked/messenger) [![Build Status](https://travis-ci.org/paked/messenger.svg?branch=master)](https://travis-ci.org/paked/messenger) This is a Go library for making bots to be used on Facebook messenger. It is built on the [Messenger Platform](https://developers.facebook.com/docs/messenger-platform). One of the main goals of the project is to implement it in an idiomatic and easy to use fashion. @@ -19,7 +19,7 @@ This is a Go library for making bots to be used on Facebook messenger. It is bui - [23/1/17](https://github.com/paked/messenger/commit/1145fe35249f8ce14d3c0a52544e4a4babdc15a4): Updating timezone type to `float64` in profile struct - [12/9/16](https://github.com/paked/messenger/commit/47f193fc858e2d710c061e88b12dbd804a399e57): Removing unused parameter `text string` from function `(r *Response) GenericTemplate`. - [20/5/16](https://github.com/paked/messenger/commit/1dc4bcc67dec50e2f58436ffbc7d61ca9da5b943): Leaving the `WebhookURL` field blank in `Options` will yield a URL of "/" instead of a panic. -- [4/5/16](https://github.com/paked/messenger/commit/eb0e72a5dcd3bfaffcfe88dced6d6ac5247f9da1): The URL to use for the webhook is changable in the `Options` struct. +- [4/5/16](https://github.com/paked/messenger/commit/eb0e72a5dcd3bfaffcfe88dced6d6ac5247f9da1): The URL to use for the webhook is changable in the `Options` struct. ## Inspiration diff --git a/messenger_test.go b/messenger_test.go new file mode 100644 index 0000000..6a1ba00 --- /dev/null +++ b/messenger_test.go @@ -0,0 +1,297 @@ +package messenger + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestMessenger_Classify(t *testing.T) { + m := New(Options{}) + + for name, test := range map[string]struct { + msgInfo MessageInfo + expected Action + }{ + "unknown": { + msgInfo: MessageInfo{}, + expected: UnknownAction, + }, + "message": { + msgInfo: MessageInfo{ + Message: &Message{}, + }, + expected: TextAction, + }, + "delivery": { + msgInfo: MessageInfo{ + Delivery: &Delivery{}, + }, + expected: DeliveryAction, + }, + "read": { + msgInfo: MessageInfo{ + Read: &Read{}, + }, + expected: ReadAction, + }, + "postback": { + msgInfo: MessageInfo{ + PostBack: &PostBack{}, + }, + expected: PostBackAction, + }, + "optin": { + msgInfo: MessageInfo{ + OptIn: &OptIn{}, + }, + expected: OptInAction, + }, + "referral": { + msgInfo: MessageInfo{ + ReferralMessage: &ReferralMessage{}, + }, + expected: ReferralAction, + }, + } { + t.Run("action "+name, func(t *testing.T) { + action := m.classify(test.msgInfo, Entry{}) + assert.Exactly(t, action, test.expected) + }) + } +} + +func TestMessenger_Dispatch(t *testing.T) { + type handlersCalls struct { + message int + delivery int + optin int + read int + postback int + referral int + } + + assertHandlersCalls := func(t *testing.T, actual *handlersCalls, expected handlersCalls) { + assert.Equal(t, actual.message, expected.message) + assert.Equal(t, actual.delivery, expected.delivery) + assert.Equal(t, actual.optin, expected.optin) + assert.Equal(t, actual.read, expected.read) + assert.Equal(t, actual.postback, expected.postback) + assert.Equal(t, actual.referral, expected.referral) + } + + newReceive := func(msgInfo []MessageInfo) Receive { + return Receive{ + Entry: []Entry{ + { + Messaging: msgInfo, + }, + }, + } + } + + t.Run("message handlers", func(t *testing.T) { + m := &Messenger{} + h := &handlersCalls{} + + handler := func(msg Message, r *Response) { + h.message++ + assert.NotNil(t, r) + assert.EqualValues(t, 111, msg.Sender.ID) + assert.EqualValues(t, 222, msg.Recipient.ID) + assert.Equal(t, time.Unix(1543095111, 0), msg.Time) + } + + messages := []MessageInfo{ + { + Sender: Sender{111}, + Recipient: Recipient{222}, + // 2018-11-24 21:31:51 UTC + 999ms + Timestamp: 1543095111999, + Message: &Message{}, + }, + } + + // First handler + m.HandleMessage(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{message: 1}) + + // Another handler + m.HandleMessage(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{message: 3}) + }) + + t.Run("delivery handlers", func(t *testing.T) { + m := &Messenger{} + h := &handlersCalls{} + + handler := func(_ Delivery, r *Response) { + h.delivery++ + assert.NotNil(t, r) + } + + messages := []MessageInfo{ + { + Sender: Sender{111}, + Recipient: Recipient{222}, + // 2018-11-24 21:31:51 UTC + 999ms + Timestamp: 1543095111999, + Delivery: &Delivery{}, + }, + } + + // First handler + m.HandleDelivery(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{delivery: 1}) + + // Another handler + m.HandleDelivery(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{delivery: 3}) + }) + + t.Run("read handlers", func(t *testing.T) { + m := &Messenger{} + h := &handlersCalls{} + + handler := func(_ Read, r *Response) { + h.read++ + assert.NotNil(t, r) + } + + messages := []MessageInfo{ + { + Sender: Sender{111}, + Recipient: Recipient{222}, + // 2018-11-24 21:31:51 UTC + 999ms + Timestamp: 1543095111999, + Read: &Read{}, + }, + } + + // First handler + m.HandleRead(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{read: 1}) + + // Another handler + m.HandleRead(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{read: 3}) + }) + + t.Run("postback handlers", func(t *testing.T) { + m := &Messenger{} + h := &handlersCalls{} + + handler := func(msg PostBack, r *Response) { + h.postback++ + assert.NotNil(t, r) + assert.EqualValues(t, 111, msg.Sender.ID) + assert.EqualValues(t, 222, msg.Recipient.ID) + assert.Equal(t, time.Unix(1543095111, 0), msg.Time) + } + + messages := []MessageInfo{ + { + Sender: Sender{111}, + Recipient: Recipient{222}, + // 2018-11-24 21:31:51 UTC + 999ms + Timestamp: 1543095111999, + PostBack: &PostBack{}, + }, + } + + // First handler + m.HandlePostBack(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{postback: 1}) + + // Another handler + m.HandlePostBack(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{postback: 3}) + }) + + t.Run("optin handlers", func(t *testing.T) { + m := &Messenger{} + h := &handlersCalls{} + + handler := func(msg OptIn, r *Response) { + h.optin++ + assert.NotNil(t, r) + assert.EqualValues(t, 111, msg.Sender.ID) + assert.EqualValues(t, 222, msg.Recipient.ID) + assert.Equal(t, time.Unix(1543095111, 0), msg.Time) + } + + messages := []MessageInfo{ + { + Sender: Sender{111}, + Recipient: Recipient{222}, + // 2018-11-24 21:31:51 UTC + 999ms + Timestamp: 1543095111999, + OptIn: &OptIn{}, + }, + } + + // First handler + m.HandleOptIn(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{optin: 1}) + + // Another handler + m.HandleOptIn(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{optin: 3}) + }) + + t.Run("referral handlers", func(t *testing.T) { + m := &Messenger{} + h := &handlersCalls{} + + handler := func(msg ReferralMessage, r *Response) { + h.referral++ + assert.NotNil(t, r) + assert.EqualValues(t, 111, msg.Sender.ID) + assert.EqualValues(t, 222, msg.Recipient.ID) + assert.Equal(t, time.Unix(1543095111, 0), msg.Time) + } + + messages := []MessageInfo{ + { + Sender: Sender{111}, + Recipient: Recipient{222}, + // 2018-11-24 21:31:51 UTC + 999ms + Timestamp: 1543095111999, + ReferralMessage: &ReferralMessage{}, + }, + } + + // First handler + m.HandleReferral(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{referral: 1}) + + // Another handler + m.HandleReferral(handler) + + m.dispatch(newReceive(messages)) + assertHandlersCalls(t, h, handlersCalls{referral: 3}) + }) +}