Skip to content

Commit

Permalink
GH-88 Add settings command to toggle daily reminders (#90)
Browse files Browse the repository at this point in the history
* GH-88 Add settings command to toggle daily reminders

* settings summary command testcases

Co-authored-by: Mattermod <[email protected]>
  • Loading branch information
openmohan and mattermod authored Jul 30, 2020
1 parent ff178b2 commit bb127b1
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 2 deletions.
53 changes: 52 additions & 1 deletion server/command.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"errors"
"fmt"
"regexp"
"strings"
Expand Down Expand Up @@ -42,6 +43,11 @@ send [user] [message]
example: /todo send @awesomePerson Don't forget to be awesome
settings summary [on, off]
Sets user preference on daily reminders
example: /todo settings summary on
help
Display usage.
`
Expand Down Expand Up @@ -93,6 +99,8 @@ func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo
handler = p.runPopCommand
case "send":
handler = p.runSendCommand
case "settings":
handler = p.runSettingsCommand
default:
p.postCommandResponse(args, getHelp())
return &model.CommandResponse{}, nil
Expand Down Expand Up @@ -269,8 +277,42 @@ func (p *Plugin) runPopCommand(args []string, extra *model.CommandArgs) (bool, e
return false, nil
}

func (p *Plugin) runSettingsCommand(args []string, extra *model.CommandArgs) (bool, error) {
if len(args) != 2 {
p.postCommandResponse(extra, "invalid number of arguments")
return true, errors.New("invalid number of arguments")
}

if args[0] == "summary" {
var responseMessage string
var err error

switch args[1] {
case "on":
err = p.saveReminderPreference(extra.UserId, true)
case "off":
err = p.saveReminderPreference(extra.UserId, false)
default:
responseMessage = `invalid input, allowed values for "settings summary" are [on] or [off]"`
p.postCommandResponse(extra, responseMessage)
return true, errors.New("invalid argument")
}

if err != nil {
responseMessage = "error saving the reminder preference"
p.postCommandResponse(extra, responseMessage)
return false, err
}

responseMessage = fmt.Sprintf("reminder preference changed to %s", args[1])
p.postCommandResponse(extra, responseMessage)
}

return false, nil
}

func getAutocompleteData() *model.AutocompleteData {
todo := model.NewAutocompleteData("todo", "[command]", "Available commands: list, add, pop, send, help")
todo := model.NewAutocompleteData("todo", "[command]", "Available commands: list, add, pop, send, settings, help")

add := model.NewAutocompleteData("add", "[message]", "Adds a Todo")
add.AddTextArgument("E.g. be awesome", "[message]", "")
Expand All @@ -297,6 +339,15 @@ func getAutocompleteData() *model.AutocompleteData {
send.AddTextArgument("Todo message", "[message]", "")
todo.AddCommand(send)

settings := model.NewAutocompleteData("settings", "summary [on] [off]", "Sets the user settings")
summary := model.NewAutocompleteData("summary", "[on] [off]", "Sets the summary settings")
on := model.NewAutocompleteData("on", "", "sets the daily reminder to enable")
off := model.NewAutocompleteData("off", "", "sets the daily reminder to disable")
summary.AddCommand(on)
summary.AddCommand(off)
settings.AddCommand(summary)
todo.AddCommand(settings)

help := model.NewAutocompleteData("help", "", "Display usage")
todo.AddCommand(help)
return todo
Expand Down
80 changes: 80 additions & 0 deletions server/command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package main

import (
"testing"

"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/plugin/plugintest"
"github.com/stretchr/testify/mock"
)

func TestSetttingsCommand(t *testing.T) {
api := &plugintest.API{}
api.On("SendEphemeralPost", mock.AnythingOfType("string"), mock.Anything).Return(nil)
api.On("KVSet", mock.AnythingOfType("string"), mock.Anything).Return(nil)

apiKVSetFailed := &plugintest.API{}
apiKVSetFailed.On("SendEphemeralPost", mock.AnythingOfType("string"), mock.Anything).Return(nil)
apiKVSetFailed.On("KVSet", mock.AnythingOfType("string"), mock.Anything).Return(model.NewAppError("failed", "", nil, "", 400))

tests := []struct {
name string
api *plugintest.API
args []string
wantErr bool
want bool
}{
{
name: "Setting summary successful",
api: api,
args: []string{"summary", "on"},
wantErr: false,
want: false,
},
{
name: "Setting summary failed due to KVSet failed",
api: apiKVSetFailed,
args: []string{"summary", "on"},
wantErr: true,
want: false,
},
{
name: "Setting summary failed due to invalid number of arguments",
api: api,
args: []string{"summary", "on", "extraValue"},
wantErr: true,
want: true,
},
{
name: "Setting summary failed due to no arguments",
api: api,
args: []string{},
wantErr: true,
want: true,
},
{
name: "Setting summary failed due to invalid argument",
api: api,
args: []string{"summary", "test"},
wantErr: true,
want: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
plugin := Plugin{}
plugin.SetAPI(tt.api)

resp, err := plugin.runSettingsCommand(tt.args, &model.CommandArgs{})
if tt.wantErr != (err != nil) {
t.Errorf("runSettingsCommand wantErr= %v got err= %v", tt.wantErr, err)
return
}

if tt.want != resp {
t.Errorf("runSettingsCommand got= %v want= %v", resp, tt.want)
}
})
}
}
2 changes: 1 addition & 1 deletion server/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) {
return
}

if len(issues) > 0 && r.URL.Query().Get("reminder") == "true" {
if len(issues) > 0 && r.URL.Query().Get("reminder") == "true" && p.getReminderPreference(userID) {
var lastReminderAt int64
lastReminderAt, err = p.getLastReminderTimeForUser(userID)
if err != nil {
Expand Down
37 changes: 37 additions & 0 deletions server/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const (
StoreIssueKey = "item"
// StoreReminderKey is the key used to store the last time a user was reminded
StoreReminderKey = "reminder"
// StoreReminderEnabledKey is the key used to store the user preference of auto daily reminder
StoreReminderEnabledKey = "reminder_enabled"
)

// IssueRef denotes every element in any of the lists. Contains the issue that refers to,
Expand All @@ -42,6 +44,10 @@ func reminderKey(userID string) string {
return fmt.Sprintf("%s_%s", StoreReminderKey, userID)
}

func reminderEnabledKey(userID string) string {
return fmt.Sprintf("%s_%s", StoreReminderEnabledKey, userID)
}

type listStore struct {
api plugin.API
}
Expand Down Expand Up @@ -378,3 +384,34 @@ func (p *Plugin) getLastReminderTimeForUser(userID string) (int64, error) {

return reminderAt, nil
}

func (p *Plugin) saveReminderPreference(userID string, preference bool) error {
preferenceString := strconv.FormatBool(preference)
appErr := p.API.KVSet(reminderEnabledKey(userID), []byte(preferenceString))
if appErr != nil {
return appErr
}
return nil
}

// getReminderPreference - gets user preference on reminder - default value will be true if in case any error
func (p *Plugin) getReminderPreference(userID string) bool {
preferenceByte, appErr := p.API.KVGet(reminderEnabledKey(userID))
if appErr != nil {
p.API.LogError("error getting the reminder preference, err=", appErr.Error())
return true
}

if preferenceByte == nil {
p.API.LogInfo(`reminder preference is empty. Defaulting to "on"`)
return true
}

preference, err := strconv.ParseBool(string(preferenceByte))
if err != nil {
p.API.LogError("unable to parse the reminder preference, err=", err.Error())
return true
}

return preference
}

0 comments on commit bb127b1

Please sign in to comment.