Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept any action type #73

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions core/activity/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,18 @@ import (

// Handler acts as the interface for the client program to define actions on various events from connector service.
type Handler interface {
OnMessage(context *TurnContext) (schema.Activity, error)
OnInvoke(context *TurnContext) (schema.Activity, error)
OnConversationUpdate(context *TurnContext) (schema.Activity, error)
On(context *TurnContext) (schema.Activity, error)
}

// HandlerFuncsMap is an adaptor to let client program handler functions
// for all activity types, including not supported by HandlerFuncs adaptor
type HandlerFuncsMap map[schema.ActivityTypes]func(turn *TurnContext) (schema.Activity, error)

func (hf HandlerFuncsMap) On(context *TurnContext) (schema.Activity, error) {
if handler, ok := hf[context.Activity.Type]; ok {
return handler(context)
}
return schema.Activity{}, fmt.Errorf("Activity type %s not supported", context.Activity.Type)
}

// HandlerFuncs is an adaptor to let client program specify as many or
Expand All @@ -42,6 +51,18 @@ type HandlerFuncs struct {
OnConversationUpdateFunc func(turn *TurnContext) (schema.Activity, error)
}

func (r HandlerFuncs) On(context *TurnContext) (schema.Activity, error) {
switch context.Activity.Type {
case schema.Message:
return r.OnMessage(context)
case schema.Invoke:
return r.OnInvoke(context)
case schema.ConversationUpdate:
return r.OnConversationUpdate(context)
}
return schema.Activity{}, fmt.Errorf("Activity type %s not supported yet", context.Activity.Type)
}

// OnMessage handles a 'message' event from connector service.
func (r HandlerFuncs) OnMessage(turn *TurnContext) (schema.Activity, error) {
if r.OnMessageFunc != nil {
Expand Down Expand Up @@ -69,13 +90,5 @@ func (r HandlerFuncs) OnInvoke(turn *TurnContext) (schema.Activity, error) {
// PrepareActivityContext routes the received Activity to respective handler function.
// Returns the result of the handler function.
func PrepareActivityContext(handler Handler, context *TurnContext) (schema.Activity, error) {
switch context.Activity.Type {
case schema.Message:
return handler.OnMessage(context)
case schema.Invoke:
return handler.OnInvoke(context)
case schema.ConversationUpdate:
return handler.OnConversationUpdate(context)
}
return schema.Activity{}, fmt.Errorf("Activity type %s not supported yet", context.Activity.Type)
return handler.On(context)
}
98 changes: 98 additions & 0 deletions core/bot_framework_adapter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,101 @@ func TestActivityUpdate(t *testing.T) {
handler.ServeHTTP(rr, req)
assert.Equal(t, rr.Code, 200, "Expect 200 response status")
}

func TestActivityCustom(t *testing.T) {
srv := serverMock(t)

type args struct {
Activity schema.Activity
Handler activity.Handler
}

tests := []struct {
name string
args args
wantErr bool
}{
{
args: args{
Activity: schema.Activity{
Type: schema.InstallationUpdate,
Conversation: schema.ConversationAccount{
ID: "abcd1234",
Name: "Convo1",
},
MembersAdded: []schema.ChannelAccount{
{
ID: "123456",
Name: "Some member name",
Role: schema.BOT,
},
},
Text: "Message from Teams Client",
ReplyToID: "5d5cdc723",
ServiceURL: srv.URL,
},
Handler: activity.HandlerFuncsMap{
schema.InstallationUpdate: func(turn *activity.TurnContext) (schema.Activity, error) {
return turn.SendActivity(activity.MsgOptionText("supported"))
},
},
},
},
{
args: args{
Activity: schema.Activity{
Type: schema.InstallationUpdate,
Conversation: schema.ConversationAccount{
ID: "abcd1234",
Name: "Convo1",
},
MembersAdded: []schema.ChannelAccount{
{
ID: "123456",
Name: "Some member name",
Role: schema.BOT,
},
},
Text: "Message from Teams Client",
ReplyToID: "5d5cdc723",
ServiceURL: srv.URL,
},
Handler: activity.HandlerFuncs{},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := context.Background()
setting := core.AdapterSetting{
AppID: "asdasd",
AppPassword: "cfg.MicrosoftTeams.AppPassword",
}
setting.CredentialProvider = auth.SimpleCredentialProvider{
AppID: setting.AppID,
Password: setting.AppPassword,
}
clientConfig, err := client.NewClientConfig(setting.CredentialProvider, auth.ToChannelFromBotLoginURL[0])
assert.Nil(t, err, fmt.Sprintf("Failed with error %s", err))
connectorClient, err := client.NewClient(clientConfig)
assert.Nil(t, err, fmt.Sprintf("Failed with error %s", err))
adapter := core.BotFrameworkAdapter{setting, &core.MockTokenValidator{}, connectorClient}
act, err := adapter.ParseRequest(ctx, req)

err = adapter.ProcessActivity(ctx, act, tt.args.Handler)
assert.True(t, (err != nil) == tt.wantErr, fmt.Sprintf("Failed with error %s", err))
})
rr := httptest.NewRecorder()
bodyJSON, err := json.Marshal(tt.args.Activity)
assert.Nil(t, err, fmt.Sprintf("Failed with error %s", err))
bodyBytes := bytes.NewReader(bodyJSON)
req, err := http.NewRequest(http.MethodPost, "/api/messages", bodyBytes)
assert.Nil(t, err, fmt.Sprintf("Failed with error %s", err))
req.Header.Set("Authorization", "Bearer abc123")
handler.ServeHTTP(rr, req)
assert.Equal(t, rr.Code, 200, "Expect 200 response status")
})
}
}